hspec-core-2.9.2: src/Test/Hspec/Core/Format.hs
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ExistentialQuantification #-}
-- |
-- Stability: experimental
module Test.Hspec.Core.Format (
Format
, FormatConfig(..)
, Event(..)
, Progress
, Path
, Location(..)
, Seconds(..)
, Item(..)
, Result(..)
, FailureReason(..)
, monadic
) where
import Prelude ()
import Test.Hspec.Core.Compat
import Control.Exception
import Control.Concurrent
import Control.Concurrent.Async (async)
import qualified Control.Concurrent.Async as Async
import Control.Monad.IO.Class
import Test.Hspec.Core.Spec (Progress, Location(..))
import Test.Hspec.Core.Example (FailureReason(..))
import Test.Hspec.Core.Util (Path)
import Test.Hspec.Core.Clock (Seconds(..))
type Format = Event -> IO ()
data Item = Item {
itemLocation :: Maybe Location
, itemDuration :: Seconds
, itemInfo :: String
, itemResult :: Result
} deriving Show
data Result =
Success
| Pending (Maybe Location) (Maybe String)
| Failure (Maybe Location) FailureReason
deriving Show
data Event =
Started
| GroupStarted Path
| GroupDone Path
| Progress Path Progress
| ItemStarted Path
| ItemDone Path Item
| Done [(Path, Item)]
deriving Show
data FormatConfig = FormatConfig {
formatConfigUseColor :: Bool
, formatConfigOutputUnicode :: Bool
, formatConfigUseDiff :: Bool
, formatConfigPrettyPrint :: Bool
, formatConfigPrintTimes :: Bool
, formatConfigHtmlOutput :: Bool
, formatConfigPrintCpuTime :: Bool
, formatConfigUsedSeed :: Integer
, formatConfigExpectedTotalCount :: Int
} deriving (Eq, Show)
data Signal = Ok | NotOk SomeException
monadic :: MonadIO m => (m () -> IO ()) -> (Event -> m ()) -> IO Format
monadic run format = do
mvar <- newEmptyMVar
done <- newEmptyMVar
let
putEvent :: Event -> IO ()
putEvent = putMVar mvar
takeEvent :: MonadIO m => m Event
takeEvent = liftIO $ takeMVar mvar
signal :: MonadIO m => Signal -> m ()
signal = liftIO . putMVar done
wait :: IO Signal
wait = takeMVar done
go = do
event <- takeEvent
format event
case event of
Done {} -> return ()
_ -> do
signal Ok
go
t <- async $ do
(run go >> signal Ok) `catch` (signal . NotOk)
return $ \ event -> do
running <- Async.poll t
case running of
Just _ -> return ()
Nothing -> do
putEvent event
r <- wait
case r of
Ok -> return ()
NotOk err -> do
Async.wait t
throwIO err