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"
|