{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-} -- | Use "runhaskell Setup.hs test" or "cabal test" to run these tests. module Main where -- import Language.Haskell.GHC.ExactPrint.Utils ( showGhc ) import qualified GHC.Paths import Control.Monad import System.Directory import System.FilePath import System.IO import System.Exit import Data.List import qualified Data.Set as Set import System.IO.Silently import Test.Common import Test.NoAnnotations import Test.Transform import Test.HUnit -- import Debug.Trace -- --------------------------------------------------------------------- data GHCVersion = GHC710 | GHC80 | GHC82 | GHC84 | GHC86 | GHC88 | GHC810 | GHC90 | GHC92 deriving (Eq, Ord, Show) ghcVersion :: GHCVersion ghcVersion = GHC92 -- | Directories to automatically find roundtrip tests testDirs :: [FilePath] testDirs = case ghcVersion of GHC90 -> ["ghc710", "ghc80", "ghc82", "ghc84", "ghc86", "ghc88", "ghc810", "ghc90"] GHC92 -> ["ghc710", "ghc80", "ghc82", "ghc84", "ghc86", "ghc88", "ghc810", "ghc90", "ghc92"] -- GHC92 -> ["ghc92-copied"] -- GHC92 -> ["ghc92"] -- --------------------------------------------------------------------- main :: IO () main = hSilence [stderr] $ do print ghcVersion tests <- mkTests cnts <- fst <$> runTestText (putTextToHandle stdout True) tests putStrLn $ show cnts if errors cnts > 0 || failures cnts > 0 then exitFailure else return () -- exitSuccess transform :: IO () transform = hSilence [stderr] $ do let libdir = GHC.Paths.libdir cnts <- fst <$> runTestText (putTextToHandle stdout True) (transformTestsTT libdir) putStrLn $ show cnts if errors cnts > 0 || failures cnts > 0 then exitFailure else return () -- exitSuccess -- --------------------------------------------------------------------- findTests :: LibDir -> IO Test findTests libdir = testList "Round-trip tests" <$> mapM (findTestsDir id (mkParserTest libdir)) testDirs findPrettyTests :: LibDir -> IO Test findPrettyTests libdir = testList "Default Annotations round-trip tests" <$> mapM (findTestsDir filterPrettyRoundTrip (mkPrettyRoundtrip libdir)) testDirs -- | Filter out tests that are known to fail, for particular compilers filterPrettyRoundTrip :: [FilePath] -> [FilePath] filterPrettyRoundTrip fps = sort $ Set.toList $ Set.difference (Set.fromList fps) skipped -- filterPrettyRoundTrip fps = error $ "filterPrettyRoundTrip:fps=" ++ show fps where skipped = Set.empty findTestsDir :: ([FilePath] -> [FilePath]) -> (FilePath -> FilePath -> Test) -> FilePath -> IO Test findTestsDir filterFn mkTestFn dir = do let fp = testPrefix dir fs <- getDirectoryContents fp let testFiles = sort $ filter (".hs" `isSuffixOf`) fs return $ testList dir (map (\fn -> TestLabel fn (mkTestFn dir fn)) $ filterFn testFiles) listTests :: IO () listTests = do let ftd dir = do let fp = testPrefix dir fs <- getDirectoryContents fp let testFiles = sort $ filter (".hs" `isSuffixOf`) fs return (zip [0::Integer ..] testFiles) files <- mapM ftd testDirs putStrLn $ "round trip tests:" ++ show (zip testDirs files) mkTests :: IO Test mkTests = do -- listTests let libdir = GHC.Paths.libdir roundTripTests <- findTests libdir prettyRoundTripTests <- findPrettyTests libdir return $ TestList [ internalTests, roundTripTests , (transformTests libdir) , (failingTests libdir) -- , noAnnotationTests -- , -- prettyRoundTripTests ] failingTests :: LibDir -> Test failingTests libdir = testList "Failing tests" [ -- Tests requiring future GHC modifications -- https://gitlab.haskell.org/ghc/ghc/-/issues/20243 mkTestModBad libdir "n-plus-k-patterns.hs" -- https://gitlab.haskell.org/ghc/ghc/-/issues/20258 , mkTestModBad libdir "TopLevelSemis.hs" -- We do not capture EOF location very well any more , mkTestModBad libdir "T10970a.hs" ] mkParserTest :: LibDir -> FilePath -> FilePath -> Test mkParserTest libdir dir fp = mkParsingTest (roundTripTest libdir) dir fp -- --------------------------------------------------------------------- formatTT :: ([([Char], Bool)], [([Char], Bool)]) -> IO () formatTT (ts, fs) = do when (not . null $ tail ts) (do putStrLn "Pass" mapM_ (putStrLn . fst) (tail ts) ) when (not . null $ fs) (do putStrLn "Fail" mapM_ (putStrLn . fst) fs) tr :: IO (Counts,Int) tr = hSilence [stderr] $ do let libdir = GHC.Paths.libdir prettyRoundTripTests <- findPrettyTests libdir runTestText (putTextToHandle stdout True) prettyRoundTripTests tt' :: IO (Counts,Int) tt' = do let libdir = GHC.Paths.libdir runTestText (putTextToHandle stdout True) $ TestList [ -- mkTestModChange libdir changeRenameCase1 "RenameCase1.hs" -- mkParserTest libdir "ghc710" "UnicodeSyntaxFailure.hs" -- mkParserTest libdir "ghc80" "Class.hs" -- mkParserTest libdir "ghc82" "Completesig03A.hs" -- mkParserTest libdir "ghc82" "brackets.hs" -- mkParserTest libdir "ghc84" "T13747.hs" -- mkParserTest libdir "ghc86" "SlidingTypeSyn.hs" -- mkParserTest libdir "ghc86" "dynamic-paper.hs" -- mkParserTest libdir "ghc90" "ArrowLambdaCase.hs" -- mkParserTest libdir "ghc80" "T6018failclosed.hs" -- mkParserTest libdir "failing" "InfixOperator.hs" -- mkParserTest libdir "ghc92-copied" "AddLocalDecl5.expected.hs" -- mkParserTest libdir "ghc92" "ScopesBug.hs" -- mkParserTest libdir "ghc92-copied" "T10279.hs" -- mkParserTest libdir "ghc92-copied" "T10891.hs" -- mkParserTest libdir "ghc92-copied" "T2632.hs" -- mkParserTest libdir "ghc92-copied" "T4442.hs" -- mkParserTest libdir "ghc92-copied" "TH_reifyExplicitForAllFams.hs" -- mkParserTest libdir "ghc92-copied" "TH_unresolvedInfix.hs" -- mkParserTest libdir "ghc92-copied" "regalloc_unit_tests.hs" -- mkParserTest libdir "ghc92" "Checkpoint.hs" -- mkParserTest libdir "ghc710" "MultiLineCommentWithPragmas.hs" -- mkParserTest libdir "ghc710" "Process.hs" -- mkParserTest libdir "ghc92" "PostgreSQL.hs" -- mkParserTest libdir "ghc92" "Main.hs" -- mkParserTest libdir "ghc92" "MainHareTest.hs" -- mkParserTest libdir "ghc92" "TH.hs" -- mkParserTest libdir "ghc92" "LeapSeconds.hs" -- mkParserTest libdir "ghc92" "proc-lets.hs" -- mkParserTest libdir "ghc92" "n-plus-k-patterns.hs" -- mkParserTest libdir "ghc92" "TopLevelSemis.hs" -- mkParserTest libdir "ghc92" "MiniBall.hs" mkParserTest libdir "ghc80" "T10970a.hs" -- mkTestModChange libdir rmDecl1 "RmDecl1.hs" -- mkParserTest libdir "ghc92" "LinearArrow.hs" -- mkParserTest libdir "transform" "AddLocalDecl5.1.hs" -- mkTestModChange libdir addLocaLDecl5 "AddLocalDecl5.hs" -- mkTestModChange libdir changeLocalDecls2 "LocalDecls2.hs" -- mkTestModChange libdir addLocaLDecl1 "AddLocalDecl1.hs" {- ### Failure in: 1:Round-trip tests:1:ghc80:27:Decision.hs ### Failure in: 2:transformation tests:0:Low level transformations:15 AddLocalDecl1.hs AddLocalDecl4.hs AddLocalDecl5.hs AddLocalDecl6.hs -} -- mkParserTest libdir "ghc710" "EmptyMostly.hs" -- comment problem -- mkParserTest libdir "ghc710" "Move1.hs" -- mkParserTest libdir "ghc80" "Decision.hs" -- mkParserTest libdir "ghc80" "RandomPGC.hs" -- mkParserTest libdir "ghc92" "BlockComment.hs" -- mkParserTest libdir "ghc92" "CommentPlacement.hs" -- mkParserTest libdir "ghc92" "CommentPlacement2.hs" -- mkParserTest libdir "ghc80" "Decision.hs" -- mkParserTest libdir "ghc92-copied" "AddLocalDecl5.expected.hs" -- mkParserTest libdir "ghc92-copied" "AtomicPrimops.hs" -- mkParserTest libdir "ghc92-copied" "BinaryLiterals0.hs" -- mkParserTest libdir "ghc92-copied" "CountDeps.hs" -- mkParserTest libdir "ghc92-copied" "regalloc_unit_tests.hs" -- ### Failure in: 1:Round-trip tests:0:ghc710:20:Control.hs -- ### Failure in: 1:Round-trip tests:0:ghc710:21:CoreIr.hs -- ### Failure in: 1:Round-trip tests:0:ghc710:23:Cpp.hs -- ### Failure in: 1:Round-trip tests:0:ghc710:38:EmptyMostly.hs -- ### Failure in: 1:Round-trip tests:0:ghc710:39:EmptyMostly2.hs -- ### Failure in: 1:Round-trip tests:0:ghc710:40:EmptyMostlyInst.hs -- ### Failure in: 1:Round-trip tests:0:ghc710:41:EmptyMostlyNoSemis.hs -- ### Error in: 1:Round-trip tests:0:ghc710:50:ForeignDecl.hs -- mkParserTest libdir "ghc710" "BracesSemiDataDecl.hs" -- mkParserTest libdir "ghc710" "GADTRecords.hs" -- mkParserTest libdir "ghc710" "RdrNames.hs" -- mkParserTest libdir "ghc710" "RdrNames1.hs" -- mkParserTest libdir "ghc80" "T11010.hs" -- mkParserTest libdir "ghc80" "Test10399.hs" -- mkParserTest libdir "ghc90" "Linear12.hs" -- mkParserTest libdir "ghc90" "T17544_kw.hs" -- mkParserTest libdir "ghc90" "FromManual.hs" -- mkPrettyRoundtrip libdir "ghc90" "FromManual.hs" -- mkParserTest libdir "ghc90" "Linear1Rule.hs" -- mkPrettyRoundtrip libdir "ghc90" "Linear1Rule.hs" -- mkParserTest libdir "ghc80" "Test11018.hs" -- mkPrettyRoundtrip libdir "ghc80" "Test11018.hs" -- mkParserTest libdir "ghc86" "UnicodeSyntax.hs" -- mkPrettyRoundtrip libdir "ghc86" "UnicodeSyntax.hs" -- mkParserTest libdir "ghc86" "empty-foralls.hs" -- mkPrettyRoundtrip libdir "ghc86" "empty-foralls.hs" -- mkParserTest libdir "ghc710" "PatSynBind.hs" -- mkPrettyRoundtrip libdir "ghc710" "PatSynBind.hs" -- --------------------------------------------- -- mkParserTest libdir "ghc86" "Webhook.hs" -- mkParserTest libdir "ghc710" "TypeBrackets2.hs" -- mkPrettyRoundtrip libdir "ghc710" "TypeBrackets2.hs" -- mkParserTest libdir "ghc710" "DataDecl.hs" -- mkPrettyRoundtrip libdir "ghc710" "DataDecl.hs" -- mkParserTest libdir "ghc90" "BaseDescriptor.hs" -- mkPrettyRoundtrip libdir "ghc90" "BaseDescriptor.hs" -- mkParserTest libdir "ghc90" "BaseDescriptors2.hs" -- mkPrettyRoundtrip libdir "ghc90" "BaseDescriptors2.hs" -- Needs GHC changes ] testsTT :: LibDir -> Test testsTT libdir = TestList [ mkParserTest libdir "ghc710" "Cpp.hs" , mkParserTest libdir "ghc710" "DroppedDoSpace.hs" ] tt :: IO () -- tt = hSilence [stderr] $ do tt = do let libdir = GHC.Paths.libdir cnts <- fst <$> runTestText (putTextToHandle stdout True) (testsTT libdir) putStrLn $ show cnts if errors cnts > 0 || failures cnts > 0 then exitFailure else return () -- exitSuccess -- --------------------------------------------------------------------- ii :: IO () ii = do cnts <- fst <$> runTestText (putTextToHandle stdout True) internalTests putStrLn $ show cnts if errors cnts > 0 || failures cnts > 0 then exitFailure else return () -- exitSuccess internalTests :: Test internalTests = testList "Internal tests" [ -- testCleanupOneLine ] {- testCleanupOneLine :: Test testCleanupOneLine = do let makeCase n = (show n ,(T.replicate n " ") <> "\t|" <> T.replicate n " " <> "\t" ,(T.replicate 8 " " <> "|")) mkTest n = TestCase $ assertEqual name outp (cleanupOneLine inp) where (name,inp,outp) = makeCase n testList "cleanupOneLine" $ map mkTest [1..7] -} -- --------------------------------------------------------------------- pwd :: IO FilePath pwd = getCurrentDirectory cd :: FilePath -> IO () cd = setCurrentDirectory