2017-06-07 16:03:00 +03:00
|
|
|
module Cases.Refinement where
|
|
|
|
|
|
|
|
import Control.Concurrent.Classy.MVar
|
|
|
|
import Control.Monad (void)
|
|
|
|
import Test.DejaFu.Conc (ConcIO)
|
|
|
|
import Test.DejaFu.Refinement
|
|
|
|
import Test.HUnit.DejaFu (testProperty)
|
|
|
|
|
2017-09-20 01:17:02 +03:00
|
|
|
import Common
|
2017-06-07 16:03:00 +03:00
|
|
|
|
|
|
|
tests :: [Test]
|
2017-09-20 11:05:23 +03:00
|
|
|
tests = [ testGroup "MVar" mvarProps ]
|
2017-06-07 16:03:00 +03:00
|
|
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
mvar :: (MVar ConcIO Int -> ConcIO a) -> Sig (MVar ConcIO Int) (Maybe Int) (Maybe Int)
|
|
|
|
mvar e = Sig
|
|
|
|
{ initialise = maybe newEmptyMVar newMVar
|
|
|
|
, observe = const . tryTakeMVar
|
|
|
|
, interfere = \v mi -> tryTakeMVar v >> maybe (pure ()) (void . tryPutMVar v) mi
|
|
|
|
, expression = void . e
|
|
|
|
}
|
|
|
|
|
2017-09-20 11:05:23 +03:00
|
|
|
mvarProps :: [Test]
|
|
|
|
mvarProps = toTestList
|
|
|
|
[ testProperty "readMVar is idempotent when composed sequentially" $
|
|
|
|
mvar readMVar === mvar (\v -> readMVar v >> readMVar v)
|
2017-06-07 16:03:00 +03:00
|
|
|
|
2017-09-20 11:05:23 +03:00
|
|
|
, testProperty "readMVar is idempotent when composed concurrently" $
|
|
|
|
mvar readMVar === mvar (\v -> readMVar v ||| readMVar v)
|
2017-06-07 16:03:00 +03:00
|
|
|
|
2017-09-20 11:05:23 +03:00
|
|
|
, testProperty "readMVar is not equivalent to a take followed by a put" $
|
|
|
|
expectFailure $ mvar readMVar === mvar (\v -> takeMVar v >>= putMVar v)
|
2017-06-07 16:03:00 +03:00
|
|
|
|
2017-09-20 11:05:23 +03:00
|
|
|
, testProperty "readMVar is a strict refinement of a take followed by a put" $
|
|
|
|
mvar readMVar ->- mvar (\v -> takeMVar v >>= putMVar v)
|
2017-06-07 16:03:00 +03:00
|
|
|
|
2017-09-20 11:05:23 +03:00
|
|
|
, testProperty "takeMVar is equivalent to a read followed by a take" $
|
|
|
|
mvar takeMVar === mvar (\v -> readMVar v >> takeMVar v)
|
2017-06-07 16:03:00 +03:00
|
|
|
|
2017-09-20 11:05:23 +03:00
|
|
|
, testProperty "takeMVar is not equivalent to a read concurrently composed with a take" $
|
|
|
|
expectFailure $ mvar takeMVar === mvar (\v -> readMVar v ||| takeMVar v)
|
2017-06-07 16:03:00 +03:00
|
|
|
|
2017-09-20 11:05:23 +03:00
|
|
|
, testProperty "takeMVar is a strict refinement of a read concurrently composed with a take" $
|
|
|
|
mvar takeMVar ->- mvar (\v -> readMVar v ||| takeMVar v)
|
2017-06-07 16:03:00 +03:00
|
|
|
|
2017-09-20 11:05:23 +03:00
|
|
|
, testProperty "putMVar is not equivalent to a put followed by a read" $
|
|
|
|
\x -> expectFailure $ mvar (\v -> putMVar v x) === mvar (\v -> putMVar v x >> readMVar v)
|
2017-06-07 16:03:00 +03:00
|
|
|
|
2017-09-20 11:05:23 +03:00
|
|
|
, testProperty "putMVar is a strict refinement of a put followed by a read" $
|
|
|
|
\x -> mvar (\v -> putMVar v x) ->- mvar (\v -> putMVar v x >> readMVar v)
|
2017-06-07 16:03:00 +03:00
|
|
|
|
2017-09-20 11:05:23 +03:00
|
|
|
, testProperty "putMVar is not equivalent to a put concurrently composed with a read" $
|
|
|
|
\x -> expectFailure $ mvar (\v -> putMVar v x) === mvar (\v -> putMVar v x ||| readMVar v)
|
2017-06-07 16:03:00 +03:00
|
|
|
|
2017-09-20 11:05:23 +03:00
|
|
|
, testProperty "putMVar is a strict refinement of a put concurrently composed with a read" $
|
|
|
|
\x -> mvar (\v -> putMVar v x) ->- mvar (\v -> putMVar v x ||| readMVar v)
|
|
|
|
]
|