module Main (main) where
import Control.Monad.State (evalState)
import Control.Monad.State.Class (MonadState, get, put)
import Control.Monad.Trans.State (evalStateT)
import Test.Lawful.QuickCheck (forAll, forAllShow, testLaws, testLawsWith)
import Test.Lawful.Types (Laws, assert, discard)
import Test.QuickCheck (arbitrary, once)
import Test.Tasty (TestTree, defaultMain, testGroup)
import Test.Tasty.ExpectedFailure (expectFailBecause)
main :: IO ()
main = defaultMain tests
monadStateLaws :: (MonadState s m, Eq s) => m s -> Laws m
monadStateLaws gen =
[ ( "get returns what was put",
do
a0 <- get
a <- gen
if a == a0
then discard
else do
put a
a' <- get
assert $ a' == a
)
]
newtype NoShow = NoShow Int
deriving (Eq)
tests :: TestTree
tests =
testGroup
"lawful-classes-hedgehog"
[ testGroup
"StateT Int"
[ testLaws
"monadStateLaws"
(`evalStateT` (0 :: Int))
(monadStateLaws $ forAll arbitrary)
],
testGroup
"StateT NoShow"
[ testLaws
"monadStateLaws"
(`evalStateT` NoShow 0)
(monadStateLaws (forAllShow (\(NoShow _) -> "NoShow") (NoShow <$> arbitrary)))
],
testGroup
"StateT ()"
[ expectFailBecause "() has only one possible value" $
testLaws
"monadStateLaws"
(`evalStateT` ())
(monadStateLaws $ forAll $ pure ())
],
testGroup
"State Int"
[ testLawsWith
once
"monadStateLaws"
(pure . flip evalState (0 :: Int))
(monadStateLaws $ pure 1)
]
]