{-# LANGUAGE CPP #-}
module Test.Hspec.Core.Config (
Config (..)
, ColorMode(..)
, defaultConfig
, getConfig
, configAddFilter
, configQuickCheckArgs
#ifdef TEST
, readConfigFiles
#endif
) where
import Prelude ()
import Control.Exception
import Control.Monad
import Data.Maybe
import System.IO
import System.IO.Error
import System.Exit
import System.FilePath
import System.Directory
import qualified Test.QuickCheck as QC
import Test.Hspec.Core.Util
import Test.Hspec.Core.Compat
import Test.Hspec.Core.Config.Options
import Test.Hspec.Core.FailureReport
import Test.Hspec.Core.QuickCheckUtil (mkGen)
import Test.Hspec.Core.Example (Params(..), defaultParams)
configAddFilter :: (Path -> Bool) -> Config -> Config
configAddFilter p1 c = c {
configFilterPredicate = Just p1 `filterOr` configFilterPredicate c
}
mkConfig :: Maybe FailureReport -> Config -> Config
mkConfig mFailureReport opts = opts {
configFilterPredicate = matchFilter `filterOr` rerunFilter
, configQuickCheckSeed = mSeed
, configQuickCheckMaxSuccess = mMaxSuccess
, configQuickCheckMaxDiscardRatio = mMaxDiscardRatio
, configQuickCheckMaxSize = mMaxSize
}
where
mSeed = configQuickCheckSeed opts <|> (failureReportSeed <$> mFailureReport)
mMaxSuccess = configQuickCheckMaxSuccess opts <|> (failureReportMaxSuccess <$> mFailureReport)
mMaxSize = configQuickCheckMaxSize opts <|> (failureReportMaxSize <$> mFailureReport)
mMaxDiscardRatio = configQuickCheckMaxDiscardRatio opts <|> (failureReportMaxDiscardRatio <$> mFailureReport)
matchFilter = configFilterPredicate opts
rerunFilter = case failureReportPaths <$> mFailureReport of
Just [] -> Nothing
Just xs -> Just (`elem` xs)
Nothing -> Nothing
configQuickCheckArgs :: Config -> QC.Args
configQuickCheckArgs c = qcArgs
where
qcArgs = (
maybe id setSeed (configQuickCheckSeed c)
. maybe id setMaxDiscardRatio (configQuickCheckMaxDiscardRatio c)
. maybe id setMaxSize (configQuickCheckMaxSize c)
. maybe id setMaxSuccess (configQuickCheckMaxSuccess c)) (paramsQuickCheckArgs defaultParams)
setMaxSuccess :: Int -> QC.Args -> QC.Args
setMaxSuccess n args = args {QC.maxSuccess = n}
setMaxSize :: Int -> QC.Args -> QC.Args
setMaxSize n args = args {QC.maxSize = n}
setMaxDiscardRatio :: Int -> QC.Args -> QC.Args
setMaxDiscardRatio n args = args {QC.maxDiscardRatio = n}
setSeed :: Integer -> QC.Args -> QC.Args
setSeed n args = args {QC.replay = Just (mkGen (fromIntegral n), 0)}
getConfig :: Config -> String -> [String] -> IO (Maybe FailureReport, Config)
getConfig opts_ prog args = do
configFiles <- do
ignore <- ignoreConfigFile opts_ args
case ignore of
True -> return []
False -> readConfigFiles
envVar <- fmap words <$> lookupEnv envVarName
case parseOptions opts_ prog configFiles envVar args of
Left (err, msg) -> exitWithMessage err msg
Right opts -> do
r <- if configRerun opts then readFailureReport opts else return Nothing
return (r, mkConfig r opts)
readConfigFiles :: IO [ConfigFile]
readConfigFiles = do
global <- readGlobalConfigFile
local <- readLocalConfigFile
return $ catMaybes [global, local]
readGlobalConfigFile :: IO (Maybe ConfigFile)
readGlobalConfigFile = do
mHome <- tryJust (guard . isDoesNotExistError) getHomeDirectory
case mHome of
Left _ -> return Nothing
Right home -> readConfigFile (home </> ".hspec")
readLocalConfigFile :: IO (Maybe ConfigFile)
readLocalConfigFile = do
mName <- tryJust (guard . isDoesNotExistError) (canonicalizePath ".hspec")
case mName of
Left _ -> return Nothing
Right name -> readConfigFile name
readConfigFile :: FilePath -> IO (Maybe ConfigFile)
readConfigFile name = do
exists <- doesFileExist name
if exists then Just . (,) name . words <$> readFile name else return Nothing
exitWithMessage :: ExitCode -> String -> IO a
exitWithMessage err msg = do
hPutStr h msg
exitWith err
where
h = case err of
ExitSuccess -> stdout
_ -> stderr