{-# LANGUAGE CPP #-}
{-# LANGUAGE LambdaCase #-}
module Runner (
runModules
, FastMode(..)
, PreserveIt(..)
, FailFast(..)
, Verbose(..)
, Summary(..)
, isSuccess
, formatSummary
#ifdef TEST
, Report
, ReportState(..)
, runReport
, Interactive(..)
, report
, reportTransient
#endif
) where
import Prelude ()
import Imports hiding (putStr, putStrLn, error)
import Text.Printf (printf)
import System.IO hiding (putStr, putStrLn)
import Control.Monad.Trans.Class
import Control.Monad.Trans.Maybe
import Control.Monad.Trans.State (StateT, evalStateT)
import qualified Control.Monad.Trans.State as State
import Control.Monad.IO.Class
import Data.IORef
import Interpreter (Interpreter, PreserveIt(..), safeEvalWith)
import qualified Interpreter
import Parse
import Location
import Property
import Runner.Example
data Summary = Summary {
Summary -> Int
sExamples :: !Int
, Summary -> Int
sTried :: !Int
, Summary -> Int
sErrors :: !Int
, Summary -> Int
sFailures :: !Int
} deriving Summary -> Summary -> Bool
(Summary -> Summary -> Bool)
-> (Summary -> Summary -> Bool) -> Eq Summary
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Summary -> Summary -> Bool
== :: Summary -> Summary -> Bool
$c/= :: Summary -> Summary -> Bool
/= :: Summary -> Summary -> Bool
Eq
instance Show Summary where
show :: Summary -> String
show = Summary -> String
formatSummary
isSuccess :: Summary -> Bool
isSuccess :: Summary -> Bool
isSuccess Summary
s = Summary -> Int
sErrors Summary
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 Bool -> Bool -> Bool
&& Summary -> Int
sFailures Summary
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
formatSummary :: Summary -> String
formatSummary :: Summary -> String
formatSummary (Summary Int
examples Int
tried Int
errors Int
failures) =
String -> Int -> Int -> Int -> Int -> String
forall r. PrintfType r => String -> r
printf String
"Examples: %d Tried: %d Errors: %d Failures: %d" Int
examples Int
tried Int
errors Int
failures
instance Monoid Summary where
mempty :: Summary
mempty = Int -> Int -> Int -> Int -> Summary
Summary Int
0 Int
0 Int
0 Int
0
#if __GLASGOW_HASKELL__ < 804
mappend
#else
instance Semigroup Summary where
<> :: Summary -> Summary -> Summary
(<>)
#endif
(Summary Int
x1 Int
x2 Int
x3 Int
x4) (Summary Int
y1 Int
y2 Int
y3 Int
y4) = Int -> Int -> Int -> Int -> Summary
Summary (Int
x1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
y1) (Int
x2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
y2) (Int
x3 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
y3) (Int
x4 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
y4)
withLineBuffering :: Handle -> IO c -> IO c
withLineBuffering :: forall c. Handle -> IO c -> IO c
withLineBuffering Handle
h IO c
action = IO BufferMode
-> (BufferMode -> IO ()) -> (BufferMode -> IO c) -> IO c
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket (Handle -> IO BufferMode
hGetBuffering Handle
h) (Handle -> BufferMode -> IO ()
hSetBuffering Handle
h) ((BufferMode -> IO c) -> IO c) -> (BufferMode -> IO c) -> IO c
forall a b. (a -> b) -> a -> b
$ \ BufferMode
_ -> do
Handle -> BufferMode -> IO ()
hSetBuffering Handle
h BufferMode
LineBuffering
IO c
action
runModules :: FastMode -> PreserveIt -> FailFast -> Verbose -> Interpreter -> [Module [Located DocTest]] -> IO Summary
runModules :: FastMode
-> PreserveIt
-> FailFast
-> Verbose
-> Interpreter
-> [Module [Located DocTest]]
-> IO Summary
runModules FastMode
fastMode PreserveIt
preserveIt FailFast
failFast Verbose
verbose Interpreter
repl [Module [Located DocTest]]
modules = Handle -> IO Summary -> IO Summary
forall c. Handle -> IO c -> IO c
withLineBuffering Handle
stderr (IO Summary -> IO Summary) -> IO Summary -> IO Summary
forall a b. (a -> b) -> a -> b
$ do
Interactive
interactive <- Handle -> IO Bool
hIsTerminalDevice Handle
stderr IO Bool -> (Bool -> Interactive) -> IO Interactive
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \ case
Bool
False -> Interactive
NonInteractive
Bool
True -> Interactive
Interactive
IORef Summary
summary <- Summary -> IO (IORef Summary)
forall a. a -> IO (IORef a)
newIORef Summary
forall a. Monoid a => a
mempty {sExamples = n}
let
reportFinalResult :: IO ()
reportFinalResult :: IO ()
reportFinalResult = do
Summary
final <- IORef Summary -> IO Summary
forall a. IORef a -> IO a
readIORef IORef Summary
summary
Handle -> String -> IO ()
hPutStrLn Handle
stderr (Summary -> String
formatSummary Summary
final)
run :: IO ()
run :: IO ()
run = ReportState -> Report () -> IO ()
runReport (Interactive -> FailFast -> Verbose -> IORef Summary -> ReportState
ReportState Interactive
interactive FailFast
failFast Verbose
verbose IORef Summary
summary) (Report () -> IO ()) -> Report () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
Report ()
reportProgress
[Module [Located DocTest]]
-> (Module [Located DocTest] -> Report ()) -> Report ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Module [Located DocTest]]
modules ((Module [Located DocTest] -> Report ()) -> Report ())
-> (Module [Located DocTest] -> Report ()) -> Report ()
forall a b. (a -> b) -> a -> b
$ FastMode
-> PreserveIt
-> Interpreter
-> Module [Located DocTest]
-> Report ()
runModule FastMode
fastMode PreserveIt
preserveIt Interpreter
repl
String -> Report ()
verboseReport String
"# Final summary:"
IO ()
run IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO a
`finally` IO ()
reportFinalResult
IORef Summary -> IO Summary
forall a. IORef a -> IO a
readIORef IORef Summary
summary
where
n :: Int
n :: Int
n = [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((Module [Located DocTest] -> Int)
-> [Module [Located DocTest]] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Module [Located DocTest] -> Int
countExpressions [Module [Located DocTest]]
modules)
countExpressions :: Module [Located DocTest] -> Int
countExpressions :: Module [Located DocTest] -> Int
countExpressions (Module String
_ Maybe [Located DocTest]
setup [[Located DocTest]]
tests) = [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum (([Located DocTest] -> Int) -> [[Located DocTest]] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map [Located DocTest] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [[Located DocTest]]
tests) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int -> ([Located DocTest] -> Int) -> Maybe [Located DocTest] -> Int
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Int
0 [Located DocTest] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Maybe [Located DocTest]
setup
type Report = MaybeT (StateT ReportState IO)
data Interactive = NonInteractive | Interactive
data FastMode = NoFastMode | FastMode
data FailFast = NoFailFast | FailFast
data Verbose = NonVerbose | Verbose
data ReportState = ReportState {
ReportState -> Interactive
reportStateInteractive :: Interactive
, ReportState -> FailFast
reportStateFailFast :: FailFast
, ReportState -> Verbose
reportStateVerbose :: Verbose
, ReportState -> IORef Summary
reportStateSummary :: IORef Summary
}
runReport :: ReportState -> Report () -> IO ()
runReport :: ReportState -> Report () -> IO ()
runReport ReportState
st = IO (Maybe ()) -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO (Maybe ()) -> IO ())
-> (Report () -> IO (Maybe ())) -> Report () -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (StateT ReportState IO (Maybe ()) -> ReportState -> IO (Maybe ()))
-> ReportState -> StateT ReportState IO (Maybe ()) -> IO (Maybe ())
forall a b c. (a -> b -> c) -> b -> a -> c
flip StateT ReportState IO (Maybe ()) -> ReportState -> IO (Maybe ())
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
evalStateT ReportState
st (StateT ReportState IO (Maybe ()) -> IO (Maybe ()))
-> (Report () -> StateT ReportState IO (Maybe ()))
-> Report ()
-> IO (Maybe ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Report () -> StateT ReportState IO (Maybe ())
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT
getSummary :: Report Summary
getSummary :: Report Summary
getSummary = (ReportState -> IORef Summary) -> Report (IORef Summary)
forall a. (ReportState -> a) -> Report a
gets ReportState -> IORef Summary
reportStateSummary Report (IORef Summary)
-> (IORef Summary -> Report Summary) -> Report Summary
forall a b.
MaybeT (StateT ReportState IO) a
-> (a -> MaybeT (StateT ReportState IO) b)
-> MaybeT (StateT ReportState IO) b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= IO Summary -> Report Summary
forall a. IO a -> MaybeT (StateT ReportState IO) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Summary -> Report Summary)
-> (IORef Summary -> IO Summary) -> IORef Summary -> Report Summary
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IORef Summary -> IO Summary
forall a. IORef a -> IO a
readIORef
gets :: (ReportState -> a) -> Report a
gets :: forall a. (ReportState -> a) -> Report a
gets = StateT ReportState IO a -> MaybeT (StateT ReportState IO) a
forall (m :: * -> *) a. Monad m => m a -> MaybeT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (StateT ReportState IO a -> MaybeT (StateT ReportState IO) a)
-> ((ReportState -> a) -> StateT ReportState IO a)
-> (ReportState -> a)
-> MaybeT (StateT ReportState IO) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ReportState -> a) -> StateT ReportState IO a
forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
State.gets
report :: String -> Report ()
report :: String -> Report ()
report = IO () -> Report ()
forall a. IO a -> MaybeT (StateT ReportState IO) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Report ()) -> (String -> IO ()) -> String -> Report ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> String -> IO ()
hPutStrLn Handle
stderr
reportTransient :: String -> Report ()
reportTransient :: String -> Report ()
reportTransient String
msg = (ReportState -> Interactive) -> Report Interactive
forall a. (ReportState -> a) -> Report a
gets ReportState -> Interactive
reportStateInteractive Report Interactive -> (Interactive -> Report ()) -> Report ()
forall a b.
MaybeT (StateT ReportState IO) a
-> (a -> MaybeT (StateT ReportState IO) b)
-> MaybeT (StateT ReportState IO) b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ case
Interactive
NonInteractive -> Report ()
forall (m :: * -> *). Monad m => m ()
pass
Interactive
Interactive -> IO () -> Report ()
forall a. IO a -> MaybeT (StateT ReportState IO) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Report ()) -> IO () -> Report ()
forall a b. (a -> b) -> a -> b
$ do
Handle -> String -> IO ()
hPutStr Handle
stderr String
msg
Handle -> IO ()
hFlush Handle
stderr
Handle -> String -> IO ()
hPutStr Handle
stderr (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Char
'\r' Char -> String -> String
forall a. a -> [a] -> [a]
: (Int -> Char -> String
forall a. Int -> a -> [a]
replicate (String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
msg) Char
' ') String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\r"
runModule :: FastMode -> PreserveIt -> Interpreter -> Module [Located DocTest] -> Report ()
runModule :: FastMode
-> PreserveIt
-> Interpreter
-> Module [Located DocTest]
-> Report ()
runModule FastMode
fastMode PreserveIt
preserveIt Interpreter
repl (Module String
module_ Maybe [Located DocTest]
setup [[Located DocTest]]
examples) = do
Summary Int
_ Int
_ Int
e0 Int
f0 <- Report Summary
getSummary
Maybe [Located DocTest]
-> ([Located DocTest] -> Report ()) -> Report ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe [Located DocTest]
setup (([Located DocTest] -> Report ()) -> Report ())
-> ([Located DocTest] -> Report ()) -> Report ()
forall a b. (a -> b) -> a -> b
$
PreserveIt
-> Interpreter -> IO () -> [Located DocTest] -> Report ()
runTestGroup PreserveIt
preserveIt Interpreter
repl IO ()
reload
Summary Int
_ Int
_ Int
e1 Int
f1 <- Report Summary
getSummary
Bool -> Report () -> Report ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
e0 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
e1 Bool -> Bool -> Bool
&& Int
f0 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
f1) (Report () -> Report ()) -> Report () -> Report ()
forall a b. (a -> b) -> a -> b
$
[[Located DocTest]]
-> ([Located DocTest] -> Report ()) -> Report ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [[Located DocTest]]
examples (([Located DocTest] -> Report ()) -> Report ())
-> ([Located DocTest] -> Report ()) -> Report ()
forall a b. (a -> b) -> a -> b
$ PreserveIt
-> Interpreter -> IO () -> [Located DocTest] -> Report ()
runTestGroup PreserveIt
preserveIt Interpreter
repl IO ()
setup_
where
reload :: IO ()
reload :: IO ()
reload = do
case FastMode
fastMode of
FastMode
NoFastMode -> IO (Either String String) -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO (Either String String) -> IO ())
-> IO (Either String String) -> IO ()
forall a b. (a -> b) -> a -> b
$ Interpreter -> String -> IO (Either String String)
Interpreter.safeEval Interpreter
repl String
":reload"
FastMode
FastMode -> IO ()
forall (m :: * -> *). Monad m => m ()
pass
IO (Either String String) -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO (Either String String) -> IO ())
-> IO (Either String String) -> IO ()
forall a b. (a -> b) -> a -> b
$ Interpreter -> String -> IO (Either String String)
Interpreter.safeEval Interpreter
repl (String -> IO (Either String String))
-> String -> IO (Either String String)
forall a b. (a -> b) -> a -> b
$ String
":m *" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
module_
case PreserveIt
preserveIt of
PreserveIt
NoPreserveIt -> IO ()
forall (m :: * -> *). Monad m => m ()
pass
PreserveIt
PreserveIt -> do
IO (Either String String) -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO (Either String String) -> IO ())
-> IO (Either String String) -> IO ()
forall a b. (a -> b) -> a -> b
$ Interpreter -> String -> IO (Either String String)
Interpreter.safeEval Interpreter
repl (String -> IO (Either String String))
-> String -> IO (Either String String)
forall a b. (a -> b) -> a -> b
$ String
"()"
setup_ :: IO ()
setup_ :: IO ()
setup_ = do
IO ()
reload
Maybe [Located DocTest] -> ([Located DocTest] -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe [Located DocTest]
setup (([Located DocTest] -> IO ()) -> IO ())
-> ([Located DocTest] -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \[Located DocTest]
l -> [Located DocTest] -> (Located DocTest -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Located DocTest]
l ((Located DocTest -> IO ()) -> IO ())
-> (Located DocTest -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \(Located Location
_ DocTest
x) -> case DocTest
x of
Property String
_ -> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Example String
e ExpectedResult
_ -> IO (Either String String) -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO (Either String String) -> IO ())
-> IO (Either String String) -> IO ()
forall a b. (a -> b) -> a -> b
$ PreserveIt -> Interpreter -> String -> IO (Either String String)
safeEvalWith PreserveIt
preserveIt Interpreter
repl String
e
reportStart :: Location -> Expression -> String -> Report ()
reportStart :: Location -> String -> String -> Report ()
reportStart Location
loc String
expression String
testType = do
String -> Report ()
verboseReport (String -> String -> String -> String -> String
forall r. PrintfType r => String -> r
printf String
"### Started execution at %s.\n### %s:\n%s" (Location -> String
forall a. Show a => a -> String
show Location
loc) String
testType String
expression)
reportFailure :: Location -> Expression -> [String] -> Report ()
reportFailure :: Location -> String -> [String] -> Report ()
reportFailure Location
loc String
expression [String]
err = do
String -> Report ()
report (String -> String -> String -> String
forall r. PrintfType r => String -> r
printf String
"%s: failure in expression `%s'" (Location -> String
forall a. Show a => a -> String
show Location
loc) String
expression)
(String -> Report ()) -> [String] -> Report ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ String -> Report ()
report [String]
err
String -> Report ()
report String
""
Summary -> Report ()
updateSummary (Int -> Int -> Int -> Int -> Summary
Summary Int
0 Int
1 Int
0 Int
1)
reportError :: Location -> Expression -> String -> Report ()
reportError :: Location -> String -> String -> Report ()
reportError Location
loc String
expression String
err = do
String -> Report ()
report (String -> String -> String -> String
forall r. PrintfType r => String -> r
printf String
"%s: error in expression `%s'" (Location -> String
forall a. Show a => a -> String
show Location
loc) String
expression)
String -> Report ()
report String
err
String -> Report ()
report String
""
Summary -> Report ()
updateSummary (Int -> Int -> Int -> Int -> Summary
Summary Int
0 Int
1 Int
1 Int
0)
reportSuccess :: Report ()
reportSuccess :: Report ()
reportSuccess = do
String -> Report ()
verboseReport String
"### Successful!\n"
Summary -> Report ()
updateSummary (Int -> Int -> Int -> Int -> Summary
Summary Int
0 Int
1 Int
0 Int
0)
verboseReport :: String -> Report ()
verboseReport :: String -> Report ()
verboseReport String
msg = (ReportState -> Verbose) -> Report Verbose
forall a. (ReportState -> a) -> Report a
gets ReportState -> Verbose
reportStateVerbose Report Verbose -> (Verbose -> Report ()) -> Report ()
forall a b.
MaybeT (StateT ReportState IO) a
-> (a -> MaybeT (StateT ReportState IO) b)
-> MaybeT (StateT ReportState IO) b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ case
Verbose
NonVerbose -> Report ()
forall (m :: * -> *). Monad m => m ()
pass
Verbose
Verbose -> String -> Report ()
report String
msg
updateSummary :: Summary -> Report ()
updateSummary :: Summary -> Report ()
updateSummary Summary
summary = do
IORef Summary
ref <- (ReportState -> IORef Summary) -> Report (IORef Summary)
forall a. (ReportState -> a) -> Report a
gets ReportState -> IORef Summary
reportStateSummary
IO () -> Report ()
forall a. IO a -> MaybeT (StateT ReportState IO) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Report ()) -> IO () -> Report ()
forall a b. (a -> b) -> a -> b
$ IORef Summary -> (Summary -> Summary) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' IORef Summary
ref ((Summary -> Summary) -> IO ()) -> (Summary -> Summary) -> IO ()
forall a b. (a -> b) -> a -> b
$ Summary -> Summary -> Summary
forall a. Monoid a => a -> a -> a
mappend Summary
summary
Report ()
reportProgress
(ReportState -> FailFast) -> Report FailFast
forall a. (ReportState -> a) -> Report a
gets ReportState -> FailFast
reportStateFailFast Report FailFast -> (FailFast -> Report ()) -> Report ()
forall a b.
MaybeT (StateT ReportState IO) a
-> (a -> MaybeT (StateT ReportState IO) b)
-> MaybeT (StateT ReportState IO) b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ case
FailFast
NoFailFast -> Report ()
forall (m :: * -> *). Monad m => m ()
pass
FailFast
FailFast -> Bool -> Report () -> Report ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Summary -> Bool
isSuccess Summary
summary) Report ()
abort
abort :: Report ()
abort :: Report ()
abort = StateT ReportState IO (Maybe ()) -> Report ()
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (StateT ReportState IO (Maybe ()) -> Report ())
-> StateT ReportState IO (Maybe ()) -> Report ()
forall a b. (a -> b) -> a -> b
$ Maybe () -> StateT ReportState IO (Maybe ())
forall a. a -> StateT ReportState IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe ()
forall a. Maybe a
Nothing
reportProgress :: Report ()
reportProgress :: Report ()
reportProgress = (ReportState -> Verbose) -> Report Verbose
forall a. (ReportState -> a) -> Report a
gets ReportState -> Verbose
reportStateVerbose Report Verbose -> (Verbose -> Report ()) -> Report ()
forall a b.
MaybeT (StateT ReportState IO) a
-> (a -> MaybeT (StateT ReportState IO) b)
-> MaybeT (StateT ReportState IO) b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ case
Verbose
NonVerbose -> do
Summary
summary <- Report Summary
getSummary
String -> Report ()
reportTransient (Summary -> String
formatSummary Summary
summary)
Verbose
Verbose -> Report ()
forall (m :: * -> *). Monad m => m ()
pass
runTestGroup :: PreserveIt -> Interpreter -> IO () -> [Located DocTest] -> Report ()
runTestGroup :: PreserveIt
-> Interpreter -> IO () -> [Located DocTest] -> Report ()
runTestGroup PreserveIt
preserveIt Interpreter
repl IO ()
setup [Located DocTest]
tests = do
IO () -> Report ()
forall a. IO a -> MaybeT (StateT ReportState IO) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO ()
setup
PreserveIt -> Interpreter -> [Located Interaction] -> Report ()
runExampleGroup PreserveIt
preserveIt Interpreter
repl [Located Interaction]
examples
[(Location, String)]
-> ((Location, String) -> Report ()) -> Report ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(Location, String)]
properties (((Location, String) -> Report ()) -> Report ())
-> ((Location, String) -> Report ()) -> Report ()
forall a b. (a -> b) -> a -> b
$ \(Location
loc, String
expression) -> do
PropertyResult
r <- do
IO () -> Report ()
forall a. IO a -> MaybeT (StateT ReportState IO) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO ()
setup
Location -> String -> String -> Report ()
reportStart Location
loc String
expression String
"property"
IO PropertyResult -> MaybeT (StateT ReportState IO) PropertyResult
forall a. IO a -> MaybeT (StateT ReportState IO) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO PropertyResult
-> MaybeT (StateT ReportState IO) PropertyResult)
-> IO PropertyResult
-> MaybeT (StateT ReportState IO) PropertyResult
forall a b. (a -> b) -> a -> b
$ Interpreter -> String -> IO PropertyResult
runProperty Interpreter
repl String
expression
case PropertyResult
r of
PropertyResult
Success ->
Report ()
reportSuccess
Error String
err -> do
Location -> String -> String -> Report ()
reportError Location
loc String
expression String
err
Failure String
msg -> do
Location -> String -> [String] -> Report ()
reportFailure Location
loc String
expression [String
msg]
where
properties :: [(Location, String)]
properties = [(Location
loc, String
p) | Located Location
loc (Property String
p) <- [Located DocTest]
tests]
examples :: [Located Interaction]
examples :: [Located Interaction]
examples = [Location -> Interaction -> Located Interaction
forall a. Location -> a -> Located a
Located Location
loc (String
e, ExpectedResult
r) | Located Location
loc (Example String
e ExpectedResult
r) <- [Located DocTest]
tests]
type Interaction = (Expression, ExpectedResult)
runExampleGroup :: PreserveIt -> Interpreter -> [Located Interaction] -> Report ()
runExampleGroup :: PreserveIt -> Interpreter -> [Located Interaction] -> Report ()
runExampleGroup PreserveIt
preserveIt Interpreter
repl = [Located Interaction] -> Report ()
go
where
go :: [Located Interaction] -> Report ()
go ((Located Location
loc (String
expression, ExpectedResult
expected)) : [Located Interaction]
xs) = do
Location -> String -> String -> Report ()
reportStart Location
loc String
expression String
"example"
Either String [String]
r <- (String -> [String])
-> Either String String -> Either String [String]
forall a b. (a -> b) -> Either String a -> Either String b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> [String]
lines (Either String String -> Either String [String])
-> MaybeT (StateT ReportState IO) (Either String String)
-> MaybeT (StateT ReportState IO) (Either String [String])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO (Either String String)
-> MaybeT (StateT ReportState IO) (Either String String)
forall a. IO a -> MaybeT (StateT ReportState IO) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (PreserveIt -> Interpreter -> String -> IO (Either String String)
safeEvalWith PreserveIt
preserveIt Interpreter
repl String
expression)
case Either String [String]
r of
Left String
err -> do
Location -> String -> String -> Report ()
reportError Location
loc String
expression String
err
Right [String]
actual -> case ExpectedResult -> [String] -> Result
mkResult ExpectedResult
expected [String]
actual of
NotEqual [String]
err -> do
Location -> String -> [String] -> Report ()
reportFailure Location
loc String
expression [String]
err
Result
Equal -> do
Report ()
reportSuccess
[Located Interaction] -> Report ()
go [Located Interaction]
xs
go [] = () -> Report ()
forall a. a -> MaybeT (StateT ReportState IO) a
forall (m :: * -> *) a. Monad m => a -> m a
return ()