module Test.HUnitPlus.Reporting(
Node(..),
State(..),
Counts(..),
Reporter(..),
Path,
zeroCounts,
showPath,
defaultReporter,
combinedReporter
) where
import Data.List
import Data.Word
import Data.Map(Map)
import Distribution.TestSuite
data Counts =
Counts {
cCases :: !Word,
cTried :: !Word,
cErrors :: !Word,
cFailures :: !Word,
cSkipped :: !Word,
cAsserts :: !Word
}
deriving (Eq, Show, Read)
data State =
State {
stName :: !String,
stPath :: !Path,
stCounts :: !Counts,
stOptions :: !(Map String String),
stOptionDescs :: ![OptionDescr]
}
deriving (Eq, Show, Read)
type Path = [Node]
data Node = Label String
deriving (Eq, Show, Read)
data Reporter us = Reporter {
reporterStart :: IO us,
reporterEnd :: Double
-> Counts
-> us
-> IO us,
reporterStartSuite :: State
-> us
-> IO us,
reporterEndSuite :: Double
-> State
-> us
-> IO us,
reporterStartCase :: State
-> us
-> IO us,
reporterCaseProgress :: String
-> State
-> us
-> IO us,
reporterEndCase :: Double
-> State
-> us
-> IO us,
reporterSkipCase :: State
-> us
-> IO us,
reporterSystemOut :: String
-> State
-> us
-> IO us,
reporterSystemErr :: String
-> State
-> us
-> IO us,
reporterFailure :: String
-> State
-> us
-> IO us,
reporterError :: String
-> State
-> us
-> IO us
}
zeroCounts :: Counts
zeroCounts = Counts { cCases = 0, cTried = 0, cErrors = 0,
cFailures = 0, cAsserts = 0, cSkipped = 0 }
defaultReporter :: Reporter a
defaultReporter = Reporter {
reporterStart = fail "Must define a reporterStart value",
reporterEnd = \_ _ us -> return us,
reporterStartSuite = \_ us -> return us,
reporterEndSuite = \_ _ us -> return us,
reporterStartCase = \_ us -> return us,
reporterCaseProgress = \_ _ us -> return us,
reporterEndCase = \_ _ us -> return us,
reporterSkipCase = \_ us -> return us,
reporterSystemOut = \_ _ us -> return us,
reporterSystemErr = \_ _ us -> return us,
reporterFailure = \_ _ us -> return us,
reporterError = \_ _ us -> return us
}
showPath :: Path -> String
showPath [] = ""
showPath nodes =
let
showNode (Label label) = safe label (show label)
safe s ss = if '.' `elem` s || "\"" ++ s ++ "\"" /= ss then ss else s
in
intercalate "." (reverse (map showNode nodes))
combinedReporter :: Reporter us1 -> Reporter us2 -> Reporter (us1, us2)
combinedReporter Reporter { reporterStart = reportStart1,
reporterEnd = reportEnd1,
reporterStartSuite = reportStartSuite1,
reporterEndSuite = reportEndSuite1,
reporterStartCase = reportStartCase1,
reporterCaseProgress = reportCaseProgress1,
reporterEndCase = reportEndCase1,
reporterSkipCase = reportSkipCase1,
reporterSystemOut = reportSystemOut1,
reporterSystemErr = reportSystemErr1,
reporterFailure = reportFailure1,
reporterError = reportError1
}
Reporter { reporterStart = reportStart2,
reporterEnd = reportEnd2,
reporterStartSuite = reportStartSuite2,
reporterEndSuite = reportEndSuite2,
reporterStartCase = reportStartCase2,
reporterCaseProgress = reportCaseProgress2,
reporterEndCase = reportEndCase2,
reporterSkipCase = reportSkipCase2,
reporterSystemOut = reportSystemOut2,
reporterSystemErr = reportSystemErr2,
reporterFailure = reportFailure2,
reporterError = reportError2
} =
let
reportStart =
do
us1 <- reportStart1
us2 <- reportStart2
return $! (us1, us2)
reportEnd time counts (us1, us2) =
do
us1' <- reportEnd1 time counts us1
us2' <- reportEnd2 time counts us2
return $! (us1', us2')
reportStartSuite ss (us1, us2) =
do
us1' <- reportStartSuite1 ss us1
us2' <- reportStartSuite2 ss us2
return $! (us1', us2')
reportEndSuite time ss (us1, us2) =
do
us1' <- reportEndSuite1 time ss us1
us2' <- reportEndSuite2 time ss us2
return $! (us1', us2')
reportStartCase ss (us1, us2) =
do
us1' <- reportStartCase1 ss us1
us2' <- reportStartCase2 ss us2
return $! (us1', us2')
reportCaseProgress msg ss (us1, us2) =
do
us1' <- reportCaseProgress1 msg ss us1
us2' <- reportCaseProgress2 msg ss us2
return $! (us1', us2')
reportEndCase time ss (us1, us2) =
do
us1' <- reportEndCase1 time ss us1
us2' <- reportEndCase2 time ss us2
return $! (us1', us2')
reportSkipCase ss (us1, us2) =
do
us1' <- reportSkipCase1 ss us1
us2' <- reportSkipCase2 ss us2
return $! (us1', us2')
reportSystemOut msg ss (us1, us2) =
do
us1' <- reportSystemOut1 msg ss us1
us2' <- reportSystemOut2 msg ss us2
return $! (us1', us2')
reportSystemErr msg ss (us1, us2) =
do
us1' <- reportSystemErr1 msg ss us1
us2' <- reportSystemErr2 msg ss us2
return $! (us1', us2')
reportFailure msg ss (us1, us2) =
do
us1' <- reportFailure1 msg ss us1
us2' <- reportFailure2 msg ss us2
return $! (us1', us2')
reportError msg ss (us1, us2) =
do
us1' <- reportError1 msg ss us1
us2' <- reportError2 msg ss us2
return $! (us1', us2')
in
Reporter {
reporterStart = reportStart,
reporterEnd = reportEnd,
reporterStartSuite = reportStartSuite,
reporterEndSuite = reportEndSuite,
reporterStartCase = reportStartCase,
reporterCaseProgress = reportCaseProgress,
reporterEndCase = reportEndCase,
reporterSkipCase = reportSkipCase,
reporterSystemOut = reportSystemOut,
reporterSystemErr = reportSystemErr,
reporterFailure = reportFailure,
reporterError = reportError
}