File: GhciWrapperSpec.hs

package info (click to toggle)
haskell-doctest-parallel 0.3.1.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 652 kB
  • sloc: haskell: 3,241; makefile: 6; ansic: 4
file content (111 lines) | stat: -rw-r--r-- 4,530 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
{-# LANGUAGE CPP #-}

module GhciWrapperSpec (main, spec) where

import           Test.Hspec
import           System.IO.Silently

import           Control.Exception
import           Data.List (isInfixOf)

import           Test.DocTest.Internal.GhciWrapper (Interpreter, Config(..), defaultConfig)
import qualified Test.DocTest.Internal.GhciWrapper as Interpreter
import           Test.DocTest.Internal.Logging (noLogger)

main :: IO ()
main = hspec spec

withInterpreterConfig :: Config -> (Interpreter -> IO a) -> IO a
withInterpreterConfig config = bracket (Interpreter.new noLogger config []) Interpreter.close

withInterpreter :: ((String -> IO String) -> IO a) -> IO a
withInterpreter action = withInterpreterConfig defaultConfig $ action . Interpreter.eval

spec :: Spec
spec = do
  describe "evalEcho" $ do
    it "prints result to stdout" $ do
      withInterpreterConfig defaultConfig $ \ghci -> do
        (capture $ Interpreter.evalEcho ghci ("putStr" ++ show "foo\nbar")) `shouldReturn` ("foo\nbar", "foo\nbar")

  describe "evalIt" $ do
    it "preserves it" $ do
      withInterpreterConfig defaultConfig $ \ghci -> do
        Interpreter.evalIt ghci "23" `shouldReturn` "23\n"
        Interpreter.eval ghci "it" `shouldReturn` "23\n"

  describe "eval" $ do
    it "shows literals" $ withInterpreter $ \ghci -> do
      ghci "23" `shouldReturn` "23\n"

    it "shows string literals containing Unicode" $ withInterpreter $ \ghci -> do
      ghci "\"λ\"" `shouldReturn` "\"\\955\"\n"

    it "evaluates simple expressions" $ withInterpreter $ \ghci -> do
      ghci "23 + 42" `shouldReturn` "65\n"

    it "supports let bindings" $ withInterpreter $ \ghci -> do
      ghci "let x = 10" `shouldReturn` ""
      ghci "x" `shouldReturn` "10\n"

    it "allows import statements" $ withInterpreter $ \ghci -> do
      ghci "import Data.Maybe" `shouldReturn` ""
      ghci "fromJust (Just 20)" `shouldReturn` "20\n"

    it "captures stdout" $ withInterpreter $ \ghci -> do
      ghci "putStr \"foo\"" `shouldReturn` "foo"

    it "captures stdout (Unicode)" $ withInterpreter $ \ghci -> do
      ghci "putStrLn \"λ\"" `shouldReturn` "λ\n"

    it "captures stdout (empty line)" $ withInterpreter $ \ghci -> do
      ghci "putStrLn \"\"" `shouldReturn` "\n"

    it "captures stdout (multiple lines)" $ withInterpreter $ \ghci -> do
      ghci "putStrLn \"foo\" >> putStrLn \"bar\" >> putStrLn \"baz\""
        `shouldReturn` "foo\nbar\nbaz\n"

    it "captures stderr" $ withInterpreter $ \ghci -> do
      ghci "import System.IO" `shouldReturn` ""
      ghci "hPutStrLn stderr \"foo\"" `shouldReturn` "foo\n"

    it "captures stderr (Unicode)" $ withInterpreter $ \ghci -> do
      ghci "import System.IO" `shouldReturn` ""
      ghci "hPutStrLn stderr \"λ\"" `shouldReturn` "λ\n"

    it "shows exceptions" $ withInterpreter $ \ghci -> do
      ghci "import Control.Exception" `shouldReturn` ""
      ghci "throwIO DivideByZero" `shouldReturn` "*** Exception: divide by zero\n"

    it "shows exceptions (ExitCode)" $ withInterpreter $ \ghci -> do
      ghci "import System.Exit" `shouldReturn` ""
      ghci "exitWith $ ExitFailure 10" `shouldReturn` "*** Exception: ExitFailure 10\n"

    it "gives an error message for identifiers that are not in scope" $ withInterpreter $ \ghci -> do
#if __GLASGOW_HASKELL__ >= 800
      ghci "foo" >>= (`shouldSatisfy` isInfixOf "Variable not in scope: foo")
#else
      ghci "foo" >>= (`shouldSatisfy` isSuffixOf "Not in scope: \8216foo\8217\n")
#endif
    context "when configVerbose is True" $ do
      it "prints prompt" $ do
        withInterpreterConfig defaultConfig{configVerbose = True} $ \ghci -> do
          Interpreter.eval ghci "print 23" >>= (`shouldSatisfy`
            (`elem` [ "Prelude> 23\nPrelude> "
                    ,  "ghci> 23\nghci> "
                    ]))

    context "with -XOverloadedStrings, -Wall and -Werror" $ do
      it "does not fail on marker expression (bug fix)" $ withInterpreter $ \ghci -> do
        ghci ":set -XOverloadedStrings -Wall -Werror" `shouldReturn` ""
        ghci "putStrLn \"foo\"" `shouldReturn` "foo\n"

    context "with NoImplicitPrelude" $ do
      it "works" $ withInterpreter $ \ghci -> do
        ghci ":set -XNoImplicitPrelude" `shouldReturn` ""
        ghci "putStrLn \"foo\"" `shouldReturn` "foo\n"

    context "with a strange String type" $ do
      it "works" $ withInterpreter $ \ghci -> do
        ghci "type String = Int" `shouldReturn` ""
        ghci "putStrLn \"foo\"" `shouldReturn` "foo\n"