HMock-0.2.0.0: test/ExpectSet.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
module ExpectSet where
import Control.Arrow (second)
import Data.List (foldl')
import Test.HMock.Internal.ExpectSet
import Test.HMock.Multiplicity
import Test.Hspec
import Test.Hspec.QuickCheck (modifyMaxSuccess)
import Test.QuickCheck
instance Arbitrary (ExpectSet Int) where
arbitrary = do
n <- getSize
frequency
[ (1, return ExpectNothing),
(5, ExpectStep <$> choose (1, 100)),
(n, scale (`div` 2) $ ExpectSequence <$> arbitrary <*> arbitrary),
(n, scale (`div` 2) $ ExpectInterleave <$> arbitrary <*> arbitrary),
(n, scale (`div` 2) $ ExpectEither <$> arbitrary <*> arbitrary),
(n, scale (subtract 1) $ ExpectMulti <$> arbitrary <*> arbitrary),
(n, scale (subtract 1) $ ExpectConsecutive <$> arbitrary <*> arbitrary)
]
shrink ExpectNothing = []
shrink (ExpectStep _) = [ExpectNothing]
shrink (ExpectSequence e f) =
[ExpectSequence e' f | e' <- shrink e]
++ [ExpectSequence e f' | f' <- shrink f]
++ [e, f]
shrink (ExpectInterleave e f) =
[ExpectSequence e' f | e' <- shrink e]
++ [ExpectSequence e f' | f' <- shrink f]
++ [e, f]
shrink (ExpectEither e f) =
[ExpectSequence e' f | e' <- shrink e]
++ [ExpectSequence e f' | f' <- shrink f]
++ [e, f]
shrink (ExpectMulti mult e) =
[ExpectMulti mult' e | mult' <- shrink mult]
++ [ExpectMulti mult e' | e' <- shrink e]
++ [e]
shrink (ExpectConsecutive mult e) =
[ExpectConsecutive mult' e | mult' <- shrink mult]
++ [ExpectConsecutive mult e' | e' <- shrink e]
++ [e]
instance Arbitrary Multiplicity where
arbitrary =
between
<$> (fromInteger <$> arbitrary)
<*> (fromInteger . getNonNegative <$> arbitrary)
liveSteps' :: ExpectSet step -> [(step, ExpectSet step)]
liveSteps' = map (second simplify) . liveSteps
expectSetSpec :: SpecWith ()
expectSetSpec = modifyMaxSuccess (const 1000) $ do
describe "ExpectSet" $ do
describe "satisfied" $ do
it "agrees with excess" $
property $
\(es :: ExpectSet Int) ->
if satisfied es
then excess es === ExpectNothing
else excess es =/= ExpectNothing
let sameBehavior ::
(Show a, Eq a) => Int -> ExpectSet a -> ExpectSet a -> Property
sameBehavior 0 e f = satisfied e === satisfied f
sameBehavior d e f =
satisfied e === satisfied f
.&&. foldl' (.&&.) (property True) (zipWith (===) esteps fsteps)
.&&. foldl'
(.&&.)
(property True)
(zipWith (sameBehavior (d - 1)) econts fconts)
where
(esteps, econts) = unzip (liveSteps e)
(fsteps, fconts) = unzip (liveSteps f)
describe "simplify" $ do
it "always terminates" $
property $
\(es :: ExpectSet Int) ->
-- Hack to force deep evaluation
let es' = simplify es in formatExpectSet es' == formatExpectSet es'
it "preserves behavior" $
property $
\(es :: ExpectSet Int) -> sameBehavior 3 es (simplify es)
describe "liveSteps" $ do
it "expects nothing" $
example $ liveSteps' (ExpectNothing :: ExpectSet Int) `shouldBe` []
it "expects a step" $
example $
liveSteps' (ExpectStep 42)
`shouldBe` [(42 :: Int, ExpectNothing)]
it "expects the first step in a sequence" $
example $ do
let input = ExpectSequence (ExpectStep 1) (ExpectStep 2)
liveSteps' input `shouldBe` [(1 :: Int, ExpectStep 2)]
it "skips an exhaustable first step in a sequence" $
example $ do
let input = ExpectSequence ExpectNothing (ExpectStep 2)
liveSteps' input `shouldBe` [(2 :: Int, ExpectNothing)]
it "skips an exhaustable first step in a sequence" $
example $ do
let input = ExpectSequence ExpectNothing (ExpectStep 2)
liveSteps' input `shouldBe` [(2 :: Int, ExpectNothing)]
it "expects either step in an interleave" $
example $ do
let input = ExpectInterleave (ExpectStep 1) (ExpectStep 2)
liveSteps' input
`shouldBe` [(1 :: Int, ExpectStep 2), (2, ExpectStep 1)]
it "optional has same behavior as or-empty" $
property $
\(es :: ExpectSet Int) ->
let a = ExpectEither ExpectNothing es
b = ExpectMulti (atMost 1) es
in sameBehavior 3 a b