@@ -12,7 +12,7 @@ import Control.Concurrent.MVar
1212 , takeMVar
1313 , readMVar
1414 )
15−import Control.Monad (replicateM_)
15+import Control.Monad (replicateM_, replicateM)
1616import Control.Monad.IO.Class (liftIO)
1717import Control.Exception (throwIO)
1818import Control.Applicative ((<$>), (<*>))
@@ -21,6 +21,7 @@ import Network.Transport.TCP (createTransport, defaultTCPParameters)
2121import Control.Distributed.Process
2222import Control.Distributed.Process.Internal.Types (LocalNode(localEndPoint))
2323import Control.Distributed.Process.Node
24+import Control.Distributed.Process.Serializable (Serializable)
2425import TestAuxiliary
2526
2627newtype Ping = Ping ProcessId
@@ -395,6 +396,93 @@ testTypedChannels transport = do
395396
396397 takeMVar clientDone
397398
399+-- | Test merging receive ports
400+testMergeChannels :: NT.Transport -> IO ()
401+testMergeChannels transport = do
402+ localNode <- newLocalNode transport initRemoteTable
403+ testFlat localNode True "aaabbbccc"
404+ testFlat localNode False "abcabcabc"
405+ testNested localNode True True "aaabbbcccdddeeefffggghhhiii"
406+ testNested localNode True False "adgadgadgbehbehbehcficficfi"
407+ testNested localNode False True "abcabcabcdefdefdefghighighi"
408+ testNested localNode False False "adgbehcfiadgbehcfiadgbehcfi"
409+ testBlocked localNode True
410+ testBlocked localNode False
411+ where
412+ -- Single layer of merging
413+ testFlat :: LocalNode -> Bool -> String -> IO ()
414+ testFlat localNode biased expected =
415+ runProcess localNode $ do
416+ rs <- mapM charChannel "abc"
417+ m <- mergePorts biased rs
418+ xs <- replicateM 9 $ receiveChan m
419+ True <- return $ xs == expected
420+ return ()
421+
422+ -- Two layers of merging
423+ testNested :: LocalNode -> Bool -> Bool -> String -> IO ()
424+ testNested localNode biasedInner biasedOuter expected =
425+ runProcess localNode $ do
426+ rss <- mapM (mapM charChannel) ["abc", "def", "ghi"]
427+ ms <- mapM (mergePorts biasedInner) rss
428+ m <- mergePorts biasedOuter ms
429+ xs <- replicateM (9 * 3) $ receiveChan m
430+ True <- return $ xs == expected
431+ return ()
432+
433+ -- Test that if no messages are (immediately) available, the scheduler makes no difference
434+ testBlocked :: LocalNode -> Bool -> IO ()
435+ testBlocked localNode biased = do
436+ vs <- replicateM 3 newEmptyMVar
437+
438+ forkProcess localNode $ do
439+ [sa, sb, sc] <- liftIO $ mapM readMVar vs
440+ mapM_ ((>> liftIO (threadDelay 10000)) . uncurry sendChan)
441+ [ -- a, b, c
442+ (sa, 'a')
443+ , (sb, 'b')
444+ , (sc, 'c')
445+ -- a, c, b
446+ , (sa, 'a')
447+ , (sc, 'c')
448+ , (sb, 'b')
449+ -- b, a, c
450+ , (sb, 'b')
451+ , (sa, 'a')
452+ , (sc, 'c')
453+ -- b, c, a
454+ , (sb, 'b')
455+ , (sc, 'c')
456+ , (sa, 'a')
457+ -- c, a, b
458+ , (sc, 'c')
459+ , (sa, 'a')
460+ , (sb, 'b')
461+ -- c, b, a
462+ , (sc, 'c')
463+ , (sb, 'b')
464+ , (sa, 'a')
465+ ]
466+
467+ runProcess localNode $ do
468+ (ss, rs) <- unzip <$> replicateM 3 newChan
469+ liftIO $ mapM_ (uncurry putMVar) $ zip vs ss
470+ m <- mergePorts biased rs
471+ xs <- replicateM (6 * 3) $ receiveChan m
472+ True <- return $ xs == "abcacbbacbcacabcba"
473+ return ()
474+
475+ mergePorts :: Serializable a => Bool -> [ReceivePort a] -> Process (ReceivePort a)
476+ mergePorts True = mergePortsBiased
477+ mergePorts False = mergePortsRR
478+
479+ charChannel :: Char -> Process (ReceivePort Char)
480+ charChannel c = do
481+ (sport, rport) <- newChan
482+ replicateM_ 3 $ sendChan sport c
483+ liftIO $ threadDelay 10000 -- Make sure messages have been sent
484+ return rport
485+
398486main :: IO ()
399487main = do
400488 Right transport <- createTransport "127.0.0.1" "8080" defaultTCPParameters
@@ -403,8 +491,9 @@ main = do
403491 , ("Math", testMath transport)
404492 , ("Timeout", testTimeout transport)
405493 , ("Timeout0", testTimeout0 transport)
406− , ("SendToTerminated", testSendToTerminated transport)
494+ , ("SendToTerminated", testSendToTerminated transport)
407495 , ("TypedChannnels", testTypedChannels transport)
496+ , ("MergeChannels", testMergeChannels transport)
408497 -- The "missing" combinations in the list below don't make much sense, as
409498 -- we cannot guarantee that the monitor reply or link exception will not
410499 -- happen before the unmonitor or unlink