1 {-# LANGUAGE FlexibleContexts #-}
2 {-# LANGUAGE RankNTypes #-}
4 module Distribution
.Simple
.Test
.ExeV10
8 import Distribution
.Compat
.Prelude
11 import Distribution
.Compat
.Environment
12 import qualified Distribution
.PackageDescription
as PD
13 import Distribution
.Pretty
14 import Distribution
.Simple
.Build
.PathsModule
15 import Distribution
.Simple
.BuildPaths
16 import Distribution
.Simple
.Compiler
17 import Distribution
.Simple
.Flag
18 import Distribution
.Simple
.Hpc
19 import Distribution
.Simple
.InstallDirs
20 import qualified Distribution
.Simple
.LocalBuildInfo
as LBI
21 import Distribution
.Simple
.Setup
.Test
22 import Distribution
.Simple
.Test
.Log
23 import Distribution
.Simple
.Utils
24 import Distribution
.System
25 import Distribution
.TestSuite
26 import qualified Distribution
.Types
.LocalBuildInfo
as LBI
27 import Distribution
.Types
.UnqualComponentName
28 import Distribution
.Verbosity
30 import System
.Directory
31 ( createDirectoryIfMissing
35 , removeDirectoryRecursive
37 import System
.FilePath ((<.>), (</>))
38 import System
.IO (stderr, stdout)
39 import System
.Process
(createPipe
)
41 import qualified Data
.ByteString
.Lazy
as LBS
42 import Distribution
.Simple
.Errors
45 :: PD
.PackageDescription
47 -> LBI
.ComponentLocalBuildInfo
51 runTest pkg_descr lbi clbi flags suite
= do
52 let isCoverageEnabled
= LBI
.testCoverage lbi
54 tixDir_
= tixDir distPref way testName
'
56 pwd
<- getCurrentDirectory
57 existingEnv
<- getEnvironment
62 </> testName
' <.> exeExtension
(LBI
.hostPlatform lbi
)
63 -- Check that the test executable exists.
64 exists
<- doesFileExist cmd
66 dieWithException verbosity
$
67 Couldn
'tFindTestProgram cmd
69 -- Remove old .tix files if appropriate.
70 unless (fromFlag
$ testKeepTix flags
) $ do
71 exists
' <- doesDirectoryExist tixDir_
72 when exists
' $ removeDirectoryRecursive tixDir_
74 -- Create directory for HPC files.
75 createDirectoryIfMissing
True tixDir_
77 -- Write summary notices indicating start of test suite
78 notice verbosity
$ summarizeSuiteStart
$ testName
'
80 -- Run the test executable
83 (testOption pkg_descr lbi suite
)
85 dataDirPath
= pwd
</> PD
.dataDir pkg_descr
86 tixFile
= pwd
</> tixFilePath distPref way
(testName
')
88 (pkgPathEnvVar pkg_descr
"datadir", dataDirPath
)
90 shellEnv
= [("HPCTIXFILE", tixFile
) | isCoverageEnabled
] ++ pkgPathEnv
92 -- Add (DY)LD_LIBRARY_PATH if needed
96 let (Platform _ os
) = LBI
.hostPlatform lbi
97 paths
<- LBI
.depLibraryPaths
True False lbi clbi
98 return (addLibraryPath os paths shellEnv
)
102 (wOut
, wErr
, getLogText
) <- case details
of
103 Direct
-> return (stdout, stderr, return LBS
.empty)
105 (rOut
, wOut
) <- createPipe
107 return $ (,,) wOut wOut
$ do
108 -- Read test executables' output
109 logText
<- LBS
.hGetContents rOut
111 -- '--show-details=streaming': print the log output in another thread
112 when (details
== Streaming
) $ LBS
.putStr logText
115 evaluate
(force logText
)
117 (exit
, logText
) <- case testWrapper flags
of
119 rawSystemIOWithEnvAndAction
126 -- these handles are automatically closed
131 rawSystemIOWithEnvAndAction
138 -- these handles are automatically closed
143 -- Generate TestSuiteLog from executable exit code and a machine-
144 -- readable test log.
145 let suiteLog
= buildLog exit
147 -- Write summary notice to log file indicating start of test suite
148 appendFile (logFile suiteLog
) $ summarizeSuiteStart testName
'
150 -- Append contents of temporary log file to the final human-
152 LBS
.appendFile (logFile suiteLog
) logText
154 -- Write end-of-suite summary notice to log file
155 appendFile (logFile suiteLog
) $ summarizeSuiteFinish suiteLog
157 -- Show the contents of the human-readable log file on the terminal
158 -- if there is a failure and/or detailed output is requested
162 || details
== Failures
&& not (suitePassed
$ testLogs suiteLog
)
164 -- verbosity overrides show-details
165 && verbosity
>= normal
170 -- Write summary notice to terminal indicating end of test suite
171 notice verbosity
$ summarizeSuiteFinish suiteLog
173 when isCoverageEnabled
$
174 case PD
.library pkg_descr
of
176 dieWithException verbosity TestCoverageSupport
178 markupTest verbosity lbi distPref
(prettyShow
$ PD
.package pkg_descr
) suite library
182 testName
' = unUnqualComponentName
$ PD
.testName suite
184 distPref
= fromFlag
$ testDistPref flags
185 verbosity
= fromFlag
$ testVerbosity flags
186 details
= fromFlag
$ testShowDetails flags
187 testLogDir
= distPref
</> "test"
192 ExitFailure c
-> Fail
$ "exit code: " ++ show c
193 -- n = unUnqualComponentName $ PD.testName suite
196 { testName
= testName
'
197 , testOptionsReturned
= []
201 { testSuiteName
= PD
.testName suite
206 (fromFlag
$ testHumanLog flags
)
213 -- TODO: This is abusing the notion of a 'PathTemplate'. The result isn't
214 -- necessarily a path.
216 :: PD
.PackageDescription
217 -> LBI
.LocalBuildInfo
221 testOption pkg_descr lbi suite template
=
222 fromPathTemplate
$ substPathTemplate env template
225 initialPathTemplateEnv
226 (PD
.package pkg_descr
)
227 (LBI
.localUnitId lbi
)
228 (compilerInfo
$ LBI
.compiler lbi
)
229 (LBI
.hostPlatform lbi
)
230 ++ [(TestSuiteNameVar
, toPathTemplate
$ unUnqualComponentName
$ PD
.testName suite
)]