{-# LANGUAGE TupleSections #-}
module Test.DejaFu
(
autocheck
, dejafu
, dejafus
, autocheckWay
, dejafuWay
, dejafusWay
, autocheckWithSettings
, dejafuWithSettings
, dejafusWithSettings
, module Test.DejaFu.Settings
, Result(..)
, runTest
, runTestWay
, runTestWithSettings
, Predicate
, ProPredicate(..)
, successful
, alwaysSame
, notAlwaysSame
, abortsNever
, abortsAlways
, abortsSometimes
, deadlocksNever
, deadlocksAlways
, deadlocksSometimes
, exceptionsNever
, exceptionsAlways
, exceptionsSometimes
, representative
, alwaysSameOn
, alwaysSameBy
, notAlwaysSameOn
, notAlwaysSameBy
, alwaysTrue
, somewhereTrue
, alwaysNothing
, somewhereNothing
, gives
, gives'
, Condition(..)
, isAbort
, isDeadlock
, isUncaughtException
, isInvariantFailure
, module Test.DejaFu.Refinement
, Program
, Basic
, ConcT
, ConcIO
, WithSetup
, WithSetupAndTeardown
, withSetup
, withTeardown
, withSetupAndTeardown
, Invariant
, registerInvariant
, inspectIORef
, inspectMVar
, inspectTVar
) where
import Control.Arrow (first)
import Control.DeepSeq (NFData(..))
import Control.Monad (unless, when)
import Control.Monad.IO.Class (MonadIO(..))
import Data.Either (isLeft)
import Data.Function (on)
import Data.List (intercalate, intersperse, partition)
import Data.Maybe (catMaybes, isJust, isNothing, mapMaybe)
import Data.Profunctor (Profunctor(..))
import System.Environment (lookupEnv)
import Test.DejaFu.Conc
import Test.DejaFu.Internal
import Test.DejaFu.Refinement
import Test.DejaFu.SCT
import Test.DejaFu.Settings
import Test.DejaFu.Types
import Test.DejaFu.Utils
autocheck :: (MonadDejaFu n, MonadIO n, Eq a, Show a)
=> Program pty n a
-> n Bool
autocheck :: forall (n :: * -> *) a pty.
(MonadDejaFu n, MonadIO n, Eq a, Show a) =>
Program pty n a -> n Bool
autocheck = Settings n a -> Program pty n a -> n Bool
forall (n :: * -> *) a pty.
(MonadDejaFu n, MonadIO n, Eq a, Show a) =>
Settings n a -> Program pty n a -> n Bool
autocheckWithSettings Settings n a
forall (n :: * -> *) a. Applicative n => Settings n a
defaultSettings
autocheckWay :: (MonadDejaFu n, MonadIO n, Eq a, Show a)
=> Way
-> MemType
-> Program pty n a
-> n Bool
autocheckWay :: forall (n :: * -> *) a pty.
(MonadDejaFu n, MonadIO n, Eq a, Show a) =>
Way -> MemType -> Program pty n a -> n Bool
autocheckWay Way
way = Settings n a -> Program pty n a -> n Bool
forall (n :: * -> *) a pty.
(MonadDejaFu n, MonadIO n, Eq a, Show a) =>
Settings n a -> Program pty n a -> n Bool
autocheckWithSettings (Settings n a -> Program pty n a -> n Bool)
-> (MemType -> Settings n a)
-> MemType
-> Program pty n a
-> n Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Way -> MemType -> Settings n a
forall (n :: * -> *) a.
Applicative n =>
Way -> MemType -> Settings n a
fromWayAndMemType Way
way
autocheckWithSettings :: (MonadDejaFu n, MonadIO n, Eq a, Show a)
=> Settings n a
-> Program pty n a
-> n Bool
autocheckWithSettings :: forall (n :: * -> *) a pty.
(MonadDejaFu n, MonadIO n, Eq a, Show a) =>
Settings n a -> Program pty n a -> n Bool
autocheckWithSettings Settings n a
settings = Settings n a
-> [(String, ProPredicate a a)] -> Program pty n a -> n Bool
forall (n :: * -> *) b a pty.
(MonadDejaFu n, MonadIO n, Show b) =>
Settings n a
-> [(String, ProPredicate a b)] -> Program pty n a -> n Bool
dejafusWithSettings Settings n a
settings
[ (String
"Successful", ProPredicate a a -> ProPredicate a a
forall b a. Eq b => ProPredicate a b -> ProPredicate a b
representative ProPredicate a a
forall a. Predicate a
successful)
, (String
"Deterministic", ProPredicate a a -> ProPredicate a a
forall b a. Eq b => ProPredicate a b -> ProPredicate a b
representative ProPredicate a a
forall a. Eq a => Predicate a
alwaysSame)
]
dejafu :: (MonadDejaFu n, MonadIO n, Show b)
=> String
-> ProPredicate a b
-> Program pty n a
-> n Bool
dejafu :: forall (n :: * -> *) b a pty.
(MonadDejaFu n, MonadIO n, Show b) =>
String -> ProPredicate a b -> Program pty n a -> n Bool
dejafu = Settings n a
-> String -> ProPredicate a b -> Program pty n a -> n Bool
forall (n :: * -> *) b a pty.
(MonadDejaFu n, MonadIO n, Show b) =>
Settings n a
-> String -> ProPredicate a b -> Program pty n a -> n Bool
dejafuWithSettings Settings n a
forall (n :: * -> *) a. Applicative n => Settings n a
defaultSettings
dejafuWay :: (MonadDejaFu n, MonadIO n, Show b)
=> Way
-> MemType
-> String
-> ProPredicate a b
-> Program pty n a
-> n Bool
dejafuWay :: forall (n :: * -> *) b a pty.
(MonadDejaFu n, MonadIO n, Show b) =>
Way
-> MemType
-> String
-> ProPredicate a b
-> Program pty n a
-> n Bool
dejafuWay Way
way = Settings n a
-> String -> ProPredicate a b -> Program pty n a -> n Bool
forall (n :: * -> *) b a pty.
(MonadDejaFu n, MonadIO n, Show b) =>
Settings n a
-> String -> ProPredicate a b -> Program pty n a -> n Bool
dejafuWithSettings (Settings n a
-> String -> ProPredicate a b -> Program pty n a -> n Bool)
-> (MemType -> Settings n a)
-> MemType
-> String
-> ProPredicate a b
-> Program pty n a
-> n Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Way -> MemType -> Settings n a
forall (n :: * -> *) a.
Applicative n =>
Way -> MemType -> Settings n a
fromWayAndMemType Way
way
dejafuWithSettings :: (MonadDejaFu n, MonadIO n, Show b)
=> Settings n a
-> String
-> ProPredicate a b
-> Program pty n a
-> n Bool
dejafuWithSettings :: forall (n :: * -> *) b a pty.
(MonadDejaFu n, MonadIO n, Show b) =>
Settings n a
-> String -> ProPredicate a b -> Program pty n a -> n Bool
dejafuWithSettings Settings n a
settings String
name ProPredicate a b
test =
Settings n a
-> [(String, ProPredicate a b)] -> Program pty n a -> n Bool
forall (n :: * -> *) b a pty.
(MonadDejaFu n, MonadIO n, Show b) =>
Settings n a
-> [(String, ProPredicate a b)] -> Program pty n a -> n Bool
dejafusWithSettings Settings n a
settings [(String
name, ProPredicate a b
test)]
dejafus :: (MonadDejaFu n, MonadIO n, Show b)
=> [(String, ProPredicate a b)]
-> Program pty n a
-> n Bool
dejafus :: forall (n :: * -> *) b a pty.
(MonadDejaFu n, MonadIO n, Show b) =>
[(String, ProPredicate a b)] -> Program pty n a -> n Bool
dejafus = Settings n a
-> [(String, ProPredicate a b)] -> Program pty n a -> n Bool
forall (n :: * -> *) b a pty.
(MonadDejaFu n, MonadIO n, Show b) =>
Settings n a
-> [(String, ProPredicate a b)] -> Program pty n a -> n Bool
dejafusWithSettings Settings n a
forall (n :: * -> *) a. Applicative n => Settings n a
defaultSettings
dejafusWay :: (MonadDejaFu n, MonadIO n, Show b)
=> Way
-> MemType
-> [(String, ProPredicate a b)]
-> Program pty n a
-> n Bool
dejafusWay :: forall (n :: * -> *) b a pty.
(MonadDejaFu n, MonadIO n, Show b) =>
Way
-> MemType
-> [(String, ProPredicate a b)]
-> Program pty n a
-> n Bool
dejafusWay Way
way = Settings n a
-> [(String, ProPredicate a b)] -> Program pty n a -> n Bool
forall (n :: * -> *) b a pty.
(MonadDejaFu n, MonadIO n, Show b) =>
Settings n a
-> [(String, ProPredicate a b)] -> Program pty n a -> n Bool
dejafusWithSettings (Settings n a
-> [(String, ProPredicate a b)] -> Program pty n a -> n Bool)
-> (MemType -> Settings n a)
-> MemType
-> [(String, ProPredicate a b)]
-> Program pty n a
-> n Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Way -> MemType -> Settings n a
forall (n :: * -> *) a.
Applicative n =>
Way -> MemType -> Settings n a
fromWayAndMemType Way
way
dejafusWithSettings :: (MonadDejaFu n, MonadIO n, Show b)
=> Settings n a
-> [(String, ProPredicate a b)]
-> Program pty n a
-> n Bool
dejafusWithSettings :: forall (n :: * -> *) b a pty.
(MonadDejaFu n, MonadIO n, Show b) =>
Settings n a
-> [(String, ProPredicate a b)] -> Program pty n a -> n Bool
dejafusWithSettings Settings n a
settings [(String, ProPredicate a b)]
tests Program pty n a
conc = do
[(Either Condition a, Trace)]
traces <- Settings n a -> Program pty n a -> n [(Either Condition a, Trace)]
forall (n :: * -> *) a pty.
MonadDejaFu n =>
Settings n a -> Program pty n a -> n [(Either Condition a, Trace)]
runSCTWithSettings (Lens' (Settings n a) (Maybe (Either Condition a -> Maybe Discard))
-> Maybe (Either Condition a -> Maybe Discard)
-> Settings n a
-> Settings n a
forall s a. Lens' s a -> a -> s -> s
set (Maybe (Either Condition a -> Maybe Discard)
-> f (Maybe (Either Condition a -> Maybe Discard)))
-> Settings n a -> f (Settings n a)
Lens' (Settings n a) (Maybe (Either Condition a -> Maybe Discard))
forall (n :: * -> *) a (f :: * -> *).
Functor f =>
(Maybe (Either Condition a -> Maybe Discard)
-> f (Maybe (Either Condition a -> Maybe Discard)))
-> Settings n a -> f (Settings n a)
ldiscard ((Either Condition a -> Maybe Discard)
-> Maybe (Either Condition a -> Maybe Discard)
forall a. a -> Maybe a
Just Either Condition a -> Maybe Discard
discarder) Settings n a
settings) Program pty n a
conc
[Bool]
results <- ((String, ProPredicate a b) -> n Bool)
-> [(String, ProPredicate a b)] -> n [Bool]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (\(String
name, ProPredicate a b
test) -> IO Bool -> n Bool
forall a. IO a -> n a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Bool -> n Bool) -> (Result b -> IO Bool) -> Result b -> n Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Result b -> IO Bool
forall a. Show a => String -> Result a -> IO Bool
doTest String
name (Result b -> n Bool) -> Result b -> n Bool
forall a b. (a -> b) -> a -> b
$ ProPredicate a b -> [(Either Condition a, Trace)] -> Result b
forall {a} {b}.
ProPredicate a b -> [(Either Condition a, Trace)] -> Result b
chk ProPredicate a b
test [(Either Condition a, Trace)]
traces) [(String, ProPredicate a b)]
tests
Bool -> n Bool
forall a. a -> n a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and [Bool]
results)
where
discarder :: Either Condition a -> Maybe Discard
discarder = ((Either Condition a -> Maybe Discard)
-> Either Condition a -> Maybe Discard)
-> ((Either Condition a -> Maybe Discard)
-> (Either Condition a -> Maybe Discard)
-> Either Condition a
-> Maybe Discard)
-> Maybe (Either Condition a -> Maybe Discard)
-> (Either Condition a -> Maybe Discard)
-> Either Condition a
-> Maybe Discard
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Either Condition a -> Maybe Discard)
-> Either Condition a -> Maybe Discard
forall a. a -> a
id (Either Condition a -> Maybe Discard)
-> (Either Condition a -> Maybe Discard)
-> Either Condition a
-> Maybe Discard
forall a.
(Either Condition a -> Maybe Discard)
-> (Either Condition a -> Maybe Discard)
-> Either Condition a
-> Maybe Discard
strengthenDiscard (Lens' (Settings n a) (Maybe (Either Condition a -> Maybe Discard))
-> Settings n a -> Maybe (Either Condition a -> Maybe Discard)
forall s a. Lens' s a -> s -> a
get (Maybe (Either Condition a -> Maybe Discard)
-> f (Maybe (Either Condition a -> Maybe Discard)))
-> Settings n a -> f (Settings n a)
Lens' (Settings n a) (Maybe (Either Condition a -> Maybe Discard))
forall (n :: * -> *) a (f :: * -> *).
Functor f =>
(Maybe (Either Condition a -> Maybe Discard)
-> f (Maybe (Either Condition a -> Maybe Discard)))
-> Settings n a -> f (Settings n a)
ldiscard Settings n a
settings) ((Either Condition a -> Maybe Discard)
-> Either Condition a -> Maybe Discard)
-> (Either Condition a -> Maybe Discard)
-> Either Condition a
-> Maybe Discard
forall a b. (a -> b) -> a -> b
$ ((String, ProPredicate a b)
-> (Either Condition a -> Maybe Discard)
-> Either Condition a
-> Maybe Discard)
-> (Either Condition a -> Maybe Discard)
-> [(String, ProPredicate a b)]
-> Either Condition a
-> Maybe Discard
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr
((Either Condition a -> Maybe Discard)
-> (Either Condition a -> Maybe Discard)
-> Either Condition a
-> Maybe Discard
forall a.
(Either Condition a -> Maybe Discard)
-> (Either Condition a -> Maybe Discard)
-> Either Condition a
-> Maybe Discard
weakenDiscard ((Either Condition a -> Maybe Discard)
-> (Either Condition a -> Maybe Discard)
-> Either Condition a
-> Maybe Discard)
-> ((String, ProPredicate a b)
-> Either Condition a -> Maybe Discard)
-> (String, ProPredicate a b)
-> (Either Condition a -> Maybe Discard)
-> Either Condition a
-> Maybe Discard
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProPredicate a b -> Either Condition a -> Maybe Discard
forall a b. ProPredicate a b -> Either Condition a -> Maybe Discard
pdiscard (ProPredicate a b -> Either Condition a -> Maybe Discard)
-> ((String, ProPredicate a b) -> ProPredicate a b)
-> (String, ProPredicate a b)
-> Either Condition a
-> Maybe Discard
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String, ProPredicate a b) -> ProPredicate a b
forall a b. (a, b) -> b
snd)
(Maybe Discard -> Either Condition a -> Maybe Discard
forall a b. a -> b -> a
const (Discard -> Maybe Discard
forall a. a -> Maybe a
Just Discard
DiscardResultAndTrace))
[(String, ProPredicate a b)]
tests
chk :: ProPredicate a b -> [(Either Condition a, Trace)] -> Result b
chk ProPredicate a b
p [(Either Condition a, Trace)]
rs
| Int -> [(Either Condition a, Trace)] -> Bool
forall a. Int -> [a] -> Bool
moreThan Int
1 [(Either Condition a, Trace)]
rs =
let go :: (Either Condition a, [a]) -> Maybe (Either Condition a, [a])
go r :: (Either Condition a, [a])
r@(Either Condition a
efa, [a]
_) = case ProPredicate a b -> Either Condition a -> Maybe Discard
forall a b. ProPredicate a b -> Either Condition a -> Maybe Discard
pdiscard ProPredicate a b
p Either Condition a
efa of
Just Discard
DiscardResultAndTrace -> Maybe (Either Condition a, [a])
forall a. Maybe a
Nothing
Just Discard
DiscardTrace -> (Either Condition a, [a]) -> Maybe (Either Condition a, [a])
forall a. a -> Maybe a
Just (Either Condition a
efa, [])
Maybe Discard
Nothing -> (Either Condition a, [a]) -> Maybe (Either Condition a, [a])
forall a. a -> Maybe a
Just (Either Condition a, [a])
r
in ProPredicate a b -> [(Either Condition a, Trace)] -> Result b
forall {a} {b}.
ProPredicate a b -> [(Either Condition a, Trace)] -> Result b
peval ProPredicate a b
p (((Either Condition a, Trace) -> Maybe (Either Condition a, Trace))
-> [(Either Condition a, Trace)] -> [(Either Condition a, Trace)]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (Either Condition a, Trace) -> Maybe (Either Condition a, Trace)
forall {a}.
(Either Condition a, [a]) -> Maybe (Either Condition a, [a])
go [(Either Condition a, Trace)]
rs)
| Bool
otherwise = ProPredicate a b -> [(Either Condition a, Trace)] -> Result b
forall {a} {b}.
ProPredicate a b -> [(Either Condition a, Trace)] -> Result b
peval ProPredicate a b
p [(Either Condition a, Trace)]
rs
data Result a = Result
{ forall a. Result a -> Bool
_pass :: Bool
, forall a. Result a -> [(Either Condition a, Trace)]
_failures :: [(Either Condition a, Trace)]
, forall a. Result a -> String
_failureMsg :: String
} deriving (Result a -> Result a -> Bool
(Result a -> Result a -> Bool)
-> (Result a -> Result a -> Bool) -> Eq (Result a)
forall a. Eq a => Result a -> Result a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => Result a -> Result a -> Bool
== :: Result a -> Result a -> Bool
$c/= :: forall a. Eq a => Result a -> Result a -> Bool
/= :: Result a -> Result a -> Bool
Eq, Int -> Result a -> ShowS
[Result a] -> ShowS
Result a -> String
(Int -> Result a -> ShowS)
-> (Result a -> String) -> ([Result a] -> ShowS) -> Show (Result a)
forall a. Show a => Int -> Result a -> ShowS
forall a. Show a => [Result a] -> ShowS
forall a. Show a => Result a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> Result a -> ShowS
showsPrec :: Int -> Result a -> ShowS
$cshow :: forall a. Show a => Result a -> String
show :: Result a -> String
$cshowList :: forall a. Show a => [Result a] -> ShowS
showList :: [Result a] -> ShowS
Show)
instance NFData a => NFData (Result a) where
rnf :: Result a -> ()
rnf Result a
r = (Bool, [(Either Condition a, Trace)], String) -> ()
forall a. NFData a => a -> ()
rnf ( Result a -> Bool
forall a. Result a -> Bool
_pass Result a
r
, Result a -> [(Either Condition a, Trace)]
forall a. Result a -> [(Either Condition a, Trace)]
_failures Result a
r
, Result a -> String
forall a. Result a -> String
_failureMsg Result a
r
)
defaultFail :: [(Either Condition a, Trace)] -> Result a
defaultFail :: forall a. [(Either Condition a, Trace)] -> Result a
defaultFail [(Either Condition a, Trace)]
failures = Bool -> [(Either Condition a, Trace)] -> String -> Result a
forall a.
Bool -> [(Either Condition a, Trace)] -> String -> Result a
Result Bool
False [(Either Condition a, Trace)]
failures String
""
defaultPass :: Result a
defaultPass :: forall a. Result a
defaultPass = Bool -> [(Either Condition a, Trace)] -> String -> Result a
forall a.
Bool -> [(Either Condition a, Trace)] -> String -> Result a
Result Bool
True [] String
""
instance Functor Result where
fmap :: forall a b. (a -> b) -> Result a -> Result b
fmap a -> b
f Result a
r = Result a
r { _failures = map (first $ fmap f) $ _failures r }
instance Foldable Result where
foldMap :: forall m a. Monoid m => (a -> m) -> Result a -> m
foldMap a -> m
f Result a
r = (a -> m) -> [a] -> m
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap a -> m
f [a
a | (Right a
a, Trace
_) <- Result a -> [(Either Condition a, Trace)]
forall a. Result a -> [(Either Condition a, Trace)]
_failures Result a
r]
runTest :: MonadDejaFu n
=> ProPredicate a b
-> Program pty n a
-> n (Result b)
runTest :: forall (n :: * -> *) a b pty.
MonadDejaFu n =>
ProPredicate a b -> Program pty n a -> n (Result b)
runTest = Settings n a -> ProPredicate a b -> Program pty n a -> n (Result b)
forall (n :: * -> *) a b pty.
MonadDejaFu n =>
Settings n a -> ProPredicate a b -> Program pty n a -> n (Result b)
runTestWithSettings Settings n a
forall (n :: * -> *) a. Applicative n => Settings n a
defaultSettings
runTestWay :: MonadDejaFu n
=> Way
-> MemType
-> ProPredicate a b
-> Program pty n a
-> n (Result b)
runTestWay :: forall (n :: * -> *) a b pty.
MonadDejaFu n =>
Way
-> MemType -> ProPredicate a b -> Program pty n a -> n (Result b)
runTestWay Way
way = Settings n a -> ProPredicate a b -> Program pty n a -> n (Result b)
forall (n :: * -> *) a b pty.
MonadDejaFu n =>
Settings n a -> ProPredicate a b -> Program pty n a -> n (Result b)
runTestWithSettings (Settings n a
-> ProPredicate a b -> Program pty n a -> n (Result b))
-> (MemType -> Settings n a)
-> MemType
-> ProPredicate a b
-> Program pty n a
-> n (Result b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Way -> MemType -> Settings n a
forall (n :: * -> *) a.
Applicative n =>
Way -> MemType -> Settings n a
fromWayAndMemType Way
way
runTestWithSettings :: MonadDejaFu n
=> Settings n a
-> ProPredicate a b
-> Program pty n a
-> n (Result b)
runTestWithSettings :: forall (n :: * -> *) a b pty.
MonadDejaFu n =>
Settings n a -> ProPredicate a b -> Program pty n a -> n (Result b)
runTestWithSettings Settings n a
settings ProPredicate a b
p Program pty n a
conc =
let discarder :: Either Condition a -> Maybe Discard
discarder = ((Either Condition a -> Maybe Discard)
-> Either Condition a -> Maybe Discard)
-> ((Either Condition a -> Maybe Discard)
-> (Either Condition a -> Maybe Discard)
-> Either Condition a
-> Maybe Discard)
-> Maybe (Either Condition a -> Maybe Discard)
-> (Either Condition a -> Maybe Discard)
-> Either Condition a
-> Maybe Discard
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Either Condition a -> Maybe Discard)
-> Either Condition a -> Maybe Discard
forall a. a -> a
id (Either Condition a -> Maybe Discard)
-> (Either Condition a -> Maybe Discard)
-> Either Condition a
-> Maybe Discard
forall a.
(Either Condition a -> Maybe Discard)
-> (Either Condition a -> Maybe Discard)
-> Either Condition a
-> Maybe Discard
strengthenDiscard (Lens' (Settings n a) (Maybe (Either Condition a -> Maybe Discard))
-> Settings n a -> Maybe (Either Condition a -> Maybe Discard)
forall s a. Lens' s a -> s -> a
get (Maybe (Either Condition a -> Maybe Discard)
-> f (Maybe (Either Condition a -> Maybe Discard)))
-> Settings n a -> f (Settings n a)
Lens' (Settings n a) (Maybe (Either Condition a -> Maybe Discard))
forall (n :: * -> *) a (f :: * -> *).
Functor f =>
(Maybe (Either Condition a -> Maybe Discard)
-> f (Maybe (Either Condition a -> Maybe Discard)))
-> Settings n a -> f (Settings n a)
ldiscard Settings n a
settings) (ProPredicate a b -> Either Condition a -> Maybe Discard
forall a b. ProPredicate a b -> Either Condition a -> Maybe Discard
pdiscard ProPredicate a b
p)
in ProPredicate a b -> [(Either Condition a, Trace)] -> Result b
forall {a} {b}.
ProPredicate a b -> [(Either Condition a, Trace)] -> Result b
peval ProPredicate a b
p ([(Either Condition a, Trace)] -> Result b)
-> n [(Either Condition a, Trace)] -> n (Result b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Settings n a -> Program pty n a -> n [(Either Condition a, Trace)]
forall (n :: * -> *) a pty.
MonadDejaFu n =>
Settings n a -> Program pty n a -> n [(Either Condition a, Trace)]
runSCTWithSettings (Lens' (Settings n a) (Maybe (Either Condition a -> Maybe Discard))
-> Maybe (Either Condition a -> Maybe Discard)
-> Settings n a
-> Settings n a
forall s a. Lens' s a -> a -> s -> s
set (Maybe (Either Condition a -> Maybe Discard)
-> f (Maybe (Either Condition a -> Maybe Discard)))
-> Settings n a -> f (Settings n a)
Lens' (Settings n a) (Maybe (Either Condition a -> Maybe Discard))
forall (n :: * -> *) a (f :: * -> *).
Functor f =>
(Maybe (Either Condition a -> Maybe Discard)
-> f (Maybe (Either Condition a -> Maybe Discard)))
-> Settings n a -> f (Settings n a)
ldiscard ((Either Condition a -> Maybe Discard)
-> Maybe (Either Condition a -> Maybe Discard)
forall a. a -> Maybe a
Just Either Condition a -> Maybe Discard
discarder) Settings n a
settings) Program pty n a
conc
type Predicate a = ProPredicate a a
data ProPredicate a b = ProPredicate
{ forall a b. ProPredicate a b -> Either Condition a -> Maybe Discard
pdiscard :: Either Condition a -> Maybe Discard
, forall {a} {b}.
ProPredicate a b -> [(Either Condition a, Trace)] -> Result b
peval :: [(Either Condition a, Trace)] -> Result b
}
instance Profunctor ProPredicate where
dimap :: forall a b c d.
(a -> b) -> (c -> d) -> ProPredicate b c -> ProPredicate a d
dimap a -> b
f c -> d
g ProPredicate b c
p = ProPredicate
{ pdiscard :: Either Condition a -> Maybe Discard
pdiscard = ProPredicate b c -> Either Condition b -> Maybe Discard
forall a b. ProPredicate a b -> Either Condition a -> Maybe Discard
pdiscard ProPredicate b c
p (Either Condition b -> Maybe Discard)
-> (Either Condition a -> Either Condition b)
-> Either Condition a
-> Maybe Discard
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> b) -> Either Condition a -> Either Condition b
forall a b. (a -> b) -> Either Condition a -> Either Condition b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f
, peval :: [(Either Condition a, Trace)] -> Result d
peval = (c -> d) -> Result c -> Result d
forall a b. (a -> b) -> Result a -> Result b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap c -> d
g (Result c -> Result d)
-> ([(Either Condition a, Trace)] -> Result c)
-> [(Either Condition a, Trace)]
-> Result d
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProPredicate b c -> [(Either Condition b, Trace)] -> Result c
forall {a} {b}.
ProPredicate a b -> [(Either Condition a, Trace)] -> Result b
peval ProPredicate b c
p ([(Either Condition b, Trace)] -> Result c)
-> ([(Either Condition a, Trace)] -> [(Either Condition b, Trace)])
-> [(Either Condition a, Trace)]
-> Result c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Either Condition a, Trace) -> (Either Condition b, Trace))
-> [(Either Condition a, Trace)] -> [(Either Condition b, Trace)]
forall a b. (a -> b) -> [a] -> [b]
map ((Either Condition a -> Either Condition b)
-> (Either Condition a, Trace) -> (Either Condition b, Trace)
forall b c d. (b -> c) -> (b, d) -> (c, d)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first ((a -> b) -> Either Condition a -> Either Condition b
forall a b. (a -> b) -> Either Condition a -> Either Condition b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f))
}
instance Functor (ProPredicate x) where
fmap :: forall a b. (a -> b) -> ProPredicate x a -> ProPredicate x b
fmap = (x -> x) -> (a -> b) -> ProPredicate x a -> ProPredicate x b
forall a b c d.
(a -> b) -> (c -> d) -> ProPredicate b c -> ProPredicate a d
forall (p :: * -> * -> *) a b c d.
Profunctor p =>
(a -> b) -> (c -> d) -> p b c -> p a d
dimap x -> x
forall a. a -> a
id
representative :: Eq b => ProPredicate a b -> ProPredicate a b
representative :: forall b a. Eq b => ProPredicate a b -> ProPredicate a b
representative ProPredicate a b
p = ProPredicate a b
p
{ peval = \[(Either Condition a, Trace)]
xs ->
let result :: Result b
result = ProPredicate a b -> [(Either Condition a, Trace)] -> Result b
forall {a} {b}.
ProPredicate a b -> [(Either Condition a, Trace)] -> Result b
peval ProPredicate a b
p [(Either Condition a, Trace)]
xs
in Result b
result { _failures = simplestsBy (==) (_failures result) }
}
successful :: Predicate a
successful :: forall a. Predicate a
successful = (Either Condition a -> Bool) -> Predicate a
forall a. (Either Condition a -> Bool) -> Predicate a
alwaysTrue ((Condition -> Bool) -> (a -> Bool) -> Either Condition a -> Bool
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Bool -> Condition -> Bool
forall a b. a -> b -> a
const Bool
False) (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
True))
abortsNever :: Predicate a
abortsNever :: forall a. Predicate a
abortsNever = (Either Condition a -> Bool) -> Predicate a
forall a. (Either Condition a -> Bool) -> Predicate a
alwaysTrue (Bool -> Bool
not (Bool -> Bool)
-> (Either Condition a -> Bool) -> Either Condition a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Condition -> Bool) -> (a -> Bool) -> Either Condition a -> Bool
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Condition -> Condition -> Bool
forall a. Eq a => a -> a -> Bool
==Condition
Abort) (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
False))
abortsAlways :: Predicate a
abortsAlways :: forall a. Predicate a
abortsAlways = (Either Condition a -> Bool) -> Predicate a
forall a. (Either Condition a -> Bool) -> Predicate a
alwaysTrue ((Either Condition a -> Bool) -> Predicate a)
-> (Either Condition a -> Bool) -> Predicate a
forall a b. (a -> b) -> a -> b
$ (Condition -> Bool) -> (a -> Bool) -> Either Condition a -> Bool
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Condition -> Condition -> Bool
forall a. Eq a => a -> a -> Bool
==Condition
Abort) (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
False)
abortsSometimes :: Predicate a
abortsSometimes :: forall a. Predicate a
abortsSometimes = (Either Condition a -> Bool) -> Predicate a
forall a. (Either Condition a -> Bool) -> Predicate a
somewhereTrue ((Either Condition a -> Bool) -> Predicate a)
-> (Either Condition a -> Bool) -> Predicate a
forall a b. (a -> b) -> a -> b
$ (Condition -> Bool) -> (a -> Bool) -> Either Condition a -> Bool
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Condition -> Condition -> Bool
forall a. Eq a => a -> a -> Bool
==Condition
Abort) (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
False)
deadlocksNever :: Predicate a
deadlocksNever :: forall a. Predicate a
deadlocksNever = (Either Condition a -> Bool) -> Predicate a
forall a. (Either Condition a -> Bool) -> Predicate a
alwaysTrue (Bool -> Bool
not (Bool -> Bool)
-> (Either Condition a -> Bool) -> Either Condition a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Condition -> Bool) -> (a -> Bool) -> Either Condition a -> Bool
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Condition -> Bool
isDeadlock (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
False))
deadlocksAlways :: Predicate a
deadlocksAlways :: forall a. Predicate a
deadlocksAlways = (Either Condition a -> Bool) -> Predicate a
forall a. (Either Condition a -> Bool) -> Predicate a
alwaysTrue ((Either Condition a -> Bool) -> Predicate a)
-> (Either Condition a -> Bool) -> Predicate a
forall a b. (a -> b) -> a -> b
$ (Condition -> Bool) -> (a -> Bool) -> Either Condition a -> Bool
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Condition -> Bool
isDeadlock (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
False)
deadlocksSometimes :: Predicate a
deadlocksSometimes :: forall a. Predicate a
deadlocksSometimes = (Either Condition a -> Bool) -> Predicate a
forall a. (Either Condition a -> Bool) -> Predicate a
somewhereTrue ((Either Condition a -> Bool) -> Predicate a)
-> (Either Condition a -> Bool) -> Predicate a
forall a b. (a -> b) -> a -> b
$ (Condition -> Bool) -> (a -> Bool) -> Either Condition a -> Bool
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Condition -> Bool
isDeadlock (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
False)
exceptionsNever :: Predicate a
exceptionsNever :: forall a. Predicate a
exceptionsNever = (Either Condition a -> Bool) -> Predicate a
forall a. (Either Condition a -> Bool) -> Predicate a
alwaysTrue (Bool -> Bool
not (Bool -> Bool)
-> (Either Condition a -> Bool) -> Either Condition a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Condition -> Bool) -> (a -> Bool) -> Either Condition a -> Bool
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Condition -> Bool
isUncaughtException (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
False))
exceptionsAlways :: Predicate a
exceptionsAlways :: forall a. Predicate a
exceptionsAlways = (Either Condition a -> Bool) -> Predicate a
forall a. (Either Condition a -> Bool) -> Predicate a
alwaysTrue ((Either Condition a -> Bool) -> Predicate a)
-> (Either Condition a -> Bool) -> Predicate a
forall a b. (a -> b) -> a -> b
$ (Condition -> Bool) -> (a -> Bool) -> Either Condition a -> Bool
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Condition -> Bool
isUncaughtException (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
False)
exceptionsSometimes :: Predicate a
exceptionsSometimes :: forall a. Predicate a
exceptionsSometimes = (Either Condition a -> Bool) -> Predicate a
forall a. (Either Condition a -> Bool) -> Predicate a
somewhereTrue ((Either Condition a -> Bool) -> Predicate a)
-> (Either Condition a -> Bool) -> Predicate a
forall a b. (a -> b) -> a -> b
$ (Condition -> Bool) -> (a -> Bool) -> Either Condition a -> Bool
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Condition -> Bool
isUncaughtException (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
False)
alwaysSame :: Eq a => Predicate a
alwaysSame :: forall a. Eq a => Predicate a
alwaysSame = (a -> a -> Bool) -> Predicate a
forall a. (a -> a -> Bool) -> Predicate a
alwaysSameBy a -> a -> Bool
forall a. Eq a => a -> a -> Bool
(==)
alwaysSameOn :: Eq b => (a -> b) -> Predicate a
alwaysSameOn :: forall b a. Eq b => (a -> b) -> Predicate a
alwaysSameOn a -> b
f = (a -> a -> Bool) -> Predicate a
forall a. (a -> a -> Bool) -> Predicate a
alwaysSameBy (b -> b -> Bool
forall a. Eq a => a -> a -> Bool
(==) (b -> b -> Bool) -> (a -> b) -> a -> a -> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` a -> b
f)
alwaysSameBy :: (a -> a -> Bool) -> Predicate a
alwaysSameBy :: forall a. (a -> a -> Bool) -> Predicate a
alwaysSameBy a -> a -> Bool
f = ProPredicate
{ pdiscard :: Either Condition a -> Maybe Discard
pdiscard = Maybe Discard -> Either Condition a -> Maybe Discard
forall a b. a -> b -> a
const Maybe Discard
forall a. Maybe a
Nothing
, peval :: [(Either Condition a, Trace)] -> Result a
peval = \[(Either Condition a, Trace)]
xs ->
let ([(Either Condition a, Trace)]
failures, [(Either Condition a, Trace)]
successes) = ((Either Condition a, Trace) -> Bool)
-> [(Either Condition a, Trace)]
-> ([(Either Condition a, Trace)], [(Either Condition a, Trace)])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (Either Condition a -> Bool
forall a b. Either a b -> Bool
isLeft (Either Condition a -> Bool)
-> ((Either Condition a, Trace) -> Either Condition a)
-> (Either Condition a, Trace)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Either Condition a, Trace) -> Either Condition a
forall a b. (a, b) -> a
fst) [(Either Condition a, Trace)]
xs
simpleSuccesses :: [(Either Condition a, Trace)]
simpleSuccesses = (Either Condition a -> Either Condition a -> Bool)
-> [(Either Condition a, Trace)] -> [(Either Condition a, Trace)]
forall x. (x -> x -> Bool) -> [(x, Trace)] -> [(x, Trace)]
simplestsBy (a -> a -> Bool
f (a -> a -> Bool)
-> (Either Condition a -> a)
-> Either Condition a
-> Either Condition a
-> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Either Condition a -> a
forall a b. HasCallStack => Either a b -> b
efromRight) [(Either Condition a, Trace)]
successes
simpleFailures :: [(Either Condition a, Trace)]
simpleFailures = (Either Condition a -> Either Condition a -> Bool)
-> [(Either Condition a, Trace)] -> [(Either Condition a, Trace)]
forall x. (x -> x -> Bool) -> [(x, Trace)] -> [(x, Trace)]
simplestsBy (Condition -> Condition -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Condition -> Condition -> Bool)
-> (Either Condition a -> Condition)
-> Either Condition a
-> Either Condition a
-> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Either Condition a -> Condition
forall a b. HasCallStack => Either a b -> a
efromLeft) [(Either Condition a, Trace)]
failures
in case ([(Either Condition a, Trace)]
simpleFailures, [(Either Condition a, Trace)]
simpleSuccesses) of
([], []) -> Result a
forall a. Result a
defaultPass
([], [(Either Condition a, Trace)
_]) -> Result a
forall a. Result a
defaultPass
([(Either Condition a, Trace)]
_, [(Either Condition a, Trace)]
_) -> [(Either Condition a, Trace)] -> Result a
forall a. [(Either Condition a, Trace)] -> Result a
defaultFail ([(Either Condition a, Trace)]
simpleFailures [(Either Condition a, Trace)]
-> [(Either Condition a, Trace)] -> [(Either Condition a, Trace)]
forall a. [a] -> [a] -> [a]
++ [(Either Condition a, Trace)]
simpleSuccesses)
}
notAlwaysSame :: Eq a => Predicate a
notAlwaysSame :: forall a. Eq a => Predicate a
notAlwaysSame = (a -> a -> Bool) -> Predicate a
forall a. (a -> a -> Bool) -> Predicate a
notAlwaysSameBy a -> a -> Bool
forall a. Eq a => a -> a -> Bool
(==)
notAlwaysSameOn :: Eq b => (a -> b) -> Predicate a
notAlwaysSameOn :: forall b a. Eq b => (a -> b) -> Predicate a
notAlwaysSameOn a -> b
f = (a -> a -> Bool) -> Predicate a
forall a. (a -> a -> Bool) -> Predicate a
notAlwaysSameBy (b -> b -> Bool
forall a. Eq a => a -> a -> Bool
(==) (b -> b -> Bool) -> (a -> b) -> a -> a -> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` a -> b
f)
notAlwaysSameBy :: (a -> a -> Bool) -> Predicate a
notAlwaysSameBy :: forall a. (a -> a -> Bool) -> Predicate a
notAlwaysSameBy a -> a -> Bool
f = ProPredicate
{ pdiscard :: Either Condition a -> Maybe Discard
pdiscard = Maybe Discard -> Either Condition a -> Maybe Discard
forall a b. a -> b -> a
const Maybe Discard
forall a. Maybe a
Nothing
, peval :: [(Either Condition a, Trace)] -> Result a
peval = \[(Either Condition a, Trace)]
xs ->
let ([(Either Condition a, Trace)]
failures, [(Either Condition a, Trace)]
successes) = ((Either Condition a, Trace) -> Bool)
-> [(Either Condition a, Trace)]
-> ([(Either Condition a, Trace)], [(Either Condition a, Trace)])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (Either Condition a -> Bool
forall a b. Either a b -> Bool
isLeft (Either Condition a -> Bool)
-> ((Either Condition a, Trace) -> Either Condition a)
-> (Either Condition a, Trace)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Either Condition a, Trace) -> Either Condition a
forall a b. (a, b) -> a
fst) [(Either Condition a, Trace)]
xs
simpleFailures :: [(Either Condition a, Trace)]
simpleFailures = (Either Condition a -> Either Condition a -> Bool)
-> [(Either Condition a, Trace)] -> [(Either Condition a, Trace)]
forall x. (x -> x -> Bool) -> [(x, Trace)] -> [(x, Trace)]
simplestsBy (Condition -> Condition -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Condition -> Condition -> Bool)
-> (Either Condition a -> Condition)
-> Either Condition a
-> Either Condition a
-> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Either Condition a -> Condition
forall a b. HasCallStack => Either a b -> a
efromLeft) [(Either Condition a, Trace)]
failures
in case [(Either Condition a, Trace)]
successes of
[(Either Condition a, Trace)
x] -> [(Either Condition a, Trace)] -> Result a
forall a. [(Either Condition a, Trace)] -> Result a
defaultFail ((Either Condition a, Trace)
x (Either Condition a, Trace)
-> [(Either Condition a, Trace)] -> [(Either Condition a, Trace)]
forall a. a -> [a] -> [a]
: [(Either Condition a, Trace)]
simpleFailures)
[(Either Condition a, Trace)]
_ ->
let res :: Result a
res = [(Either Condition a, Trace)] -> Result a -> Result a
go [(Either Condition a, Trace)]
successes ([(Either Condition a, Trace)] -> Result a
forall a. [(Either Condition a, Trace)] -> Result a
defaultFail [])
in case [(Either Condition a, Trace)]
failures of
[] -> Result a
res
[(Either Condition a, Trace)]
_ -> Result a
res { _failures = simpleFailures ++ _failures res, _pass = False }
}
where
(Either a a, b)
y1 .*. :: (Either a a, b) -> (Either a a, b) -> Bool
.*. (Either a a, b)
y2 = Bool -> Bool
not ((a -> a -> Bool)
-> ((Either a a, b) -> a)
-> (Either a a, b)
-> (Either a a, b)
-> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
on a -> a -> Bool
f (Either a a -> a
forall a b. HasCallStack => Either a b -> b
efromRight (Either a a -> a)
-> ((Either a a, b) -> Either a a) -> (Either a a, b) -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Either a a, b) -> Either a a
forall a b. (a, b) -> a
fst) (Either a a, b)
y1 (Either a a, b)
y2)
go :: [(Either Condition a, Trace)] -> Result a -> Result a
go [(Either Condition a, Trace)
y1,(Either Condition a, Trace)
y2] Result a
res
| (Either Condition a, Trace)
y1 (Either Condition a, Trace) -> (Either Condition a, Trace) -> Bool
forall {a} {b}. (Either a a, b) -> (Either a a, b) -> Bool
.*. (Either Condition a, Trace)
y2 = Result a
res { _pass = True }
| Bool
otherwise = Result a
res { _failures = y1 : y2 : _failures res }
go ((Either Condition a, Trace)
y1:(Either Condition a, Trace)
y2:[(Either Condition a, Trace)]
ys) Result a
res
| (Either Condition a, Trace)
y1 (Either Condition a, Trace) -> (Either Condition a, Trace) -> Bool
forall {a} {b}. (Either a a, b) -> (Either a a, b) -> Bool
.*. (Either Condition a, Trace)
y2 = [(Either Condition a, Trace)] -> Result a -> Result a
go ((Either Condition a, Trace)
y2(Either Condition a, Trace)
-> [(Either Condition a, Trace)] -> [(Either Condition a, Trace)]
forall a. a -> [a] -> [a]
:[(Either Condition a, Trace)]
ys) Result a
res { _pass = True }
| Bool
otherwise = [(Either Condition a, Trace)] -> Result a -> Result a
go ((Either Condition a, Trace)
y2(Either Condition a, Trace)
-> [(Either Condition a, Trace)] -> [(Either Condition a, Trace)]
forall a. a -> [a] -> [a]
:[(Either Condition a, Trace)]
ys) Result a
res { _failures = y1 : y2 : _failures res }
go [(Either Condition a, Trace)]
_ Result a
res = Result a
res
alwaysNothing :: (Either Condition a -> Maybe (Either Condition b)) -> ProPredicate a b
alwaysNothing :: forall a b.
(Either Condition a -> Maybe (Either Condition b))
-> ProPredicate a b
alwaysNothing Either Condition a -> Maybe (Either Condition b)
f = ProPredicate
{ pdiscard :: Either Condition a -> Maybe Discard
pdiscard = Maybe Discard
-> (Either Condition b -> Maybe Discard)
-> Maybe (Either Condition b)
-> Maybe Discard
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Discard -> Maybe Discard
forall a. a -> Maybe a
Just Discard
DiscardResultAndTrace) (Maybe Discard -> Either Condition b -> Maybe Discard
forall a b. a -> b -> a
const Maybe Discard
forall a. Maybe a
Nothing) (Maybe (Either Condition b) -> Maybe Discard)
-> (Either Condition a -> Maybe (Either Condition b))
-> Either Condition a
-> Maybe Discard
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Either Condition a -> Maybe (Either Condition b)
f
, peval :: [(Either Condition a, Trace)] -> Result b
peval = \[(Either Condition a, Trace)]
xs ->
let failures :: [(Either Condition b, Trace)]
failures = ((Either Condition a, Trace) -> Maybe (Either Condition b, Trace))
-> [(Either Condition a, Trace)] -> [(Either Condition b, Trace)]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (\(Either Condition a
efa,Trace
trc) -> (,Trace
trc) (Either Condition b -> (Either Condition b, Trace))
-> Maybe (Either Condition b) -> Maybe (Either Condition b, Trace)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Either Condition a -> Maybe (Either Condition b)
f Either Condition a
efa) [(Either Condition a, Trace)]
xs
in Bool -> [(Either Condition b, Trace)] -> String -> Result b
forall a.
Bool -> [(Either Condition a, Trace)] -> String -> Result a
Result ([(Either Condition b, Trace)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Either Condition b, Trace)]
failures) [(Either Condition b, Trace)]
failures String
""
}
alwaysTrue :: (Either Condition a -> Bool) -> Predicate a
alwaysTrue :: forall a. (Either Condition a -> Bool) -> Predicate a
alwaysTrue Either Condition a -> Bool
p = (Either Condition a -> Maybe (Either Condition a))
-> ProPredicate a a
forall a b.
(Either Condition a -> Maybe (Either Condition b))
-> ProPredicate a b
alwaysNothing (\Either Condition a
efa -> if Either Condition a -> Bool
p Either Condition a
efa then Maybe (Either Condition a)
forall a. Maybe a
Nothing else Either Condition a -> Maybe (Either Condition a)
forall a. a -> Maybe a
Just Either Condition a
efa)
somewhereNothing :: (Either Condition a -> Maybe (Either Condition b)) -> ProPredicate a b
somewhereNothing :: forall a b.
(Either Condition a -> Maybe (Either Condition b))
-> ProPredicate a b
somewhereNothing Either Condition a -> Maybe (Either Condition b)
f = ProPredicate
{ pdiscard :: Either Condition a -> Maybe Discard
pdiscard = Maybe Discard
-> (Either Condition b -> Maybe Discard)
-> Maybe (Either Condition b)
-> Maybe Discard
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Discard -> Maybe Discard
forall a. a -> Maybe a
Just Discard
DiscardTrace) (Maybe Discard -> Either Condition b -> Maybe Discard
forall a b. a -> b -> a
const Maybe Discard
forall a. Maybe a
Nothing) (Maybe (Either Condition b) -> Maybe Discard)
-> (Either Condition a -> Maybe (Either Condition b))
-> Either Condition a
-> Maybe Discard
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Either Condition a -> Maybe (Either Condition b)
f
, peval :: [(Either Condition a, Trace)] -> Result b
peval = \[(Either Condition a, Trace)]
xs ->
let failures :: [Maybe (Either Condition b, Trace)]
failures = ((Either Condition a, Trace) -> Maybe (Either Condition b, Trace))
-> [(Either Condition a, Trace)]
-> [Maybe (Either Condition b, Trace)]
forall a b. (a -> b) -> [a] -> [b]
map (\(Either Condition a
efa,Trace
trc) -> (,Trace
trc) (Either Condition b -> (Either Condition b, Trace))
-> Maybe (Either Condition b) -> Maybe (Either Condition b, Trace)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Either Condition a -> Maybe (Either Condition b)
f Either Condition a
efa) [(Either Condition a, Trace)]
xs
in Bool -> [(Either Condition b, Trace)] -> String -> Result b
forall a.
Bool -> [(Either Condition a, Trace)] -> String -> Result a
Result ((Maybe (Either Condition b, Trace) -> Bool)
-> [Maybe (Either Condition b, Trace)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Maybe (Either Condition b, Trace) -> Bool
forall a. Maybe a -> Bool
isNothing [Maybe (Either Condition b, Trace)]
failures) ([Maybe (Either Condition b, Trace)]
-> [(Either Condition b, Trace)]
forall a. [Maybe a] -> [a]
catMaybes [Maybe (Either Condition b, Trace)]
failures) String
""
}
somewhereTrue :: (Either Condition a -> Bool) -> Predicate a
somewhereTrue :: forall a. (Either Condition a -> Bool) -> Predicate a
somewhereTrue Either Condition a -> Bool
p = (Either Condition a -> Maybe (Either Condition a))
-> ProPredicate a a
forall a b.
(Either Condition a -> Maybe (Either Condition b))
-> ProPredicate a b
somewhereNothing (\Either Condition a
efa -> if Either Condition a -> Bool
p Either Condition a
efa then Maybe (Either Condition a)
forall a. Maybe a
Nothing else Either Condition a -> Maybe (Either Condition a)
forall a. a -> Maybe a
Just Either Condition a
efa)
gives :: (Eq a, Show a) => [Either Condition a] -> Predicate a
gives :: forall a. (Eq a, Show a) => [Either Condition a] -> Predicate a
gives [Either Condition a]
expected = ProPredicate
{ pdiscard :: Either Condition a -> Maybe Discard
pdiscard = \Either Condition a
efa -> if Either Condition a
efa Either Condition a -> [Either Condition a] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Either Condition a]
expected then Discard -> Maybe Discard
forall a. a -> Maybe a
Just Discard
DiscardTrace else Maybe Discard
forall a. Maybe a
Nothing
, peval :: [(Either Condition a, Trace)] -> Result a
peval = \[(Either Condition a, Trace)]
xs -> [Either Condition a]
-> [Either Condition a]
-> [(Either Condition a, Trace)]
-> Result a
-> Result a
forall {a} {b} {a}.
(Eq a, Show a) =>
[a] -> [a] -> [(a, b)] -> Result a -> Result a
go [Either Condition a]
expected [] [(Either Condition a, Trace)]
xs (Result a -> Result a) -> Result a -> Result a
forall a b. (a -> b) -> a -> b
$ [(Either Condition a, Trace)] -> Result a
forall a. [(Either Condition a, Trace)] -> Result a
defaultFail ([(Either Condition a, Trace)] -> [(Either Condition a, Trace)]
forall {b}. [(Either Condition a, b)] -> [(Either Condition a, b)]
failures [(Either Condition a, Trace)]
xs)
}
where
go :: [a] -> [a] -> [(a, b)] -> Result a -> Result a
go [a]
waitingFor [a]
alreadySeen ((a
x, b
_):[(a, b)]
xs) Result a
res
| a
x a -> [a] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [a]
waitingFor = [a] -> [a] -> [(a, b)] -> Result a -> Result a
go ((a -> Bool) -> [a] -> [a]
forall a. (a -> Bool) -> [a] -> [a]
filter (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/=a
x) [a]
waitingFor) (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
alreadySeen) [(a, b)]
xs Result a
res
| a
x a -> [a] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [a]
alreadySeen = [a] -> [a] -> [(a, b)] -> Result a -> Result a
go [a]
waitingFor [a]
alreadySeen [(a, b)]
xs Result a
res
| Bool
otherwise = Result a
res
go [] [a]
_ [] Result a
res = Result a
res { _pass = True }
go [a]
es [a]
_ [] Result a
res = Result a
res { _failureMsg = unlines $ map (\a
e -> String
"Expected: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
e) es }
failures :: [(Either Condition a, b)] -> [(Either Condition a, b)]
failures = ((Either Condition a, b) -> Bool)
-> [(Either Condition a, b)] -> [(Either Condition a, b)]
forall a. (a -> Bool) -> [a] -> [a]
filter (\(Either Condition a
r, b
_) -> Either Condition a
r Either Condition a -> [Either Condition a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [Either Condition a]
expected)
gives' :: (Eq a, Show a) => [a] -> Predicate a
gives' :: forall a. (Eq a, Show a) => [a] -> Predicate a
gives' = [Either Condition a] -> Predicate a
forall a. (Eq a, Show a) => [Either Condition a] -> Predicate a
gives ([Either Condition a] -> Predicate a)
-> ([a] -> [Either Condition a]) -> [a] -> Predicate a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Either Condition a) -> [a] -> [Either Condition a]
forall a b. (a -> b) -> [a] -> [b]
map a -> Either Condition a
forall a b. b -> Either a b
Right
doTest :: Show a => String -> Result a -> IO Bool
doTest :: forall a. Show a => String -> Result a -> IO Bool
doTest String
name Result a
result = do
Bool
doctest <- Maybe String -> Bool
forall a. Maybe a -> Bool
isJust (Maybe String -> Bool) -> IO (Maybe String) -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO (Maybe String)
lookupEnv String
"DEJAFU_DOCTEST"
if Result a -> Bool
forall a. Result a -> Bool
_pass Result a
result
then String -> IO ()
putStrLn (Bool -> String
passmsg Bool
doctest)
else do
String -> IO ()
putStrLn (Bool -> String
failmsg Bool
doctest)
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (String -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (String -> Bool) -> String -> Bool
forall a b. (a -> b) -> a -> b
$ Result a -> String
forall a. Result a -> String
_failureMsg Result a
result) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Result a -> String
forall a. Result a -> String
_failureMsg Result a
result
let failures :: [(Either Condition a, Trace)]
failures = Result a -> [(Either Condition a, Trace)]
forall a. Result a -> [(Either Condition a, Trace)]
_failures Result a
result
let output :: [IO ()]
output = ((Either Condition a, Trace) -> IO ())
-> [(Either Condition a, Trace)] -> [IO ()]
forall a b. (a -> b) -> [a] -> [b]
map (\(Either Condition a
r, Trace
t) -> String -> IO ()
putStrLn (String -> IO ()) -> ShowS -> String -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
indent (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ (Condition -> String)
-> (a -> String) -> Either Condition a -> String
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Condition -> String
showCondition a -> String
forall a. Show a => a -> String
show Either Condition a
r String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Trace -> String
showTrace Trace
t) ([(Either Condition a, Trace)] -> [IO ()])
-> [(Either Condition a, Trace)] -> [IO ()]
forall a b. (a -> b) -> a -> b
$ Int
-> [(Either Condition a, Trace)] -> [(Either Condition a, Trace)]
forall a. Int -> [a] -> [a]
take Int
5 [(Either Condition a, Trace)]
failures
[IO ()] -> IO ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ ([IO ()] -> IO ()) -> [IO ()] -> IO ()
forall a b. (a -> b) -> a -> b
$ IO () -> [IO ()] -> [IO ()]
forall a. a -> [a] -> [a]
intersperse (String -> IO ()
putStrLn String
"") [IO ()]
output
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int -> [(Either Condition a, Trace)] -> Bool
forall a. Int -> [a] -> Bool
moreThan Int
5 [(Either Condition a, Trace)]
failures) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> IO ()
putStrLn (ShowS
indent String
"...")
Bool -> IO Bool
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Result a -> Bool
forall a. Result a -> Bool
_pass Result a
result)
where
passmsg :: Bool -> String
passmsg Bool
True = String
"[pass] " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
name
passmsg Bool
False = String
"\27[32m[pass]\27[0m " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
name
failmsg :: Bool -> String
failmsg Bool
True = String
"[fail] " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
name
failmsg Bool
False = String
"\27[31m[fail]\27[0m " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
name
moreThan :: Int -> [a] -> Bool
moreThan :: forall a. Int -> [a] -> Bool
moreThan Int
n [] = Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0
moreThan Int
0 [a]
_ = Bool
True
moreThan Int
n (a
_:[a]
rest) = Int -> [a] -> Bool
forall a. Int -> [a] -> Bool
moreThan (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) [a]
rest
indent :: String -> String
indent :: ShowS
indent = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"\n" ([String] -> String) -> (String -> [String]) -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String
" "String -> ShowS
forall a. [a] -> [a] -> [a]
++) ([String] -> [String])
-> (String -> [String]) -> String -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
lines