module Test.StateMachine.Internal.Utils
( Shrinker
, genFromMaybe
, anyP
, liftProperty
, shrinkPropertyHelper
, shrinkPropertyHelper'
, shrinkPair
) where
import Control.Monad.State
(StateT)
import Test.QuickCheck
(Gen, Property, Result(Failure), chatty,
counterexample, output, property,
quickCheckWithResult, stdArgs)
import Test.QuickCheck.Monadic
(PropertyM(MkPropertyM), monadicIO, run)
import Test.QuickCheck.Property
((.&&.), (.||.))
type Shrinker a = a -> [a]
genFromMaybe :: StateT s (StateT t Gen) (Maybe a) -> StateT s (StateT t Gen) a
genFromMaybe g = do
mx <- g
case mx of
Nothing -> genFromMaybe g
Just x -> return x
anyP :: (a -> Property) -> [a] -> Property
anyP p = foldr (\x ih -> p x .||. ih) (property False)
liftProperty :: Monad m => Property -> PropertyM m ()
liftProperty prop = MkPropertyM (\k -> fmap (prop .&&.) <$> k ())
shrinkPropertyHelper :: Property -> (String -> Bool) -> Property
shrinkPropertyHelper prop p = shrinkPropertyHelper' prop (property . p)
shrinkPropertyHelper' :: Property -> (String -> Property) -> Property
shrinkPropertyHelper' prop p = monadicIO $ do
result <- run $ quickCheckWithResult (stdArgs {chatty = False}) prop
case result of
Failure { output = outputLines } -> liftProperty $
counterexample ("failed: " ++ outputLines) $ p outputLines
_ -> return ()
shrinkPair :: Shrinker a -> Shrinker b -> Shrinker (a, b)
shrinkPair shrinkerA shrinkerB (x, y) =
[ (x', y) | x' <- shrinkerA x ] ++
[ (x, y') | y' <- shrinkerB y ]