{-# LANGUAGE TemplateHaskell #-} {-# 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 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) ]