strict-checked-vars-0.2.1.0: test/Test/Control/Concurrent/Class/MonadMVar/Strict/Checked/WHNF.hs
{-# LANGUAGE LambdaCase #-}
module Test.Control.Concurrent.Class.MonadMVar.Strict.Checked.WHNF where
import Control.Concurrent.Class.MonadMVar.Strict.Checked hiding
( newEmptyMVar
, newEmptyMVarWithInvariant
, newMVar
, newMVarWithInvariant
)
import Control.Concurrent.Class.MonadMVar.Strict.Checked qualified as Checked
import Control.Monad (void)
import Control.Monad.IOSim (runSimOrThrow)
import Data.Typeable (Typeable)
import NoThunks.Class (OnlyCheckWhnf (..), unsafeNoThunks)
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.QuickCheck
( Fun
, Property
, applyFun
, counterexample
, ioProperty
, property
, testProperty
, (.&&.)
)
import Test.Utils (Invariant (..), (..:))
{-------------------------------------------------------------------------------
Main test tree
-------------------------------------------------------------------------------}
tests :: TestTree
tests =
testGroup
"WHNF"
[ testGroup "IO" testIO
, testGroup "IOSim" testIOSim
]
where
testIO =
[ testProperty
"prop_IO_newMVarWithInvariant"
prop_IO_newMVarWithInvariant
, testProperty
"prop_IO_putMVar"
prop_IO_putMVar
, testProperty
"prop_IO_swapMVar"
prop_IO_swapMVar
, testProperty
"prop_IO_tryPutMVarJust"
prop_IO_tryPutMVarJust
, testProperty
"prop_IO_tryPutMVarNothing"
prop_IO_tryPutMVarNothing
, testProperty
"prop_IO_modifyMVar_"
prop_IO_modifyMVar_
, testProperty
"prop_IO_modifyMVar"
prop_IO_modifyMVar
, testProperty
"prop_IO_modifyMVarMasked_"
prop_IO_modifyMVarMasked_
, testProperty
"prop_IO_modifyMVarMasked"
prop_IO_modifyMVarMasked
]
testIOSim =
[ testProperty
"prop_IOSim_newMVarWithInvariant"
prop_IOSim_newMVarWithInvariant
, testProperty
"prop_IOSim_putMVar"
prop_IOSim_putMVar
, testProperty
"prop_IOSim_swapMVar"
prop_IOSim_swapMVar
, testProperty
"prop_IOSim_tryPutMVarJust"
prop_IOSim_tryPutMVarJust
, testProperty
"prop_IOSim_tryPutMVarNothing"
prop_IOSim_tryPutMVarNothing
, testProperty
"prop_IOSim_modifyMVar_"
prop_IOSim_modifyMVar_
, testProperty
"prop_IOSim_modifyMVar"
prop_IOSim_modifyMVar
, testProperty
"prop_IOSim_modifyMVarMasked_"
prop_IOSim_modifyMVarMasked_
, testProperty
"prop_IOSim_modifyMVarMasked"
prop_IOSim_modifyMVarMasked
]
{-------------------------------------------------------------------------------
Utilities
-------------------------------------------------------------------------------}
isInWHNF :: (MonadMVar m, Typeable a) => StrictMVar m a -> m Property
isInWHNF v = do
x <- readMVar v
pure $ case unsafeNoThunks (OnlyCheckWhnf x) of
Nothing -> property True
Just tinfo ->
counterexample ("Not in WHNF: " ++ show tinfo) $
property False
-- | Wrapper around 'Checked.newMVar' and 'Checked.newMVarWithInvariant'.
newMVarWithInvariant :: MonadMVar m => Invariant a -> a -> m (StrictMVar m a)
newMVarWithInvariant = \case
NoInvariant -> Checked.newMVar
Invariant _ inv -> Checked.newMVarWithInvariant inv
-- | Wrapper around 'Checked.newEmptyMVar' and
-- 'Checked.newEmptyMVarWithInvariant'.
newEmptyMVarWithInvariant :: MonadMVar m => Invariant a -> m (StrictMVar m a)
newEmptyMVarWithInvariant = \case
NoInvariant -> Checked.newEmptyMVar
Invariant _ inv -> Checked.newEmptyMVarWithInvariant inv
{-------------------------------------------------------------------------------
Properties
-------------------------------------------------------------------------------}
--
-- newMVarWithInvariant
--
-- | Test 'newMVarWithInvariant', not to be confused with
-- 'Checked.newMVarWithInvariant'.
prop_M_newMVarWithInvariant ::
MonadMVar m =>
Invariant Int ->
Int ->
Fun Int Int ->
m Property
prop_M_newMVarWithInvariant inv x f = do
v <- newMVarWithInvariant inv (applyFun f x)
isInWHNF v
prop_IO_newMVarWithInvariant :: Invariant Int -> Int -> Fun Int Int -> Property
prop_IO_newMVarWithInvariant =
ioProperty
..: prop_M_newMVarWithInvariant
prop_IOSim_newMVarWithInvariant :: Invariant Int -> Int -> Fun Int Int -> Property
prop_IOSim_newMVarWithInvariant inv x f =
runSimOrThrow $
prop_M_newMVarWithInvariant inv x f
--
-- putMVar
--
prop_M_putMVar ::
MonadMVar m =>
Invariant Int ->
Int ->
Fun Int Int ->
m Property
prop_M_putMVar inv x f = do
v <- newEmptyMVarWithInvariant inv
putMVar v (applyFun f x)
isInWHNF v
prop_IO_putMVar :: Invariant Int -> Int -> Fun Int Int -> Property
prop_IO_putMVar =
ioProperty
..: prop_M_putMVar
prop_IOSim_putMVar :: Invariant Int -> Int -> Fun Int Int -> Property
prop_IOSim_putMVar inv x f =
runSimOrThrow $
prop_M_putMVar inv x f
--
-- swapMVar
--
prop_M_swapMVar ::
MonadMVar m =>
Invariant Int ->
Int ->
Fun Int Int ->
m Property
prop_M_swapMVar inv x f = do
v <- newMVarWithInvariant inv x
void $ swapMVar v (applyFun f x)
isInWHNF v
prop_IO_swapMVar :: Invariant Int -> Int -> Fun Int Int -> Property
prop_IO_swapMVar =
ioProperty
..: prop_M_swapMVar
prop_IOSim_swapMVar :: Invariant Int -> Int -> Fun Int Int -> Property
prop_IOSim_swapMVar inv x f =
runSimOrThrow $
prop_M_swapMVar inv x f
--
-- tryPutMVar
--
prop_M_tryPutMVarJust ::
MonadMVar m =>
Invariant Int ->
Int ->
Fun Int Int ->
m Property
prop_M_tryPutMVarJust inv x f = do
v <- newEmptyMVarWithInvariant inv
b <- tryPutMVar v (applyFun f x)
b' <- isInWHNF v
pure (property b .&&. b')
prop_IO_tryPutMVarJust :: Invariant Int -> Int -> Fun Int Int -> Property
prop_IO_tryPutMVarJust =
ioProperty
..: prop_M_tryPutMVarJust
prop_IOSim_tryPutMVarJust :: Invariant Int -> Int -> Fun Int Int -> Property
prop_IOSim_tryPutMVarJust inv x f =
runSimOrThrow $
prop_M_tryPutMVarJust inv x f
prop_M_tryPutMVarNothing ::
MonadMVar m =>
Invariant Int ->
Int ->
Fun Int Int ->
m Property
prop_M_tryPutMVarNothing inv x f = do
v <- newMVarWithInvariant inv x
b <- tryPutMVar v (applyFun f x)
b' <- isInWHNF v
pure (property (not b) .&&. b')
prop_IO_tryPutMVarNothing :: Invariant Int -> Int -> Fun Int Int -> Property
prop_IO_tryPutMVarNothing =
ioProperty
..: prop_M_tryPutMVarNothing
prop_IOSim_tryPutMVarNothing :: Invariant Int -> Int -> Fun Int Int -> Property
prop_IOSim_tryPutMVarNothing inv x f =
runSimOrThrow $
prop_M_tryPutMVarNothing inv x f
--
-- modifyMVar_
--
prop_M_modifyMVar_ ::
MonadMVar m =>
Invariant Int ->
Int ->
Fun Int Int ->
m Property
prop_M_modifyMVar_ inv x f = do
v <- newMVarWithInvariant inv x
modifyMVar_ v (pure . applyFun f)
isInWHNF v
prop_IO_modifyMVar_ :: Invariant Int -> Int -> Fun Int Int -> Property
prop_IO_modifyMVar_ =
ioProperty
..: prop_M_modifyMVar_
prop_IOSim_modifyMVar_ :: Invariant Int -> Int -> Fun Int Int -> Property
prop_IOSim_modifyMVar_ inv x f =
runSimOrThrow $
prop_M_modifyMVar_ inv x f
--
-- modifyMVar_
--
prop_M_modifyMVar ::
MonadMVar m =>
Invariant Int ->
Int ->
Fun Int (Int, Char) ->
m Property
prop_M_modifyMVar inv x f = do
v <- newMVarWithInvariant inv x
void $ modifyMVar v (pure . applyFun f)
isInWHNF v
prop_IO_modifyMVar :: Invariant Int -> Int -> Fun Int (Int, Char) -> Property
prop_IO_modifyMVar =
ioProperty
..: prop_M_modifyMVar
prop_IOSim_modifyMVar :: Invariant Int -> Int -> Fun Int (Int, Char) -> Property
prop_IOSim_modifyMVar inv x f =
runSimOrThrow $
prop_M_modifyMVar inv x f
--
-- modifyMVarMasked_
--
prop_M_modifyMVarMasked_ ::
MonadMVar m =>
Invariant Int ->
Int ->
Fun Int Int ->
m Property
prop_M_modifyMVarMasked_ inv x f = do
v <- newMVarWithInvariant inv x
void $ modifyMVarMasked_ v (pure . applyFun f)
isInWHNF v
prop_IO_modifyMVarMasked_ :: Invariant Int -> Int -> Fun Int Int -> Property
prop_IO_modifyMVarMasked_ =
ioProperty
..: prop_M_modifyMVarMasked_
prop_IOSim_modifyMVarMasked_ :: Invariant Int -> Int -> Fun Int Int -> Property
prop_IOSim_modifyMVarMasked_ inv x f =
runSimOrThrow $
prop_M_modifyMVarMasked_ inv x f
--
-- modifyMVarMasked
--
prop_M_modifyMVarMasked ::
MonadMVar m =>
Invariant Int ->
Int ->
Fun Int (Int, Char) ->
m Property
prop_M_modifyMVarMasked inv x f = do
v <- newMVarWithInvariant inv x
void $ modifyMVarMasked v (pure . applyFun f)
isInWHNF v
prop_IO_modifyMVarMasked :: Invariant Int -> Int -> Fun Int (Int, Char) -> Property
prop_IO_modifyMVarMasked =
ioProperty
..: prop_M_modifyMVarMasked
prop_IOSim_modifyMVarMasked :: Invariant Int -> Int -> Fun Int (Int, Char) -> Property
prop_IOSim_modifyMVarMasked inv x f =
runSimOrThrow $
prop_M_modifyMVarMasked inv x f