1{-# LANGUAGE DeriveDataTypeable #-}
6import qualified Control.Concurrent as C
7import Control.Exception (Exception, handle, throwIO, finally, SomeException)
8import Control.Monad (foldM, unless, when, replicateM)
9import qualified Data.Map as Map
10import qualified Data.Set as Set
11import Data.Typeable (Typeable)
15import System.Directory (canonicalizePath, createDirectory,
17import System.Environment (getEnvironment)
18import System.Exit (ExitCode (ExitSuccess))
19import System.FilePath ((<.>), (</>))
20import System.IO (IOMode (WriteMode, AppendMode),
22import System.Process (runProcess, waitForProcess)
24runTestSuites :: BuildSettings -> InstallInfo -> IO ()
25runTestSuites settings ii = do
26 let testdir = "runtests"
28 createDirectory testdir
29 allPass <- parFoldM (testWorkerThreads settings) (runTestSuite settings testdir hasTestSuites) (&&) True $ Map.toList $ iiPackages ii
30 unless allPass $ error $ "There were failures, please see the logs in " ++ testdir
32 PackageDB pdb = iiPackageDB ii
34 hasTestSuites name = maybe defaultHasTestSuites piHasTests $ Map.lookup name pdb
36parFoldM :: Int -- ^ number of threads
42parFoldM threadCount f g a0 bs0 = do
45 signal <- C.newEmptyMVar
46 tids <- replicateM threadCount $ C.forkIO $ worker ma mbs signal
47 wait threadCount signal tids
50 worker ma mbs signal =
52 (C.putMVar signal . Just)
53 (loop >> C.putMVar signal Nothing)
56 mb <- C.modifyMVar mbs $ \bs -> return $
59 b:bs' -> (bs', Just b)
64 C.modifyMVar_ ma $ \a -> return $! g a c
66 wait threadCount signal tids
67 | threadCount == 0 = return ()
69 me <- C.takeMVar signal
71 Nothing -> wait (threadCount - 1) signal tids
73 mapM_ C.killThread tids
74 throwIO (e :: SomeException)
76data TestException = TestException
77 deriving (Show, Typeable)
78instance Exception TestException
80runTestSuite :: BuildSettings
82 -> (PackageName -> Bool) -- ^ do we have any test suites?
83 -> (PackageName, (Version, Maintainer))
85runTestSuite settings testdir hasTestSuites (packageName, (version, Maintainer maintainer)) = do
86 -- Set up a new environment that includes the sandboxed bin folder in PATH.
87 env' <- getModifiedEnv settings
89 = Just $ (if addGPP then (("GHC_PACKAGE_PATH", packageDir settings ++ ":"):) else id)
90 $ ("HASKELL_PACKAGE_SANDBOX", packageDir settings)
93 let runGen addGPP cmd args wdir handle = do
94 ph <- runProcess cmd args (Just wdir) (menv addGPP) Nothing (Just handle) (Just handle)
95 ec <- waitForProcess ph
96 unless (ec == ExitSuccess) $ throwIO TestException
98 let run = runGen False
99 runGhcPackagePath = runGen True
101 passed <- handle (\TestException -> return False) $ do
102 getHandle WriteMode $ run "cabal" ["unpack", package] testdir
103 getHandle AppendMode $ run "cabal" (addCabalArgs settings ["configure", "--enable-tests"]) dir
104 when (hasTestSuites packageName) $ do
105 getHandle AppendMode $ run "cabal" ["build"] dir
106 getHandle AppendMode $ runGhcPackagePath "cabal" ["test"] dir
107 getHandle AppendMode $ run "cabal" ["haddock"] dir
109 let expectedFailure = packageName `Set.member` expectedFailures settings
113 when expectedFailure $ putStrLn $ package ++ " passed, but I didn't think it would."
114 else unless expectedFailure $ putStrLn $ "Test suite failed: " ++ package ++ "(" ++ maintainer ++ ")"
116 return $! passed || expectedFailure
118 logfile = testdir </> package <.> "log"
119 dir = testdir </> package
120 getHandle mode = withBinaryFile logfile mode
121 package = packageVersionString (packageName, version)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list