distributed-process-tests-0.5.0: src/Control/Distributed/Process/Tests/Receive.hs
{-# LANGUAGE TemplateHaskell, DeriveDataTypeable #-}
{-# OPTIONS_GHC -Wall #-}
-- | XXX test doesn't work, because failure exceptions don't get propagated. The
-- test always claims to succeed, even if it failed.
module Control.Distributed.Process.Tests.Receive (tests) where
import Network.Transport.Test (TestTransport(..))
import Network.Transport (Transport)
import Control.Distributed.Process
import Control.Distributed.Process.Closure
import Control.Distributed.Process.Node
import Control.Monad
import Text.Printf
import Data.Binary
import Data.Typeable
import Test.HUnit (Assertion, (@?=))
import Test.Framework (Test, defaultMain)
import Test.Framework.Providers.HUnit (testCase)
-- Tests:
-- 1. 2 matchChans, receive on each one
-- 2. matchChan/matchIf, receive on each one
-- 3. matchIf/matchChan, receive on each one
-- 4. matchIf/matchChan/matchIf, receive on each one
recTest1 :: ReceivePort ()
-> SendPort String
-> ReceivePort String -> ReceivePort String
-> Process ()
recTest1 wait sync r1 r2 = do
forever $ do
receiveChan wait
r <- receiveWait
[ matchChan r1 $ \s -> return ("received1 " ++ s)
, matchChan r2 $ \s -> return ("received2 " ++ s)
]
sendChan sync r
recTest2 :: ReceivePort ()
-> SendPort String
-> ReceivePort String -> ReceivePort String
-> Process ()
recTest2 wait sync r1 r2 = do
forever $ do
receiveChan wait
r <- receiveWait
[ matchChan r1 $ \s -> return ("received1 " ++ s)
, matchIf (== "foo") $ \s -> return ("received2 " ++ s)
]
sendChan sync r
recTest3 :: ReceivePort ()
-> SendPort String
-> ReceivePort String -> ReceivePort String
-> Process ()
recTest3 wait sync r1 r2 = do
forever $ do
receiveChan wait
r <- receiveWait
[ matchIf (== "foo") $ \s -> return ("received1 " ++ s)
, matchChan r1 $ \s -> return ("received2 " ++ s)
]
sendChan sync r
recTest4 :: ReceivePort ()
-> SendPort String
-> ReceivePort String -> ReceivePort String
-> Process ()
recTest4 wait sync r1 r2 = do
forever $ do
receiveChan wait
r <- receiveWait
[ matchIf (== "foo") $ \s -> return ("received1 " ++ s)
, matchChan r1 $ \s -> return ("received2 " ++ s)
, matchIf (== "bar") $ \s -> return ("received3 " ++ s)
]
sendChan sync r
master :: Process ()
master = do
(waits,waitr) <- newChan
(syncs,syncr) <- newChan
let go expect = do
sendChan waits ()
r <- receiveChan syncr
liftIO $ print (r,expect, r == expect)
liftIO $ r @?= expect
liftIO $ putStrLn "---- Test 1 ----"
(s1,r1) <- newChan
(s2,r2) <- newChan
p <- spawnLocal (recTest1 waitr syncs r1 r2)
sendChan s1 "a" >> go "received1 a"
sendChan s2 "b" >> go "received2 b"
sendChan s1 "a" >> sendChan s2 "b" >> go "received1 a"
go "received2 b"
kill p "BANG"
liftIO $ putStrLn "\n---- Test 2 ----"
(s1,r1) <- newChan
(s2,r2) <- newChan
p <- spawnLocal (recTest2 waitr syncs r1 r2)
sendChan s1 "a" >> go "received1 a"
send p "foo" >> go "received2 foo"
sendChan s1 "a" >> send p "foo" >> go "received1 a"
sendChan s1 "a" >> send p "bar" >> go "received1 a"
go "received2 foo"
kill p "BANG"
liftIO $ putStrLn "\n---- Test 3 ----"
(s1,r1) <- newChan
(s2,r2) <- newChan
p <- spawnLocal (recTest3 waitr syncs r1 r2)
sendChan s1 "a" >> go "received2 a"
send p "foo" >> go "received1 foo"
sendChan s1 "a" >> send p "foo" >> go "received1 foo"
sendChan s1 "a" >> send p "bar" >> go "received2 a"
go "received2 a"
kill p "BANG"
liftIO $ putStrLn "\n---- Test 4 ----"
(s1,r1) <- newChan
(s2,r2) <- newChan
p <- spawnLocal (recTest4 waitr syncs r1 r2)
sendChan s1 "a" >> go "received2 a"
send p "foo" >> go "received1 foo"
send p "bar" >> go "received3 bar"
sendChan s1 "a" >> send p "foo" >> go "received1 foo"
send p "bar" >> go "received2 a"
send p "foo" >> go "received1 foo" >> go "received3 bar"
kill p "BANG"
terminate
testReceive :: Transport -> RemoteTable -> Assertion
testReceive transport rtable = do
node <- newLocalNode transport rtable
runProcess node $ master
tests :: TestTransport -> IO [Test]
tests TestTransport{..} = do
let rtable = initRemoteTable
return
[ testCase "testReceive" (testReceive testTransport rtable) ]