@@ -18,13 +18,30 @@
18{-# LANGUAGE GeneralizedNewtypeDeriving #-}
18{-# LANGUAGE GeneralizedNewtypeDeriving #-}
19{-# LANGUAGE FlexibleInstances #-}
19{-# LANGUAGE FlexibleInstances #-}
21+-- Failing tests can specify the kind of error that should be thrown with a
22+-- @shouldFailWith declaration. For example:
24+-- "-- @shouldFailWith TypesDoNotUnify"
26+-- will cause the test to fail unless that module fails to compile with exactly
27+-- one TypesDoNotUnify error.
29+-- If a module is expected to produce multiple type errors, then use multiple
30+-- @shouldFailWith lines; for example:
32+-- -- @shouldFailWith TypesDoNotUnify
33+-- -- @shouldFailWith TypesDoNotUnify
34+-- -- @shouldFailWith TransitiveExportError
21module Main (main) where
36module Main (main) where
23import qualified Language.PureScript as P
38import qualified Language.PureScript as P
24import qualified Language.PureScript.CodeGen.JS as J
39import qualified Language.PureScript.CodeGen.JS as J
25import qualified Language.PureScript.CoreFn as CF
40import qualified Language.PureScript.CoreFn as CF
27−import Data.List (isSuffixOf)
42+import Data.Char (isSpace)
43+import Data.Maybe (mapMaybe)
44+import Data.List (isSuffixOf, sort, stripPrefix)
28import Data.Traversable (traverse)
45import Data.Traversable (traverse)
29import Data.Time.Clock (UTCTime())
46import Data.Time.Clock (UTCTime())
@@ -33,6 +50,7 @@ import qualified Data.Map as M
33import Control.Monad
50import Control.Monad
34import Control.Monad.IO.Class (liftIO)
51import Control.Monad.IO.Class (liftIO)
35import Control.Applicative
52import Control.Applicative
53+import Control.Arrow ((>>>))
37import Control.Monad.Reader
55import Control.Monad.Reader
38import Control.Monad.Writer
56import Control.Monad.Writer
@@ -146,11 +164,35 @@ assertCompiles inputFiles foreigns = do
147assertDoesNotCompile :: [FilePath] -> M.Map P.ModuleName (FilePath, P.ForeignJS) -> IO ()
165assertDoesNotCompile :: [FilePath] -> M.Map P.ModuleName (FilePath, P.ForeignJS) -> IO ()
148assertDoesNotCompile inputFiles foreigns = do
166assertDoesNotCompile inputFiles foreigns = do
167+ let testFile = last inputFiles
149− putStrLn $ "Assert " ++ last inputFiles ++ " does not compile"
168+ putStrLn $ "Assert " ++ testFile ++ " does not compile"
169+ shouldFailWith <- getShouldFailWith testFile
150 assert inputFiles foreigns $ \e ->
170 assert inputFiles foreigns $ \e ->
151 case e of
171 case e of
152− Left errs -> putStrLn (P.prettyPrintMultipleErrors False errs) >> return Nothing
173+ putStrLn (P.prettyPrintMultipleErrors False errs)
174+ if null shouldFailWith
176+ else return $ checkShouldFailWith shouldFailWith errs
153− Right _ -> return $ Just "Should not have compiled"
178+ return $ Just "Should not have compiled"
184+ >>> mapMaybe (stripPrefix "-- @shouldFailWith ")
188+ checkShouldFailWith expected errs =
189+ let actual = map P.errorCode $ P.runMultipleErrors errs
190+ in if sort expected == sort actual
192+ else Just $ "Expected these errors: " ++ show expected ++ ", but got these: " ++ show actual
195+ dropWhile isSpace >>> reverse >>> dropWhile isSpace >>> reverse
155findNodeProcess :: IO (Maybe String)
197findNodeProcess :: IO (Maybe String)
156findNodeProcess = runMaybeT . msum $ map (MaybeT . findExecutable) names
198findNodeProcess = runMaybeT . msum $ map (MaybeT . findExecutable) names