git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Merge pull request #1323 from hdgarrood/should-fail-with

Check the right kind of error is thrown in tests

commit464af8e3c2e40c23868aeffb4ded6dc8136200a2 authorPhil Freeman <paf31@cantab.net> dateSun 2 Aug 2015, 17:24 (11 years ago) parenteadd1dad8e46b0
66 files changed+169−44
examples/failing/365.purs+1 examples/failing/438.purs+6−2 examples/failing/ArrayType.purs+2 examples/failing/Arrays.purs+3 examples/failing/CaseDoesNotMatchAllConstructorArgs.purs+1 examples/failing/Do.purs+2 examples/failing/DoNotSuggestComposition.purs+3 examples/failing/DoNotSuggestComposition2.purs+4 examples/failing/DuplicateDeclarationsInLet.purs+1 examples/failing/DuplicateProperties1.purs+1 examples/failing/DuplicateProperties2.purs+1 examples/failing/DuplicateTypeVars.purs+1 examples/failing/Eff.purs+1 examples/failing/ExtraRecordField.purs+2−1 examples/failing/Foldable.purs+1 examples/failing/InstanceExport.purs+2 examples/failing/KindError.purs+1 examples/failing/LeadingZeros1.purs+1 examples/failing/LeadingZeros2.purs+1 examples/failing/Let.purs+1 examples/failing/MPTCs.purs+1 examples/failing/MissingClassExport.purs+1 examples/failing/MissingClassMemberExport.purs+1 examples/failing/MissingRecordField.purs+2−1 examples/failing/MultipleErrors.purs+4−2 examples/failing/MultipleErrors2.purs+2 examples/failing/MutRec.purs+1 examples/failing/MutRec2.purs+1 examples/failing/NewtypeMultiArgs.purs+1 examples/failing/NewtypeMultiCtor.purs+1 examples/failing/NoOverlap.purs−13 examples/failing/NullaryAbs.purs+1 examples/failing/Object.purs+1 examples/failing/OverlappingArguments.purs+1 examples/failing/OverlappingBinders.purs+1 examples/failing/OverlappingInstances.purs+1 examples/failing/OverlappingInstances2.purs+5−6 examples/failing/OverlappingVars.purs+1 examples/failing/Rank2Types.purs+1 examples/failing/Reserved.purs+1 examples/failing/RowConstructors1.purs+1 examples/failing/RowConstructors2.purs+1 examples/failing/RowConstructors3.purs+1 examples/failing/SkolemEscape.purs+1 examples/failing/SkolemEscape2.purs+1 examples/failing/SuggestComposition.purs+2 examples/failing/Superclasses1.purs+1 examples/failing/Superclasses2.purs+2 examples/failing/Superclasses3.purs+1 examples/failing/Superclasses4.purs+2−1 examples/failing/TopLevelCaseNoArgs.purs+1 examples/failing/TypeClassInstances.purs+1 examples/failing/TypeClasses2.purs+1 examples/failing/TypeError.purs+1 examples/failing/TypeSynonyms.purs+1 examples/failing/TypeSynonyms2.purs+1 examples/failing/TypeSynonyms3.purs+1 examples/failing/TypeSynonyms4.purs+1 examples/failing/TypeSynonyms5.purs+1 examples/failing/TypeWildcards1.purs+1 examples/failing/TypeWildcards2.purs+1 examples/failing/TypeWildcards3.purs+1 examples/failing/UnderscoreModuleName.purs+1 examples/failing/UnifyInTypeInstanceLookup.purs+3 examples/failing/UnknownType.purs+1 tests/Main.hs+75−18
examples/failing/365.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith CycleInDeclaration
12module Main where
23
34import Prelude
examples/failing/438.purs+6−2
@@ -1,3 +1,8 @@
1+-- @shouldFailWith NoInstanceFound
2+
3+-- See issue 438 for details: this test is mainly here to test that code like
4+-- this doesn't cause the compiler to loop.
5+
16module Main where
27
38import Prelude
@@ -5,7 +10,6 @@ import Prelude
510data Fix f = In (f (Fix f))
611
712instance eqFix :: (Eq (f (Fix f))) => Eq (Fix f) where
8− (==) (In f) (In g) = f == g
9− (/=) a b = not (a == b)
13+ eq (In f) (In g) = f == g
1014
1115example = In [] == In []
examples/failing/ArrayType.purs+2
@@ -1,3 +1,5 @@
1+-- @shouldFailWith TypesDoNotUnify
2+
13module Main where
24
35import Prelude
examples/failing/Arrays.purs+3
@@ -1,5 +1,8 @@
1+-- @shouldFailWith ExprDoesNotHaveType
12module Main where
23
34import Prelude
45
6+foreign import (!!) :: forall a. Array a -> Int -> a
7+
58test = \arr -> arr !! (0 !! 0)
examples/failing/CaseDoesNotMatchAllConstructorArgs.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith IncorrectConstructorArity
12module Main where
23
34import Prelude
examples/failing/Do.purs+2
@@ -1,3 +1,5 @@
1+-- @shouldFailWith InvalidDoBind
2+-- @shouldFailWith InvalidDoLet
13module Main where
24
35import Prelude
examples/failing/DoNotSuggestComposition.purs+3
@@ -1,3 +1,6 @@
1+-- @shouldFailWith TypesDoNotUnify
2+-- TODO: Check that this does not produce a "function composition is (<<<)"
3+-- suggestion.
14module DoNotSuggestComposition where
25
36import Prelude
examples/failing/DoNotSuggestComposition2.purs+4
@@ -1,3 +1,7 @@
1+-- @shouldFailWith CannotApplyFunction
2+-- TODO: Check that this does not produce a "function composition is (<<<)"
3+-- suggestion.
4+
15module DoNotSuggestComposition2 where
26
37foo = let x = { y: 3 } in x 2
examples/failing/DuplicateDeclarationsInLet.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith OverlappingNamesInLet
12module Main where
23
34import Prelude
examples/failing/DuplicateProperties1.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith TypesDoNotUnify
12module DuplicateProperties where
23
34import Prelude
examples/failing/DuplicateProperties2.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith DuplicateLabel
12module DuplicateProperties where
23
34import Prelude
examples/failing/DuplicateTypeVars.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith DuplicateTypeArgument
12module Main where
23
34import Prelude
examples/failing/Eff.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith TypesDoNotUnify
12module Main where
23
34import Prelude
examples/failing/ExtraRecordField.purs+2−1
@@ -1,4 +1,5 @@
1−
1+-- @shouldFailWith PropertyIsMissing
2+-- TODO: Make this fail with a new error ExtraProperty instead.
23module ExtraRecordField where
34
45import Prelude ((<>))
examples/failing/Foldable.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith CycleInDeclaration
12module Main where
23
34import Prelude
examples/failing/InstanceExport.purs+2
@@ -1,3 +1,4 @@
1+-- @shouldFailWith TransitiveExportError
12module InstanceExport (S(..), f) where
23
34import Prelude
@@ -13,5 +14,6 @@ instance fs :: F S where
1314module Test where
1415
1516import InstanceExport
17+import Prelude
1618
1719test = f $ S "Test"
examples/failing/KindError.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith KindsDoNotUnify
12module Main where
23
34import Prelude
examples/failing/LeadingZeros1.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith ErrorParsingModule
12module Main where
23
34import Prelude
examples/failing/LeadingZeros2.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith ErrorParsingModule
12module Main where
23
34import Prelude
examples/failing/Let.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith CycleInDeclaration
12module Main where
23
34import Prelude
examples/failing/MPTCs.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith KindsDoNotUnify
12module Main where
23
34import Prelude
examples/failing/MissingClassExport.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith TransitiveExportError
12module Test (bar) where
23
34import Prelude
examples/failing/MissingClassMemberExport.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith TransitiveExportError
12module Test (Foo) where
23
34import Prelude
examples/failing/MissingRecordField.purs+2−1
@@ -1,4 +1,5 @@
1−
1+-- @shouldFailWith TypesDoNotUnify
2+-- TODO: Update type checker to make this fail with PropertyIsMissing instead.
23module MissingRecordField where
34
45import Prelude ((>))
examples/failing/MultipleErrors.purs+4−2
@@ -1,11 +1,13 @@
1+-- @shouldFailWith ExprDoesNotHaveType
2+-- @shouldFailWith ExprDoesNotHaveType
13module MultipleErrors where
24
35import Prelude
46
5−foo :: Number -> Number
7+foo :: Int -> Int
68foo 0 = "Test"
79foo n = bar (n - 1)
810
9−bar :: Number -> Number
11+bar :: Int -> Int
1012bar 0 = "Test"
1113bar n = foo (n - 1)
examples/failing/MultipleErrors2.purs+2
@@ -1,3 +1,5 @@
1+-- @shouldFailWith UnknownValue
2+-- @shouldFailWith UnknownValue
13module MultipleErrors2 where
24
35import Prelude
examples/failing/MutRec.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith CycleInDeclaration
12module MutRec where
23
34import Prelude
examples/failing/MutRec2.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith CycleInDeclaration
12module Main where
23
34import Prelude
examples/failing/NewtypeMultiArgs.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith InvalidNewtype
12module Main where
23
34import Prelude
examples/failing/NewtypeMultiCtor.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith InvalidNewtype
12module Main where
23
34import Prelude
examples/failing/NoOverlap.pursdeleted−13
@@ -1,13 +0,0 @@
1−module Main where
2−
3−import Prelude
4−
5−data Foo = Foo
6−
7−instance showFoo1 :: Show Foo where
8− show _ = "Foo"
9−
10−instance showFoo2 :: Show Foo where
11− show _ = "Bar"
12−
13−test = show Foo
examples/failing/NullaryAbs.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith ErrorParsingModule
12module Main where
23
34import Prelude
examples/failing/Object.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith PropertyIsMissing
12module Main where
23
34import Prelude
examples/failing/OverlappingArguments.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith OverlappingArgNames
12module OverlappingArguments where
23
34import Prelude
examples/failing/OverlappingBinders.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith OverlappingArgNames
12module OverlappingBinders where
23
34import Prelude
examples/failing/OverlappingInstances.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith OverlappingInstances
12module OverlappingInstances where
23
34import Prelude
examples/failing/OverlappingInstances2.purs+5−6
@@ -1,3 +1,4 @@
1+-- @shouldFailWith OverlappingInstances
12module OverlappingInstances where
23
34import Prelude
@@ -5,14 +6,12 @@ import Prelude
56data A = A | B
67
78instance eqA1 :: Eq A where
8− (==) A A = true
9− (==) B B = true
10− (==) _ _ = false
11− (/=) x y = not (x == y)
9+ eq A A = true
10+ eq B B = true
11+ eq _ _ = false
1212
1313instance eqA2 :: Eq A where
14− (==) _ _ = true
15− (/=) _ _ = false
14+ eq _ _ = true
1615
1716instance ordA :: Ord A where
1817 compare A B = LT
examples/failing/OverlappingVars.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith NoInstanceFound
12module Main where
23
34import Prelude
examples/failing/Rank2Types.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith ExprDoesNotHaveType
12module Main where
23
34import Prelude
examples/failing/Reserved.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith ErrorParsingModule
12module Main where
23
34import Prelude
examples/failing/RowConstructors1.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith KindsDoNotUnify
12module Main where
23
34import Prelude
examples/failing/RowConstructors2.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith KindsDoNotUnify
12module Main where
23
34import Prelude
examples/failing/RowConstructors3.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith KindsDoNotUnify
12module Main where
23
34import Prelude
examples/failing/SkolemEscape.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith EscapedSkolem
12module Main where
23
34import Prelude
examples/failing/SkolemEscape2.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith EscapedSkolem
12module Main where
23
34import Prelude
examples/failing/SuggestComposition.purs+2
@@ -1,3 +1,5 @@
1+-- @shouldFailWith TypesDoNotUnify
2+-- TODO: Ensure the correct suggestion is produced.
13module SuggestComposition where
24
35import Prelude
examples/failing/Superclasses1.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith NoInstanceFound
12module Main where
23
34import Prelude
examples/failing/Superclasses2.purs+2
@@ -1,3 +1,5 @@
1+-- @shouldFailWith CycleInTypeSynonym
2+-- TODO: Should this have its own error, perhaps CycleInTypeClassDeclaration?
13module CycleInSuperclasses where
24
35import Prelude
examples/failing/Superclasses3.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith UndefinedTypeVariable
12module UnknownSuperclassTypeVar where
23
34import Prelude
examples/failing/Superclasses4.purs+2−1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith OverlappingInstances
12module OverlappingInstances where
23
34import Prelude
@@ -11,4 +12,4 @@ instance foo2 :: Foo Number
1112test :: forall a. (Foo a) => a -> a
1213test a = a
1314
14−test1 = test 0
15+test1 = test 0.0
examples/failing/TopLevelCaseNoArgs.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith DuplicateValueDeclaration
12module Main where
23
34import Prelude
examples/failing/TypeClassInstances.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith MissingClassMember
12module Main where
23
34import Prelude
examples/failing/TypeClasses2.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith NoInstanceFound
12module Main where
23
34import Prelude ()
examples/failing/TypeError.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith ExprDoesNotHaveType
12module Main where
23
34import Prelude
examples/failing/TypeSynonyms.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith CycleInTypeSynonym
12module Main where
23
34import Prelude
examples/failing/TypeSynonyms2.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith TypeSynonymInstance
12module Main where
23
34import Prelude
examples/failing/TypeSynonyms3.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith TypeSynonymInstance
12module Main where
23
34import Prelude
examples/failing/TypeSynonyms4.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith PartiallyAppliedSynonym
12module TypeSynonyms4 where
23
34import Prelude
examples/failing/TypeSynonyms5.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith CycleInTypeSynonym
12module Main where
23
34import Prelude
examples/failing/TypeWildcards1.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith ErrorParsingModule
12module TypeWildcards where
23
34import Prelude
examples/failing/TypeWildcards2.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith ErrorParsingModule
12module TypeWildcards where
23
34import Prelude
examples/failing/TypeWildcards3.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith ErrorParsingModule
12module TypeWildcards where
23
34import Prelude
examples/failing/UnderscoreModuleName.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith ErrorParsingModule
12module Bad_Module where
23
34import Prelude
examples/failing/UnifyInTypeInstanceLookup.purs+3
@@ -1,3 +1,6 @@
1+-- @shouldFailWith NoInstanceFound
2+-- See issue #390.
3+-- TODO: Improve this error.
14module Main where
25
36import Prelude
examples/failing/UnknownType.purs+1
@@ -1,3 +1,4 @@
1+-- @shouldFailWith UnknownType
12module Main where
23
34import Prelude
tests/Main.hs+75−18
@@ -18,13 +18,30 @@
1818{-# LANGUAGE GeneralizedNewtypeDeriving #-}
1919{-# LANGUAGE FlexibleInstances #-}
2020
21+-- Failing tests can specify the kind of error that should be thrown with a
22+-- @shouldFailWith declaration. For example:
23+--
24+-- "-- @shouldFailWith TypesDoNotUnify"
25+--
26+-- will cause the test to fail unless that module fails to compile with exactly
27+-- one TypesDoNotUnify error.
28+--
29+-- If a module is expected to produce multiple type errors, then use multiple
30+-- @shouldFailWith lines; for example:
31+--
32+-- -- @shouldFailWith TypesDoNotUnify
33+-- -- @shouldFailWith TypesDoNotUnify
34+-- -- @shouldFailWith TransitiveExportError
35+
2136module Main (main) where
2237
2338import qualified Language.PureScript as P
2439import qualified Language.PureScript.CodeGen.JS as J
2540import qualified Language.PureScript.CoreFn as CF
2641
27−import Data.List (isSuffixOf)
42+import Data.Char (isSpace)
43+import Data.Maybe (mapMaybe, fromMaybe)
44+import Data.List (isSuffixOf, sort, stripPrefix)
2845import Data.Traversable (traverse)
2946import Data.Time.Clock (UTCTime())
3047
@@ -33,6 +50,7 @@ import qualified Data.Map as M
3350import Control.Monad
3451import Control.Monad.IO.Class (liftIO)
3552import Control.Applicative
53+import Control.Arrow ((>>>))
3654
3755import Control.Monad.Reader
3856import Control.Monad.Writer
@@ -111,6 +129,8 @@ readInput inputFiles = forM inputFiles $ \inputFile -> do
111129 text <- readFile inputFile
112130 return (inputFile, text)
113131
132+type TestM = WriterT [(FilePath, String)] IO
133+
114134compile :: [FilePath] -> M.Map P.ModuleName (FilePath, P.ForeignJS) -> IO (Either P.MultipleErrors P.Environment)
115135compile inputFiles foreigns = runTest $ do
116136 fs <- liftIO $ readInput inputFiles
@@ -120,17 +140,17 @@ compile inputFiles foreigns = runTest $ do
120140assert :: [FilePath] ->
121141 M.Map P.ModuleName (FilePath, P.ForeignJS) ->
122142 (Either P.MultipleErrors P.Environment -> IO (Maybe String)) ->
123− IO ()
143+ TestM ()
124144assert inputFiles foreigns f = do
125− e <- compile inputFiles foreigns
126− maybeErr <- f e
145+ e <- liftIO $ compile inputFiles foreigns
146+ maybeErr <- liftIO $ f e
127147 case maybeErr of
128− Just err -> putStrLn err >> exitFailure
148+ Just err -> tell [(last inputFiles, err)]
129149 Nothing -> return ()
130150
131−assertCompiles :: [FilePath] -> M.Map P.ModuleName (FilePath, P.ForeignJS) -> IO ()
151+assertCompiles :: [FilePath] -> M.Map P.ModuleName (FilePath, P.ForeignJS) -> TestM ()
132152assertCompiles inputFiles foreigns = do
133− putStrLn $ "Assert " ++ last inputFiles ++ " compiles successfully"
153+ liftIO . putStrLn $ "Assert " ++ last inputFiles ++ " compiles successfully"
134154 assert inputFiles foreigns $ \e ->
135155 case e of
136156 Left errs -> return . Just . P.prettyPrintMultipleErrors False $ errs
@@ -144,13 +164,40 @@ assertCompiles inputFiles foreigns = do
144164 Just (ExitFailure _, _, err) -> return $ Just err
145165 Nothing -> return $ Just "Couldn't find node.js executable"
146166
147−assertDoesNotCompile :: [FilePath] -> M.Map P.ModuleName (FilePath, P.ForeignJS) -> IO ()
167+assertDoesNotCompile :: [FilePath] -> M.Map P.ModuleName (FilePath, P.ForeignJS) -> TestM ()
148168assertDoesNotCompile inputFiles foreigns = do
149− putStrLn $ "Assert " ++ last inputFiles ++ " does not compile"
169+ let testFile = last inputFiles
170+ liftIO . putStrLn $ "Assert " ++ testFile ++ " does not compile"
171+ shouldFailWith <- getShouldFailWith testFile
150172 assert inputFiles foreigns $ \e ->
151173 case e of
152− Left errs -> putStrLn (P.prettyPrintMultipleErrors False errs) >> return Nothing
153− Right _ -> return $ Just "Should not have compiled"
174+ Left errs -> do
175+ putStrLn (P.prettyPrintMultipleErrors False errs)
176+ return $ if null shouldFailWith
177+ then Just $ "shouldFailWith declaration is missing (errors were: "
178+ ++ show (map P.errorCode (P.runMultipleErrors errs))
179+ ++ ")"
180+ else checkShouldFailWith shouldFailWith errs
181+ Right _ ->
182+ return $ Just "Should not have compiled"
183+
184+ where
185+ getShouldFailWith =
186+ readFile
187+ >>> liftIO
188+ >>> fmap ( lines
189+ >>> mapMaybe (stripPrefix "-- @shouldFailWith ")
190+ >>> map trim
191+ )
192+
193+ checkShouldFailWith expected errs =
194+ let actual = map P.errorCode $ P.runMultipleErrors errs
195+ in if sort expected == sort actual
196+ then Nothing
197+ else Just $ "Expected these errors: " ++ show expected ++ ", but got these: " ++ show actual
198+
199+ trim =
200+ dropWhile isSpace >>> reverse >>> dropWhile isSpace >>> reverse
154201
155202findNodeProcess :: IO (Maybe String)
156203findNodeProcess = runMaybeT . msum $ map (MaybeT . findExecutable) names
@@ -172,14 +219,24 @@ main = do
172219 Right (foreigns, _) <- runExceptT $ runWriterT $ P.parseForeignModulesFromFiles foreignFiles
173220
174221 let passing = cwd </> "examples" </> "passing"
175− passingTestCases <- getDirectoryContents passing
176− forM_ passingTestCases $ \inputFile -> when (".purs" `isSuffixOf` inputFile) $
177− assertCompiles (supportPurs ++ [passing </> inputFile]) foreigns
222+ passingTestCases <- sort . filter (".purs" `isSuffixOf`) <$> getDirectoryContents passing
178223 let failing = cwd </> "examples" </> "failing"
179− failingTestCases <- getDirectoryContents failing
180− forM_ failingTestCases $ \inputFile -> when (".purs" `isSuffixOf` inputFile) $
181− assertDoesNotCompile (supportPurs ++ [failing </> inputFile]) foreigns
182− exitSuccess
224+ failingTestCases <- sort . filter (".purs" `isSuffixOf`) <$> getDirectoryContents failing
225+
226+ failures <- execWriterT $ do
227+ forM_ passingTestCases $ \inputFile ->
228+ assertCompiles (supportPurs ++ [passing </> inputFile]) foreigns
229+ forM_ failingTestCases $ \inputFile ->
230+ assertDoesNotCompile (supportPurs ++ [failing </> inputFile]) foreigns
231+
232+ if null failures
233+ then exitSuccess
234+ else do
235+ putStrLn "Failures:"
236+ forM_ failures $ \(fp, err) ->
237+ let fp' = fromMaybe fp $ stripPrefix (failing ++ [pathSeparator]) fp
238+ in putStrLn $ fp' ++ ": " ++ err
239+ exitFailure
183240
184241fetchSupportCode :: IO ()
185242fetchSupportCode = do