{-# OPTIONS_GHC -fno-warn-unused-do-bind #-}
module Main where
import Control.Concurrent hiding (yield)
import Control.Concurrent.STM
import Control.Monad
import Pipes
import Pipes.Async
import qualified Pipes.Prelude as P
import Pipes.Safe
import Test.Hspec
segment1 :: Proxy x' x () Int (SafeT IO) ()
segment1 = do
liftIO $ putStrLn "Starting segment 1"
each [(1 :: Int)..3]
segment2 :: (Num b, MonadIO m) => TMVar String -> Proxy () b () b m ()
segment2 var = do
liftIO $ putStrLn "Starting segment 2"
replicateM_ 3 $ yield . (+1) =<< await
-- P.map (+1)
liftIO $ do
putStrLn "atomically $ tryPutTMVar var \"sender\""
atomically $ tryPutTMVar var "sender"
putStrLn "Done sending"
segment3 :: (Num c, Show c, MonadIO m) => TMVar String -> Proxy () c () c m ()
segment3 var = do
liftIO $ putStrLn "Starting segment 3"
for cat $ \a -> do
liftIO $ do
putStrLn "Got a value from upstream"
threadDelay 300000
putStrLn "atomically $ tryPutTMVar var \"receiver\""
atomically $ tryPutTMVar var "receiver"
print a
yield (a + 100)
liftIO $ putStrLn "Done receiving"
segment4 :: Proxy () Int () Int (SafeT IO) b
segment4 = do
liftIO $ putStrLn "Starting segment 4"
P.map (+10)
main :: IO ()
main = hspec $ do
describe "Sanity tests" $ do
it "Works in the simplest case" $ do
var' <- newEmptyTMVarIO
ys <- runSafeT $ P.toListM $
segment1 >-> (segment2 var' >-> segment3 var') >-> segment4
ys `shouldBe` [112, 113, 114]
var <- newEmptyTMVarIO
xs <- runSafeT $ P.toListM $
segment1 >-> (segment2 var >&> segment3 var) >-> segment4
xs `shouldBe` [112, 113, 114]
result <- atomically $ tryTakeTMVar var
result `shouldBe` Just "sender"
it "Behaves the same under composition (one)" $ do
var' <- newEmptyTMVarIO
ys <- runSafeT $ P.toListM $
(segment1 >-> segment2 var') >-> segment3 var' >-> segment4
ys `shouldBe` [112, 113, 114]
var <- newEmptyTMVarIO
xs <- runSafeT $ P.toListM $
(segment1 >-> segment2 var) >&> segment3 var >-> segment4
xs `shouldBe` [112, 113, 114]
result <- atomically $ tryTakeTMVar var
result `shouldBe` Just "sender"
it "Behaves the same under composition (two)" $ do
var' <- newEmptyTMVarIO
ys <- runSafeT $ P.toListM $
(segment1 >-> segment2 var' >-> segment3 var') >-> segment4
ys `shouldBe` [112, 113, 114]
var <- newEmptyTMVarIO
xs <- runSafeT $ P.toListM $
(segment1 >-> segment2 var >&> segment3 var) >-> segment4
xs `shouldBe` [112, 113, 114]
result <- atomically $ tryTakeTMVar var
result `shouldBe` Just "sender"
it "Behaves the same under composition (three)" $ do
var' <- newEmptyTMVarIO
ys <- runSafeT $ P.toListM $
segment1 >-> segment2 var' >-> (segment3 var' >-> segment4)
ys `shouldBe` [112, 113, 114]
var <- newEmptyTMVarIO
xs <- runSafeT $ P.toListM $
segment1 >-> segment2 var >&> (segment3 var >-> segment4)
xs `shouldBe` [112, 113, 114]
result <- atomically $ tryTakeTMVar var
result `shouldBe` Just "sender"
it "Behaves the same under composition (four)" $ do
var' <- newEmptyTMVarIO
ys <- runSafeT $ P.toListM $
segment1 >-> (segment2 var' >-> segment3 var' >-> segment4)
ys `shouldBe` [112, 113, 114]
var <- newEmptyTMVarIO
xs <- runSafeT $ P.toListM $
segment1 >-> (segment2 var >&> segment3 var >-> segment4)
xs `shouldBe` [112, 113, 114]
result <- atomically $ tryTakeTMVar var
result `shouldBe` Just "sender"