on master help sign in
Add test case for checking monadic state transfer for async & ahead
e9828b3adithyaov
test/Main.hs+38−1
@@ -6,7 +6,8 @@ import Control.Monad (void)
6import Control.Monad.Catch (throwM, MonadThrow)
6import Control.Monad.Catch (throwM, MonadThrow)
7import Control.Monad.Error.Class (throwError, MonadError)
7import Control.Monad.Error.Class (throwError, MonadError)
8import Control.Monad.IO.Class (MonadIO(liftIO))
8import Control.Monad.IO.Class (MonadIO(liftIO))
9−import Control.Monad.State (MonadState, get, modify, runStateT, StateT)
9+import Control.Monad.State (MonadState, get, modify, runStateT
10+ , StateT(..), evalStateT)
10import Control.Monad.Trans.Except (runExceptT, ExceptT)
11import Control.Monad.Trans.Except (runExceptT, ExceptT)
11import Data.Foldable (forM_, fold)
12import Data.Foldable (forM_, fold)
12import Data.Function ((&))
13import Data.Function ((&))
@@ -436,6 +437,21 @@ parallelTests = H.parallel $ do
436
437
437 it "foldrM is lazy enough" checkFoldrLaziness
438 it "foldrM is lazy enough" checkFoldrLaziness
438
439
440+ ---------------------------------------------------------------------------
441+ -- Monadic state transfer in concurrent tasks
442+ ---------------------------------------------------------------------------
443+
444+ -- XXX Can we write better test cases to hit every case?
445+
446+ it "async: state is saved and used if the work is partially enqueued"
447+ (checkMonadicStateTransfer async)
448+
449+ it "wAsync: state is saved and used if the work is partially enqueued"
450+ (checkMonadicStateTransfer wAsync)
451+
452+ it "ahead: state is saved and used if the work is partially enqueued"
453+ (checkMonadicStateTransfer ahead)
454+
439 ---------------------------------------------------------------------------
455 ---------------------------------------------------------------------------
440 -- Monadic state snapshot in concurrent tasks
456 -- Monadic state snapshot in concurrent tasks
441 ---------------------------------------------------------------------------
457 ---------------------------------------------------------------------------
@@ -561,6 +577,27 @@ takeCombined n t = do
561 S.take n (constr ([] :: [Int]) <> constr ([] :: [Int]))
577 S.take n (constr ([] :: [Int]) <> constr ([] :: [Int]))
562 r `shouldBe` []
578 r `shouldBe` []
563
579
580+checkMonadicStateTransfer
581+ :: (IsStream t1, IsStream t2)
582+ => ( t1 (StateT Int IO) ()
583+ -> t2 (StateT Int IO) ()
584+ -> SerialT (StateT Int IO) a3 )
585+ -> IO ()
586+checkMonadicStateTransfer op = evalStateT str (0 :: Int)
587+ where
588+ str =
589+ S.drain $
590+ maxBuffer 1 $
591+ (serially $ S.mapM snapshoti $ S.fromList [1..10]) `op`
592+ (serially $ S.mapM snapshoti $ S.fromList [1..10])
593+ snapshoti y = do
594+ modify (+ 1)
595+ x <- get
596+ lift1 $ x `shouldBe` y
597+ lift1 m = StateT $ \s -> do
598+ a <- m
599+ return (a, s)
600+
564checkFoldrLaziness :: IO ()
601checkFoldrLaziness :: IO ()
565checkFoldrLaziness = do
602checkFoldrLaziness = do
566 S.foldrM (\x xs -> if odd x then return True else xs)
603 S.foldrM (\x xs -> if odd x then return True else xs)