@@ -25,21 +25,29 @@ import Control.Concurrent.MVar
26import Control.Monad (replicateM_, replicateM, forever, void, unless, join)
26import Control.Monad (replicateM_, replicateM, forever, void, unless, join)
27import Control.Exception (SomeException, throwIO, ErrorCall(..))
27import Control.Exception (SomeException, throwIO, ErrorCall(..))
28−import qualified Control.Exception as Ex (catch)
28+import Control.Monad.Catch (try, catch, finally, mask, onException)
29−import Control.Applicative ((<$>), (<*>), pure, (<|>))
29+import Control.Applicative ((<|>))
30import qualified Network.Transport as NT (closeEndPoint, EndPointAddress)
30import qualified Network.Transport as NT (closeEndPoint, EndPointAddress)
31−import Control.Distributed.Process
31+import Control.Distributed.Process hiding
32import Control.Distributed.Process.Internal.Types
38import Control.Distributed.Process.Internal.Types
33− ( NodeId(nodeAddress)
34− , LocalNode(localEndPoint)
39+ ( LocalNode(localEndPoint)
35 , ProcessExitException(..)
40 , ProcessExitException(..)
36 , nullProcessId
41 , nullProcessId
37 , createUnencodedMessage
42 , createUnencodedMessage
39import Control.Distributed.Process.Node
44import Control.Distributed.Process.Node
45+import Control.Distributed.Process.Debug
46+import Control.Distributed.Process.Management.Internal.Types
47+import Control.Distributed.Process.Tests.Internal.Utils (shouldBe)
40import Control.Distributed.Process.Serializable (Serializable)
48import Control.Distributed.Process.Serializable (Serializable)
42−import Test.HUnit (Assertion, assertFailure)
50+import Test.HUnit (Assertion, assertBool, assertFailure)
43import Test.Framework (Test, testGroup)
51import Test.Framework (Test, testGroup)
44import Test.Framework.Providers.HUnit (testCase)
52import Test.Framework.Providers.HUnit (testCase)
45import Control.Rematch hiding (match)
53import Control.Rematch hiding (match)
@@ -65,7 +73,7 @@ expectThat a matcher = case res of
65forkTry :: IO () -> IO ThreadId
73forkTry :: IO () -> IO ThreadId
66forkTry p = do
74forkTry p = do
67 tid <- myThreadId
75 tid <- myThreadId
68− forkIO $ Ex.catch p (\e -> throwTo tid (e :: SomeException))
76+ forkIO $ catch p (\e -> throwTo tid (e :: SomeException))
70-- | The ping server from the paper
78-- | The ping server from the paper
71ping :: Process ()
79ping :: Process ()
@@ -75,12 +83,47 @@ ping = do
75 send partner (Ping self)
83 send partner (Ping self)
86+verifyClient :: String -> MVar Bool -> IO ()
87+verifyClient s b = takeMVar b >>= assertBool s
89+expectPing :: MVar Bool -> Process ()
90+expectPing mv = expect >>= liftIO . putMVar mv . checkPing
92+ checkPing (Ping _) = True
78-- | Quick and dirty synchronous version of whereisRemoteAsync
95-- | Quick and dirty synchronous version of whereisRemoteAsync
79whereisRemote :: NodeId -> String -> Process (Maybe ProcessId)
96whereisRemote :: NodeId -> String -> Process (Maybe ProcessId)
80whereisRemote nid string = do
97whereisRemote nid string = do
81 whereisRemoteAsync nid string
98 whereisRemoteAsync nid string
82− WhereIsReply _ mPid <- expect
100+ match (\(WhereIsReply _ mPid) -> return mPid)
103+verifyWhereIsRemote :: NodeId -> String -> Process ProcessId
104+verifyWhereIsRemote n s = whereisRemote n s >>= maybe (die "remote name not found") return
106+waitForExit :: ProcessId -> Process DiedReason
107+waitForExit pid = monitor pid >>= waitForDown
109+waitForDown :: MonitorRef -> Process DiedReason
111+ receiveWait [ matchIf (\(ProcessMonitorNotification ref' _ _) -> ref == ref')
112+ (\(ProcessMonitorNotification _ _ dr) -> return dr) ]
114+syncBreakConnection :: (NT.EndPointAddress -> NT.EndPointAddress -> IO ()) -> LocalNode -> LocalNode -> IO ()
115+syncBreakConnection breakConnection nid0 nid1 = do
117+ _ <- forkProcess nid1 $ getSelfPid >>= liftIO . putMVar m
118+ runProcess nid0 $ do
119+ them <- liftIO $ takeMVar m
120+ pinger <- spawnLocal $ forever $ send them ()
121+ _ <- monitorNode (localNodeId nid1)
122+ liftIO $ breakConnection (nodeAddress $ localNodeId nid0)
123+ (nodeAddress $ localNodeId nid1)
124+ NodeMonitorNotification _ _ _ <- expect
125+ kill pinger "finished"
83− return mPid
126+ return ()
85data Add = Add ProcessId Double Double deriving (Typeable)
128data Add = Add ProcessId Double Double deriving (Typeable)
86data Divide = Divide ProcessId Double Double deriving (Typeable)
129data Divide = Divide ProcessId Double Double deriving (Typeable)
@@ -155,12 +198,18 @@ monitorTestProcess theirAddr mOrL un reason monitorSetup done =
155 unmonitor ref
198 unmonitor ref
156 liftIO $ putMVar done ()
199 liftIO $ putMVar done ()
157 (False, ref) -> do
200 (False, ref) -> do
158− ProcessMonitorNotification ref' pid reason' <- expect
202+ match (\(ProcessMonitorNotification ref' pid reason') -> do
204+ assertBool "Bad Monitor Signal"
159− True <- return $ Just ref' == ref && pid == theirAddr && mOrL && reason == reason'
205+ (Just ref' == ref && pid == theirAddr &&
206+ mOrL && reason == reason')
160− liftIO $ putMVar done ()
207+ putMVar done ())
162 (\(ProcessLinkException pid reason') -> do
210 (\(ProcessLinkException pid reason') -> do
211+ (liftIO $ assertBool "link exception unmatched" $
163− True <- return $ pid == theirAddr && not mOrL && not un && reason == reason'
212+ pid == theirAddr && not mOrL && not un && reason == reason')
164 liftIO $ putMVar done ()
213 liftIO $ putMVar done ()
@@ -191,8 +240,10 @@ testPing TestTransport{..} = do
191 pid <- getSelfPid
240 pid <- getSelfPid
192 replicateM_ numPings $ do
241 replicateM_ numPings $ do
193 send pingServer (Pong pid)
242 send pingServer (Pong pid)
194− Ping _ <- expect
243+ p <- expect
195− return ()
245+ Ping _ -> return ()
246+ _ -> die "Unexpected message"
197 putMVar clientDone ()
248 putMVar clientDone ()
@@ -279,7 +330,7 @@ testMonitorLocalDeadProcess TestTransport{..} mOrL un = do
279 runProcess localNode $ do
330 runProcess localNode $ do
280 monitor theirAddr
331 monitor theirAddr
281 -- wait for the process to die
332 -- wait for the process to die
282− ProcessMonitorNotification _ _ _ <- expect
333+ expect :: Process ProcessMonitorNotification
283 monitorTestProcess theirAddr mOrL un DiedUnknownId Nothing done
334 monitorTestProcess theirAddr mOrL un DiedUnknownId Nothing done
285 takeMVar done
336 takeMVar done
@@ -353,14 +404,17 @@ testMath TestTransport{..} = do
353 runProcess localNode $ do
404 runProcess localNode $ do
354 pid <- getSelfPid
405 pid <- getSelfPid
355 send mathServer (Add pid 1 2)
406 send mathServer (Add pid 1 2)
356− 3 <- expect :: Process Double
407+ three <- expect :: Process Double
357 send mathServer (Divide pid 8 2)
408 send mathServer (Divide pid 8 2)
358− 4 <- expect :: Process Double
409+ four <- expect :: Process Double
359 send mathServer (Divide pid 8 0)
410 send mathServer (Divide pid 8 0)
360− DivByZero <- expect
411+ divByZ <- expect
361− liftIO $ putMVar clientDone ()
412+ liftIO $ putMVar clientDone (three, four, divByZ)
363− takeMVar clientDone
414+ res <- takeMVar clientDone
416+ (3, 4, DivByZero) -> return ()
417+ _ -> error $ "Something went horribly wrong"
365-- | Send first message (i.e. connect) to an already terminated process
419-- | Send first message (i.e. connect) to an already terminated process
366-- (without monitoring); then send another message to a second process on
420-- (without monitoring); then send another message to a second process on
@@ -388,11 +442,9 @@ testSendToTerminated TestTransport{..} = do
388 pid <- getSelfPid
442 pid <- getSelfPid
389 send server1 "Hi"
443 send server1 "Hi"
390 send server2 (Pong pid)
444 send server2 (Pong pid)
392− True <- return $ pid' == server2
393− liftIO $ putMVar clientDone ()
445+ expectPing clientDone
395− takeMVar clientDone
447+ verifyClient "Expected Ping from server" clientDone
397-- | Test (non-zero) timeout
449-- | Test (non-zero) timeout
398testTimeout :: TestTransport -> Assertion
450testTimeout :: TestTransport -> Assertion
@@ -401,10 +453,10 @@ testTimeout TestTransport{..} = do
401 done <- newEmptyMVar
453 done <- newEmptyMVar
403 runProcess localNode $ do
455 runProcess localNode $ do
404− Nothing <- receiveTimeout 1000000 [match (\(Add _ _ _) -> return ())]
456+ res <- receiveTimeout 1000000 [match (\Add{} -> return ())]
405− liftIO $ putMVar done ()
457+ liftIO $ putMVar done $ res == Nothing
407− takeMVar done
459+ verifyClient "Expected receiveTimeout to timeout..." done
409-- | Test zero timeout
461-- | Test zero timeout
410testTimeout0 :: TestTransport -> Assertion
462testTimeout0 :: TestTransport -> Assertion
@@ -432,10 +484,9 @@ testTimeout0 TestTransport{..} = do
432 -- is not interested in, and then a single message that it wants
484 -- is not interested in, and then a single message that it wants
433 replicateM_ 10000 $ send server "Irrelevant message"
485 replicateM_ 10000 $ send server "Irrelevant message"
434 send server (Pong pid)
486 send server (Pong pid)
436− liftIO $ putMVar clientDone ()
487+ expectPing clientDone
438− takeMVar clientDone
489+ verifyClient "Expected Ping from server" clientDone
440-- | Test typed channels
491-- | Test typed channels
441testTypedChannels :: TestTransport -> Assertion
492testTypedChannels :: TestTransport -> Assertion
@@ -458,10 +509,10 @@ testTypedChannels TestTransport{..} = do
458 runProcess localNode $ do
509 runProcess localNode $ do
459 (clientSendPort, rport) <- newChan
510 (clientSendPort, rport) <- newChan
460 sendChan serverSendPort (clientSendPort, 5)
511 sendChan serverSendPort (clientSendPort, 5)
461− False <- receiveChan rport
512+ ch <- receiveChan rport
462− liftIO $ putMVar clientDone ()
513+ liftIO $ putMVar clientDone $ ch == False
464− takeMVar clientDone
515+ verifyClient "Expected channel to send 'False'" clientDone
466-- | Test merging receive ports
517-- | Test merging receive ports
467testMergeChannels :: TestTransport -> Assertion
518testMergeChannels :: TestTransport -> Assertion
@@ -484,9 +535,8 @@ testMergeChannels TestTransport{..} = do
484 rs <- mapM charChannel "abc"
535 rs <- mapM charChannel "abc"
485 m <- mergePorts biased rs
536 m <- mergePorts biased rs
486 xs <- replicateM 9 $ receiveChan m
537 xs <- replicateM 9 $ receiveChan m
487− True <- return $ xs == expected
488− liftIO $ putMVar done ()
538+ liftIO $ putMVar done $ xs == expected
489− takeMVar done
539+ verifyClient "Expected single layer merge to match expected ordering" done
491 -- Two layers of merging
541 -- Two layers of merging
492 testNested :: LocalNode -> Bool -> Bool -> String -> IO ()
542 testNested :: LocalNode -> Bool -> Bool -> String -> IO ()
@@ -497,9 +547,8 @@ testMergeChannels TestTransport{..} = do
497 ms <- mapM (mergePorts biasedInner) rss
547 ms <- mapM (mergePorts biasedInner) rss
498 m <- mergePorts biasedOuter ms
548 m <- mergePorts biasedOuter ms
499 xs <- replicateM (9 * 3) $ receiveChan m
549 xs <- replicateM (9 * 3) $ receiveChan m
500− True <- return $ xs == expected
550+ liftIO $ putMVar done $ xs == expected
501− liftIO $ putMVar done ()
551+ verifyClient "Expected nested channels to match expeted ordering" done
504 -- Test that if no messages are (immediately) available, the scheduler makes no difference
553 -- Test that if no messages are (immediately) available, the scheduler makes no difference
505 testBlocked :: LocalNode -> Bool -> IO ()
554 testBlocked :: LocalNode -> Bool -> IO ()
@@ -508,43 +557,45 @@ testMergeChannels TestTransport{..} = do
508 done <- newEmptyMVar
557 done <- newEmptyMVar
510 forkProcess localNode $ do
559 forkProcess localNode $ do
511− [sa, sb, sc] <- liftIO $ mapM readMVar vs
560+ ss <- liftIO $ mapM readMVar vs
512− mapM_ ((>> liftIO (threadDelay 10000)) . uncurry sendChan)
563+ mapM_ ((>> liftIO (threadDelay 10000)) . uncurry sendChan)
513− [ -- a, b, c
564+ [ -- a, b, c
514− (sa, 'a')
565+ (sa, 'a')
515− , (sb, 'b')
566+ , (sb, 'b')
516− , (sc, 'c')
567+ , (sc, 'c')
517− -- a, c, b
568+ -- a, c, b
518− , (sa, 'a')
569+ , (sa, 'a')
519− , (sc, 'c')
570+ , (sc, 'c')
520− , (sb, 'b')
571+ , (sb, 'b')
521− -- b, a, c
572+ -- b, a, c
522− , (sb, 'b')
573+ , (sb, 'b')
523− , (sa, 'a')
574+ , (sa, 'a')
524− , (sc, 'c')
575+ , (sc, 'c')
525− -- b, c, a
576+ -- b, c, a
526− , (sb, 'b')
577+ , (sb, 'b')
527− , (sc, 'c')
578+ , (sc, 'c')
528− , (sa, 'a')
579+ , (sa, 'a')
529− -- c, a, b
580+ -- c, a, b
530− , (sc, 'c')
581+ , (sc, 'c')
531− , (sa, 'a')
582+ , (sa, 'a')
532− , (sb, 'b')
583+ , (sb, 'b')
533− -- c, b, a
584+ -- c, b, a
534− , (sc, 'c')
585+ , (sc, 'c')
535− , (sb, 'b')
586+ , (sb, 'b')
536− , (sa, 'a')
587+ , (sa, 'a')
589+ _ -> die "Something went horribly wrong"
539 forkProcess localNode $ do
591 forkProcess localNode $ do
540 (ss, rs) <- unzip <$> replicateM 3 newChan
592 (ss, rs) <- unzip <$> replicateM 3 newChan
541 liftIO $ mapM_ (uncurry putMVar) $ zip vs ss
593 liftIO $ mapM_ (uncurry putMVar) $ zip vs ss
542 m <- mergePorts biased rs
594 m <- mergePorts biased rs
543 xs <- replicateM (6 * 3) $ receiveChan m
595 xs <- replicateM (6 * 3) $ receiveChan m
544− True <- return $ xs == "abcacbbacbcacabcba"
545− liftIO $ putMVar done ()
596+ liftIO $ putMVar done $ xs == "abcacbbacbcacabcba"
547− takeMVar done
598+ verifyClient "Expected merged ports to match expected ordering" done
549 mergePorts :: Serializable a => Bool -> [ReceivePort a] -> Process (ReceivePort a)
600 mergePorts :: Serializable a => Bool -> [ReceivePort a] -> Process (ReceivePort a)
550 mergePorts True = mergePortsBiased
601 mergePorts True = mergePortsBiased
@@ -562,8 +613,9 @@ testTerminate TestTransport{..} = do
562 localNode <- newLocalNode testTransport initRemoteTable
613 localNode <- newLocalNode testTransport initRemoteTable
563 runProcess localNode $ do
614 runProcess localNode $ do
564 e <- try terminate :: Process (Either ProcessTerminationException ())
615 e <- try terminate :: Process (Either ProcessTerminationException ())
565− True <- return $ either show show e == show ProcessTerminationException
616+ if either show show e == show ProcessTerminationException
566− return ()
617+ then return ()
618+ else die "Unexpected result from terminate"
568testMonitorNode :: TestTransport -> Assertion
620testMonitorNode :: TestTransport -> Assertion
569testMonitorNode TestTransport{..} = do
621testMonitorNode TestTransport{..} = do
@@ -574,11 +626,12 @@ testMonitorNode TestTransport{..} = do
575 runProcess node2 $ do
627 runProcess node2 $ do
576 ref <- monitorNode (localNodeId node1)
628 ref <- monitorNode (localNodeId node1)
577− NodeMonitorNotification ref' nid DiedDisconnect <- expect
630+ match (\(NodeMonitorNotification ref' nid DiedDisconnect) ->
578− True <- return $ ref == ref' && nid == localNodeId node1
631+ return $ ref == ref' && nid == localNodeId node1)
579− liftIO $ putMVar done ()
632+ ] >>= liftIO . putMVar done
581− takeMVar done
634+ verifyClient "Expected NodeMonitorNotification with matching ref & nodeId" done
583testMonitorLiveNode :: TestTransport -> Assertion
636testMonitorLiveNode :: TestTransport -> Assertion
584testMonitorLiveNode TestTransport{..} = do
637testMonitorLiveNode TestTransport{..} = do
@@ -593,15 +646,16 @@ testMonitorLiveNode TestTransport{..} = do
593 liftIO $ putMVar ready ()
646 liftIO $ putMVar ready ()
594 liftIO $ takeMVar readyr
647 liftIO $ takeMVar readyr
595 send p ()
648 send p ()
596− NodeMonitorNotification ref' nid _ <- expect
650+ match (\(NodeMonitorNotification ref' nid _) ->
597− True <- return $ ref == ref' && nid == localNodeId node1
651+ (return $ ref == ref' && nid == localNodeId node1))
598− liftIO $ putMVar done ()
652+ ] >>= liftIO . putMVar done
600 takeMVar ready
654 takeMVar ready
601 closeLocalNode node1
655 closeLocalNode node1
602 putMVar readyr ()
656 putMVar readyr ()
604− takeMVar done
658+ verifyClient "Expected NodeMonitorNotification for LIVE node" done
606testMonitorChannel :: TestTransport -> Assertion
660testMonitorChannel :: TestTransport -> Assertion
607testMonitorChannel TestTransport{..} = do
661testMonitorChannel TestTransport{..} = do
@@ -611,18 +665,20 @@ testMonitorChannel TestTransport{..} = do
611 pid <- forkProcess node1 $ do
665 pid <- forkProcess node1 $ do
612 sport <- expect :: Process (SendPort ())
666 sport <- expect :: Process (SendPort ())
613 ref <- monitorPort sport
667 ref <- monitorPort sport
614− PortMonitorNotification ref' port' reason <- expect
668+ receiveWait [
615− -- reason might be DiedUnknownId if the receive port is GCed before the
669+ -- reason might be DiedUnknownId if the receive port is GCed before the
616− -- monitor is established (TODO: not sure that this is reasonable)
670+ -- monitor is established (TODO: not sure that this is reasonable)
671+ match (\(PortMonitorNotification ref' port' reason) ->
672+ return $ ref' == ref && port' == sendPortId sport &&
617− return $ ref' == ref && port' == sendPortId sport && (reason == DiedNormal || reason == DiedUnknownId)
673+ (reason == DiedNormal || reason == DiedUnknownId))
618− liftIO $ putMVar gotNotification ()
674+ ] >>= liftIO . putMVar gotNotification
620 runProcess node2 $ do
676 runProcess node2 $ do
621 (sport, _) <- newChan :: Process (SendPort (), ReceivePort ())
677 (sport, _) <- newChan :: Process (SendPort (), ReceivePort ())
622 send pid sport
678 send pid sport
623 liftIO $ threadDelay 100000
679 liftIO $ threadDelay 100000
625− takeMVar gotNotification
681+ verifyClient "Expected PortMonitorNotification" gotNotification
627testRegistry :: TestTransport -> Assertion
683testRegistry :: TestTransport -> Assertion
628testRegistry TestTransport{..} = do
684testRegistry TestTransport{..} = do
@@ -634,20 +690,28 @@ testRegistry TestTransport{..} = do
635 runProcess node $ do
691 runProcess node $ do
636 register "ping" pingServer
692 register "ping" pingServer
637− Just pid <- whereis "ping"
693+ whereis "ping" >>= liftIO . assertBool "Unexpected ping" . (== Just pingServer)
638− True <- return $ pingServer == pid
639 us <- getSelfPid
694 us <- getSelfPid
640 nsend "ping" (Pong us)
695 nsend "ping" (Pong us)
641− Ping pid' <- expect
696+ receiveWait [
642− True <- return $ pingServer == pid'
697+ matchIf (\(Ping pid') -> pingServer == pid') (const $ return ())
643− Left (ProcessRegistrationException "dead" Nothing) <- try $ register "dead" deadProcess
698+ ]
644− Left (ProcessRegistrationException "ping" (Just x)) <- try $ register "ping" deadProcess
699+ checkRegException "dead" Nothing deadProcess
645− True <- return $ x == pingServer
700+ checkRegException "ping" (Just pingServer) deadProcess
646− Left (ProcessRegistrationException "dead" Nothing) <- try $ unregister "dead"
701+ try (unregister "dead") >>= checkReg "dead" Nothing
647 liftIO $ putMVar done ()
702 liftIO $ putMVar done ()
649 takeMVar done
704 takeMVar done
707+ checkRegException name pid dead =
708+ try (register name dead) >>= checkReg name pid
710+ checkReg name pid res =
712+ Left (ProcessRegistrationException name pid) -> return ()
713+ _ -> die $ "Unexpected Registration" ++ show res
651testRegistryRemoteProcess :: TestTransport -> Assertion
715testRegistryRemoteProcess :: TestTransport -> Assertion
652testRegistryRemoteProcess TestTransport{..} = do
716testRegistryRemoteProcess TestTransport{..} = do
653 node1 <- newLocalNode testTransport initRemoteTable
717 node1 <- newLocalNode testTransport initRemoteTable
@@ -658,13 +722,13 @@ testRegistryRemoteProcess TestTransport{..} = do
659 runProcess node2 $ do
723 runProcess node2 $ do
660 register "ping" pingServer
724 register "ping" pingServer
661− Just pid <- whereis "ping"
725+ whereis "ping" >>= liftIO . assertBool "Unexpected ping" . (== Just pingServer)
662− True <- return $ pingServer == pid
663 us <- getSelfPid
726 us <- getSelfPid
664 nsend "ping" (Pong us)
727 nsend "ping" (Pong us)
665− Ping pid' <- expect
728+ receiveWait [
666− True <- return $ pingServer == pid'
729+ matchIf (\(Ping pid') -> pingServer == pid')
667− liftIO $ putMVar done ()
730+ (const $ liftIO $ putMVar done ())
669 takeMVar done
733 takeMVar done
@@ -685,12 +749,13 @@ testRemoteRegistry TestTransport{..} = do
685 "ping" == label' && pid == pingServer)
749 "ping" == label' && pid == pingServer)
686 (\(RegisterReply _ _ _) -> return ()) ]
750 (\(RegisterReply _ _ _) -> return ()) ]
688− Just pid <- whereisRemote nid1 "ping"
752+ pid <- verifyWhereIsRemote nid1 "ping"
689− True <- return $ pingServer == pid
753+ liftIO $ assertBool "Expected pindServer to match pid" $ pingServer == pid
690 us <- getSelfPid
754 us <- getSelfPid
691 nsendRemote nid1 "ping" (Pong us)
755 nsendRemote nid1 "ping" (Pong us)
692− Ping pid' <- expect
756+ receiveWait [
693− True <- return $ pingServer == pid'
757+ match (\(Ping pid') -> return $ pingServer == pid')
758+ ] >>= liftIO . assertBool "Expected Ping with ping server's ProcessId"
695 -- test that if process was not registered Nothing is returned
760 -- test that if process was not registered Nothing is returned
696 -- in owner field.
761 -- in owner field.
@@ -700,8 +765,8 @@ testRemoteRegistry TestTransport{..} = do
700 (\(RegisterReply _ _ _) -> return ()) ]
765 (\(RegisterReply _ _ _) -> return ()) ]
701 registerRemoteAsync nid1 "ping" deadProcess
766 registerRemoteAsync nid1 "ping" deadProcess
702 receiveWait [
767 receiveWait [
703− matchIf (\(RegisterReply label' False (Just pid)) ->
768+ matchIf (\(RegisterReply label' False (Just pid'')) ->
704− "ping" == label' && pid == pingServer)
769+ "ping" == label' && pid'' == pingServer)
705 (\(RegisterReply _ _ _) -> return ()) ]
770 (\(RegisterReply _ _ _) -> return ()) ]
706 unregisterRemoteAsync nid1 "dead"
771 unregisterRemoteAsync nid1 "dead"
707 receiveWait [
772 receiveWait [
@@ -726,15 +791,15 @@ testRemoteRegistryRemoteProcess TestTransport{..} = do
726 receiveWait [
791 receiveWait [
727 matchIf (\(RegisterReply label' _ _) -> "ping" == label')
792 matchIf (\(RegisterReply label' _ _) -> "ping" == label')
728 (\(RegisterReply _ _ _) -> return ()) ]
793 (\(RegisterReply _ _ _) -> return ()) ]
729− Just pid <- whereisRemote nid1 "ping"
794+ pid <- verifyWhereIsRemote nid1 "ping"
730− True <- return $ pingServer == pid
795+ liftIO $ assertBool "Expected pingServer to match remote name" $ pingServer == pid
731 us <- getSelfPid
796 us <- getSelfPid
732 nsendRemote nid1 "ping" (Pong us)
797 nsendRemote nid1 "ping" (Pong us)
733− Ping pid' <- expect
798+ receiveWait [
734− True <- return $ pingServer == pid'
799+ match (\(Ping pid') -> return $ pingServer == pid')
735− liftIO $ putMVar done ()
800+ ] >>= liftIO . putMVar done
737− takeMVar done
802+ verifyClient "Expected Ping with ping server's ProcessId" done
739testSpawnLocal :: TestTransport -> Assertion
804testSpawnLocal :: TestTransport -> Assertion
740testSpawnLocal TestTransport{..} = do
805testSpawnLocal TestTransport{..} = do
@@ -748,15 +813,14 @@ testSpawnLocal TestTransport{..} = do
748 sport <- expect
813 sport <- expect
749 sendChan sport (1234 :: Int)
814 sendChan sport (1234 :: Int)
751− sport <- spawnChannelLocal $ \rport -> do
816+ sport <- spawnChannelLocal $
752− (1234 :: Int) <- receiveChan rport
817+ \rport -> (receiveChan rport :: Process Int) >>= send us
755 send pid sport
819 send pid sport
757− liftIO $ putMVar done ()
820+ expect >>= liftIO . putMVar done
759− takeMVar done
822+ res <- takeMVar done
823+ assertBool "Expected 1234 :: Int" $ res == (1234 :: Int)
761testSpawnAsyncStrictness :: TestTransport -> Assertion
825testSpawnAsyncStrictness :: TestTransport -> Assertion
762testSpawnAsyncStrictness TestTransport{..} = do
826testSpawnAsyncStrictness TestTransport{..} = do
@@ -785,8 +849,9 @@ testReconnect TestTransport{..} = do
785 liftIO $ putMVar processA us
849 liftIO $ putMVar processA us
786 msg1 <- expect
850 msg1 <- expect
787 msg2 <- expect
851 msg2 <- expect
788− True <- return $ msg1 == "message 1" && msg2 == "message 3"
853+ assertBool "messages did not match" $ msg1 == "message 1" && msg2 == "message 3"
789− liftIO $ putMVar sendTestOk ()
854+ putMVar sendTestOk ()
791 forkProcess node2 $ do
856 forkProcess node2 $ do
@@ -819,7 +884,7 @@ testReconnect TestTransport{..} = do
819 matchIf (\(RegisterReply label' _ _) -> "a" == label')
884 matchIf (\(RegisterReply label' _ _) -> "a" == label')
820 (\(RegisterReply _ _ _) -> return ()) ]
885 (\(RegisterReply _ _ _) -> return ()) ]
822− Just _ <- whereisRemote nid1 "a"
887+ _ <- whereisRemote nid1 "a"
825 -- Simulate network failure
890 -- Simulate network failure
@@ -838,9 +903,10 @@ testReconnect TestTransport{..} = do
838 (\(RegisterReply _ _ _) -> return ()) ]
903 (\(RegisterReply _ _ _) -> return ()) ]
841− Nothing <- whereisRemote nid1 "a" -- this will fail because the name is removed when the node is disconnected
906+ mPid <- whereisRemote nid1 "a" -- this will fail because the name is removed when the node is disconnected
907+ liftIO $ assertBool "Expected remote name to be lost" $ mPid == Nothing
842− Just _ <- whereisRemote nid1 "b" -- this will suceed because the value is set after thereconnect
908+ verifyWhereIsRemote nid1 "b" -- this will suceed because the value is set after thereconnect
843− Just _ <- whereisRemote nid1 "c"
909+ verifyWhereIsRemote nid1 "c"
845 liftIO $ putMVar registerTestOk ()
911 liftIO $ putMVar registerTestOk ()
@@ -881,19 +947,19 @@ testUSend usendPrim TestTransport{..} numMessages = do
881 isSorted _ = True
947 isSorted _ = True
882 -- The list can't be null since there are no failures after sending
948 -- The list can't be null since there are no failures after sending
883 -- the last message.
949 -- the last message.
884− True <- return $ isSorted msgs && not (null msgs)
950+ liftIO $ putMVar usendTestOk $ isSorted msgs && not (null msgs)
885− liftIO $ putMVar usendTestOk ()
887 forkProcess node2 $ do
952 forkProcess node2 $ do
888 them <- liftIO $ readMVar processA
953 them <- liftIO $ readMVar processA
889 getSelfPid >>= send them
954 getSelfPid >>= send them
890− () <- expect
955+ expect :: Process ()
891 forM_ [1..numMessages] $ \i -> do
956 forM_ [1..numMessages] $ \i -> do
892 liftIO $ testBreakConnection (nodeAddress nid1) (nodeAddress nid2)
957 liftIO $ testBreakConnection (nodeAddress nid1) (nodeAddress nid2)
893 usendPrim them i
958 usendPrim them i
894 liftIO (threadDelay 30000)
959 liftIO (threadDelay 30000)
896− takeMVar usendTestOk
961+ res <- takeMVar usendTestOk
962+ assertBool "Unexpected failure after sending last msg" res
898-- | Test 'matchAny'. This repeats the 'testMath' but with a proxy server
964-- | Test 'matchAny'. This repeats the 'testMath' but with a proxy server
899-- in between
965-- in between
@@ -919,14 +985,17 @@ testMatchAny TestTransport{..} = do
919 runProcess localNode $ do
985 runProcess localNode $ do
920 pid <- getSelfPid
986 pid <- getSelfPid
921 send mathServer (Add pid 1 2)
987 send mathServer (Add pid 1 2)
922− 3 <- expect :: Process Double
988+ three <- expect :: Process Double
923 send mathServer (Divide pid 8 2)
989 send mathServer (Divide pid 8 2)
924− 4 <- expect :: Process Double
990+ four <- expect :: Process Double
925 send mathServer (Divide pid 8 0)
991 send mathServer (Divide pid 8 0)
926− DivByZero <- expect
992+ divByZ <- expect
927− liftIO $ putMVar clientDone ()
993+ liftIO $ putMVar clientDone (three, four, divByZ)
929− takeMVar clientDone
995+ res <- takeMVar clientDone
997+ (3, 4, DivByZero) -> return ()
998+ _ -> error "Unexpected result"
931-- | Test 'matchAny'. This repeats the 'testMath' but with a proxy server
1000-- | Test 'matchAny'. This repeats the 'testMath' but with a proxy server
932-- in between, however we block 'Divide' requests ....
1001-- in between, however we block 'Divide' requests ....
@@ -953,12 +1022,13 @@ testMatchAnyHandle TestTransport{..} = do
953 runProcess localNode $ do
1022 runProcess localNode $ do
954 pid <- getSelfPid
1023 pid <- getSelfPid
955 send mathServer (Add pid 1 2)
1024 send mathServer (Add pid 1 2)
956− 3 <- expect :: Process Double
1025+ three <- expect :: Process Double
957 send mathServer (Divide pid 8 2)
1026 send mathServer (Divide pid 8 2)
958− Nothing <- (expectTimeout 100000) :: Process (Maybe Double)
1027+ res <- (expectTimeout 100000) :: Process (Maybe Double)
959− liftIO $ putMVar clientDone ()
1028+ liftIO $ putMVar clientDone $ three == 3 && res == Nothing
1030+ verifyClient "Expected Nothing (i.e. timeout)" clientDone
962 where maybeForward :: ProcessId -> Message -> Process (Maybe ())
1032 where maybeForward :: ProcessId -> Message -> Process (Maybe ())
963 maybeForward s msg =
1033 maybeForward s msg =
964 handleMessage msg (\m@(Add _ _ _) -> send s m)
1034 handleMessage msg (\m@(Add _ _ _) -> send s m)
@@ -986,8 +1056,10 @@ testMatchAnyNoHandle TestTransport{..} = do
986 Just _ -> die "NONSENSE")
1056 Just _ -> die "NONSENSE")
988 -- we *must* have removed the message from our mailbox though!!!
1058 -- we *must* have removed the message from our mailbox though!!!
989− Nothing <- receiveTimeout 100000 [ match (\(Add _ _ _) -> return ()) ]
1059+ res <- receiveTimeout 100000 [ match (\(Add _ _ _) -> return ()) ]
1061+ assertBool "Expected timeout!" $ res == Nothing
990− liftIO $ putMVar serverDone ()
1062+ putMVar serverDone ()
991 putMVar addr server
1063 putMVar addr server
993 -- Client
1065 -- Client
@@ -1030,14 +1102,21 @@ testMatchAnyIf TestTransport{..} = do
1030 runProcess localNode $ do
1102 runProcess localNode $ do
1031 pid <- getSelfPid
1103 pid <- getSelfPid
1032 send server (pid, "foo")
1104 send server (pid, "foo")
1033− "foo" <- expect
1105+ foo <- expect
1034− send server (pid, "baz")
1106+ -- provoking what would be the wrong ordering is informative here...
1035− "baz" <- expect
1107+
1036 send server (pid, "bar")
1108 send server (pid, "bar")
1037− Nothing <- (expectTimeout 100000) :: Process (Maybe Double)
1109+ bar <- (expectTimeout 100000) :: Process (Maybe String) -- was Double o_O !?
1111+ send server (pid, "baz")
1038− liftIO $ putMVar clientDone ()
1114+ liftIO $ putMVar clientDone (foo, bar, baz)
1116+ res <- takeMVar clientDone
1117+ let res' = res == ("foo", Nothing, "baz")
1118+ assertBool "Expected timeout due to type mismatch" res'
1040− takeMVar clientDone
1041 where tryHandleMessage :: Message -> Process (Maybe ())
1120 where tryHandleMessage :: Message -> Process (Maybe ())
1042 tryHandleMessage msg =
1121 tryHandleMessage msg =
1043 handleMessage msg (\(pid :: ProcessId, (m :: String))
1122 handleMessage msg (\(pid :: ProcessId, (m :: String))
@@ -1070,12 +1149,13 @@ testMatchMessageWithUnwrap TestTransport{..} = do
1070 runProcess localNode $ do
1149 runProcess localNode $ do
1071 pid <- getSelfPid
1150 pid <- getSelfPid
1072 send server (pid, wrapMessage ("foo" :: String))
1151 send server (pid, wrapMessage ("foo" :: String))
1073− "foo" <- expect
1152+ foo <- expect
1074 send server (pid, wrapMessage ("baz" :: String))
1153 send server (pid, wrapMessage ("baz" :: String))
1075− "baz" <- expect
1154+ baz <- expect
1076− liftIO $ putMVar clientDone ()
1155+ liftIO $ putMVar clientDone (foo, baz)
1078− takeMVar clientDone
1157+ res <- takeMVar clientDone
1158+ assertBool "Unexpected unwrapped results" $ res == ("foo", "baz")
1080-- Test 'receiveChanTimeout'
1160-- Test 'receiveChanTimeout'
1081testReceiveChanTimeout :: TestTransport -> Assertion
1161testReceiveChanTimeout :: TestTransport -> Assertion
@@ -1093,18 +1173,19 @@ testReceiveChanTimeout TestTransport{..} = do
1094 -- Wait for a message with a delay. No message arrives, we should get
1174 -- Wait for a message with a delay. No message arrives, we should get
1095 -- Nothing after the delay.
1175 -- Nothing after the delay.
1096− Nothing <- receiveChanTimeout 100000 rp
1176+ receiveChanTimeout 100000 rp >>= maybe (return ()) (const $ die "Expected Timeout")
1098 -- Let the sender know that it can send a message.
1178 -- Let the sender know that it can send a message.
1099 liftIO $ putMVar mvSender ()
1179 liftIO $ putMVar mvSender ()
1101 -- Wait for a message with a delay again. Now a message arrives after
1181 -- Wait for a message with a delay again. Now a message arrives after
1102 -- 0.1 seconds
1182 -- 0.1 seconds
1103− Just True <- receiveChanTimeout 20000000 rp
1183+ res <- receiveChanTimeout 20000000 rp >>= maybe (die "Timeout") return
1184+ liftIO $ assertBool "Expected result to be 'True'" res
1105 -- Wait for a message with zero timeout: non-blocking check. No message is
1186 -- Wait for a message with zero timeout: non-blocking check. No message is
1106 -- available, we get Nothing
1187 -- available, we get Nothing
1107− Nothing <- receiveChanTimeout 0 rp
1188+ receiveChanTimeout 0 rp >>= maybe (return ()) (const $ die "Expected Timeout")
1109 -- Let the sender know that it can send a message.
1190 -- Let the sender know that it can send a message.
1110 liftIO $ putMVar mvSender ()
1191 liftIO $ putMVar mvSender ()
@@ -1114,7 +1195,7 @@ testReceiveChanTimeout TestTransport{..} = do
1114 liftIO $ threadDelay 100000
1195 liftIO $ threadDelay 100000
1115 mb <- receiveChanTimeout 0 rp
1196 mb <- receiveChanTimeout 0 rp
1116 case mb of
1197 case mb of
1117− Just b -> do False <- return b; return ()
1198+ Just b -> do liftIO $ assertBool "Unexpected Message" $ not b
1118 _ -> loop
1199 _ -> loop
1120 liftIO $ putMVar done ()
1201 liftIO $ putMVar done ()
@@ -1151,8 +1232,8 @@ testReceiveChanFeatures TestTransport{..} = do
1152 rp1 <- mergePortsBiased [even <$> rpInt, rpBool]
1233 rp1 <- mergePortsBiased [even <$> rpInt, rpBool]
1154− True <- receiveChan rp1
1235+ receiveChan rp1 >>= liftIO . assertBool "Expected True"
1155− False <- receiveChan rp1
1236+ receiveChan rp1 >>= liftIO . assertBool "Expected False" . not
1157 -- Test Applicative instance
1238 -- Test Applicative instance
@@ -1161,7 +1242,7 @@ testReceiveChanFeatures TestTransport{..} = do
1162 let rp2 = pure (+) <*> rpInt <*> rpInt
1243 let rp2 = pure (+) <*> rpInt <*> rpInt
1164− 7 <- receiveChan rp2
1245+ receiveChan rp2 >>= liftIO . assertBool "Expected 7" . (== 7)
1166 -- Test Alternative instance
1247 -- Test Alternative instance
@@ -1170,8 +1251,8 @@ testReceiveChanFeatures TestTransport{..} = do
1171 let rp3 = (even <$> rpInt) <|> rpBool
1252 let rp3 = (even <$> rpInt) <|> rpBool
1173− False <- receiveChan rp3
1254+ receiveChan rp3 >>= liftIO . assertBool "Expected False" . not
1174− True <- receiveChan rp3
1255+ receiveChan rp3 >>= liftIO . assertBool "Expected True"
1176 -- Test Monad instance
1257 -- Test Monad instance
@@ -1185,8 +1266,8 @@ testReceiveChanFeatures TestTransport{..} = do
1185 then rpInt
1266 then rpInt
1186 else return 7
1267 else return 7
1188− 5 <- receiveChan rp4
1269+ receiveChan rp4 >>= liftIO . assertBool "Expected 5" . (== 5)
1189− 7 <- receiveChan rp4
1270+ receiveChan rp4 >>= liftIO . assertBool "Expected 7" . (== 7)
1191 liftIO $ putMVar done ()
1272 liftIO $ putMVar done ()
@@ -1195,7 +1276,6 @@ testReceiveChanFeatures TestTransport{..} = do
1195testKillLocal :: TestTransport -> Assertion
1276testKillLocal :: TestTransport -> Assertion
1196testKillLocal TestTransport{..} = do
1277testKillLocal TestTransport{..} = do
1197 localNode <- newLocalNode testTransport initRemoteTable
1278 localNode <- newLocalNode testTransport initRemoteTable
1198− done <- newEmptyMVar
1200 pid <- forkProcess localNode $ do
1280 pid <- forkProcess localNode $ do
1201 liftIO $ threadDelay 1000000
1281 liftIO $ threadDelay 1000000
@@ -1204,17 +1284,18 @@ testKillLocal TestTransport{..} = do
1204 ref <- monitor pid
1284 ref <- monitor pid
1205 us <- getSelfPid
1285 us <- getSelfPid
1206 kill pid "TestKill"
1286 kill pid "TestKill"
1207− ProcessMonitorNotification ref' pid' (DiedException ex) <- expect
1287+ mn <- expect
1289+ ProcessMonitorNotification ref' pid' (DiedException ex) ->
1208− True <- return $ ref == ref' && pid == pid' && ex == "killed-by=" ++ show us ++ ",reason=TestKill"
1290+ case ref == ref' && pid == pid' && ex == "killed-by=" ++ show us ++ ",reason=TestKill" of
1209− liftIO $ putMVar done ()
1291+ True -> return ()
1210−
1292+ False -> die "Invalid ProcessMonitorNotification received"
1211− takeMVar done
1293+ _ -> die "Something went horribly wrong"
1213testKillRemote :: TestTransport -> Assertion
1295testKillRemote :: TestTransport -> Assertion
1214testKillRemote TestTransport{..} = do
1296testKillRemote TestTransport{..} = do
1215 node1 <- newLocalNode testTransport initRemoteTable
1297 node1 <- newLocalNode testTransport initRemoteTable
1216 node2 <- newLocalNode testTransport initRemoteTable
1298 node2 <- newLocalNode testTransport initRemoteTable
1217− done <- newEmptyMVar
1219 pid <- forkProcess node1 $ do
1300 pid <- forkProcess node1 $ do
1220 liftIO $ threadDelay 1000000
1301 liftIO $ threadDelay 1000000
@@ -1223,11 +1304,17 @@ testKillRemote TestTransport{..} = do
1223 ref <- monitor pid
1304 ref <- monitor pid
1224 us <- getSelfPid
1305 us <- getSelfPid
1225 kill pid "TestKill"
1306 kill pid "TestKill"
1226− ProcessMonitorNotification ref' pid' (DiedException reason) <- expect
1309+ ProcessMonitorNotification ref' pid' (DiedException reason) ->
1227− True <- return $ ref == ref' && pid == pid' && reason == "killed-by=" ++ show us ++ ",reason=TestKill"
1310+ case (ref == ref', pid == pid', reason == "killed-by=" ++ show us ++ ",reason=TestKill") of
1228− liftIO $ putMVar done ()
1311+ (True, True, True) -> return ()
1229−
1312+ (a, b, c) -> do
1230− takeMVar done
1313+ let a' = if a then "" else "Invalid ref"
1314+ let b' = if b then "" else "Invalid pid"
1315+ let c' = if c then "" else "Invalid message"
1316+ die $ unwords [a', b', c']
1317+ _ -> die "Received unexpected message"
1232testCatchesExit :: TestTransport -> Assertion
1319testCatchesExit :: TestTransport -> Assertion
1233testCatchesExit TestTransport{..} = do
1320testCatchesExit TestTransport{..} = do
@@ -1253,7 +1340,10 @@ testHandleMessageIf TestTransport{..} = do
1253 self <- getSelfPid
1340 self <- getSelfPid
1254 send self (5 :: Integer, 10 :: Integer)
1341 send self (5 :: Integer, 10 :: Integer)
1255 msg <- receiveWait [ matchMessage return ]
1342 msg <- receiveWait [ matchMessage return ]
1256− Nothing <- handleMessageIf msg (\() -> True) (\() -> die $ "whoops")
1343+ handleMessageIf msg
1345+ (\() -> die "whoops") >>= maybe (return ())
1346+ (const $ die "Expected Mismatch")
1257 handleMessageIf msg (\(x :: Integer, y :: Integer) -> x == 5 && y == 10)
1347 handleMessageIf msg (\(x :: Integer, y :: Integer) -> x == 5 && y == 10)
1258 (\input -> liftIO $ putMVar done input)
1348 (\input -> liftIO $ putMVar done input)
1259 return ()
1349 return ()
@@ -1298,8 +1388,11 @@ testDie TestTransport{..} = do
1298 (die ("foobar", 123 :: Int))
1388 (die ("foobar", 123 :: Int))
1299 `catchExit` \_from reason -> do
1389 `catchExit` \_from reason -> do
1300 -- TODO: should verify that 'from' has the right value
1390 -- TODO: should verify that 'from' has the right value
1301− True <- return $ reason == ("foobar", 123 :: Int)
1391+ let res = reason == ("foobar", 123 :: Int)
1302 liftIO $ putMVar done ()
1392 liftIO $ putMVar done ()
1395+ else die "Something went horribly wrong"
1304 takeMVar done
1397 takeMVar done
@@ -1313,8 +1406,11 @@ testPrettyExit TestTransport{..} = do
1313 `catch` \ex@(ProcessExitException from _) ->
1406 `catch` \ex@(ProcessExitException from _) ->
1314 let expected = "exit-from=" ++ (show from)
1407 let expected = "exit-from=" ++ (show from)
1316− True <- return $ (show ex) == expected
1409+ let res = (show ex) == expected
1317 liftIO $ putMVar done ()
1410 liftIO $ putMVar done ()
1413+ else die "Something went horribly wrong"
1319 takeMVar done
1415 takeMVar done
@@ -1330,17 +1426,26 @@ testExitLocal TestTransport{..} = do
1330 pid <- forkProcess localNode $ do
1426 pid <- forkProcess localNode $ do
1331 (liftIO (putMVar handlerSetUp ()) >> expect) `catchExit` \_from reason -> do
1427 (liftIO (putMVar handlerSetUp ()) >> expect) `catchExit` \_from reason -> do
1332 -- TODO: should verify that 'from' has the right value
1428 -- TODO: should verify that 'from' has the right value
1333− True <- return $ reason == "TestExit"
1429+ res <- return $ reason == "TestExit"
1334 liftIO $ putMVar supervisedDone ()
1430 liftIO $ putMVar supervisedDone ()
1433+ else die "Something went horribly wrong"
1336 runProcess localNode $ do
1435 runProcess localNode $ do
1337 liftIO $ takeMVar handlerSetUp
1436 liftIO $ takeMVar handlerSetUp
1338 ref <- monitor pid
1437 ref <- monitor pid
1339 exit pid "TestExit"
1438 exit pid "TestExit"
1340 -- This time the client catches the exception, so it dies normally
1439 -- This time the client catches the exception, so it dies normally
1341− ProcessMonitorNotification ref' pid' DiedNormal <- expect
1442+ ProcessMonitorNotification ref' pid' DiedNormal -> do
1342− True <- return $ ref == ref' && pid == pid'
1443+ let res = ref == ref' && pid == pid'
1343− liftIO $ putMVar supervisorDone ()
1444+ liftIO $ putMVar supervisorDone ()
1447+ else die "Something went horribly wrong"
1448+ _ -> die "Something went horribly wrong"
1345 takeMVar supervisedDone
1450 takeMVar supervisedDone
1346 takeMVar supervisorDone
1451 takeMVar supervisorDone
@@ -1356,19 +1461,90 @@ testExitRemote TestTransport{..} = do
1356 (receiveWait [] :: Process ()) -- block forever
1461 (receiveWait [] :: Process ()) -- block forever
1357 `catchExit` \_from reason -> do
1462 `catchExit` \_from reason -> do
1358 -- TODO: should verify that 'from' has the right value
1463 -- TODO: should verify that 'from' has the right value
1359− True <- return $ reason == "TestExit"
1464+ res <- return $ reason == "TestExit"
1360 liftIO $ putMVar supervisedDone ()
1465 liftIO $ putMVar supervisedDone ()
1468+ else die "Something went horribly wrong"
1362 runProcess node2 $ do
1470 runProcess node2 $ do
1363 ref <- monitor pid
1471 ref <- monitor pid
1364 exit pid "TestExit"
1472 exit pid "TestExit"
1365− ProcessMonitorNotification ref' pid' DiedNormal <- expect
1475+ ProcessMonitorNotification ref' pid' DiedNormal -> do
1366− True <- return $ ref == ref' && pid == pid'
1476+ res' <- return $ ref == ref' && pid == pid'
1367− liftIO $ putMVar supervisorDone ()
1477+ liftIO $ putMVar supervisorDone ()
1480+ else die "Something went horribly wrong"
1481+ _ -> die "Something went horribly wrong"
1369 takeMVar supervisedDone
1483 takeMVar supervisedDone
1370 takeMVar supervisorDone
1484 takeMVar supervisorDone
1486+testRegistryMonitoring :: TestTransport -> Assertion
1487+testRegistryMonitoring TestTransport{..} = do
1488+ node1 <- newLocalNode testTransport initRemoteTable
1489+ node2 <- newLocalNode testTransport initRemoteTable
1490+ waitH <- newEmptyMVar
1492+ let nid = localNodeId node2
1493+ pid <- forkProcess node1 $ do
1494+ getSelfPid >>= runUntilRegistered nid
1495+ liftIO $ takeMVar waitH
1497+ runProcess node2 $ do
1498+ register regName pid
1499+ res <- whereis regName
1503+ assertBool "expected (Just pid)" $ res == (Just pid)
1505+ -- This delay isn't essential!
1506+ -- The test case passes perfectly fine without it (feel free to comment out
1507+ -- and see), however waiting a few seconds here, makes it much more likely
1508+ -- that in delayUntilMaybeUnregistered we will hit the match case right
1509+ -- away, and thus not be subjected to a 20 second delay. The value of 4
1510+ -- seconds appears to work optimally on osx and across several linux distros
1511+ -- running in virtual machines (which is essentially what we do in CI)
1512+ void $ receiveTimeout 4000000 [ matchAny return ]
1514+ -- This delay doesn't serve much purpose in the happy path, however if some
1515+ -- future patch breaks the cooperative behaviour of node controllers viz
1516+ -- remote process registration and notification taking place via ncEffectDied,
1517+ -- there would be the possibility of a race in the test case should we attempt
1518+ -- to evaluate `whereis regName` on node2 right away. In case the name is still
1519+ -- erroneously registered, observing the 20 second delay (or lack of), could at
1520+ -- least give a hint that something is wrong, and we give up our time slice
1521+ -- so that there's a higher change the registrations have been cleaned up
1523+ runProcess node2 $ delayUntilMaybeUnregistered nid pid
1525+ regHere <- newEmptyMVar
1526+ runProcess node2 $ whereis regName >>= liftIO . putMVar regHere
1527+ res <- takeMVar regHere
1528+ assertBool "expected Nothing, but process still registered" (res == Nothing)
1531+ runUntilRegistered nid us = do
1532+ whereisRemoteAsync nid regName
1534+ matchIf (\(WhereIsReply n (Just p)) -> n == regName && p == us)
1535+ (const $ return ())
1538+ delayUntilMaybeUnregistered nid p = do
1539+ whereisRemoteAsync nid regName
1540+ receiveTimeout 20000000 {- 20 sec delay -} [
1541+ matchIf (\(WhereIsReply n p) -> n == regName && p == Nothing)
1542+ (const $ return ())
1546+ regName = "testRegisterRemote"
1372testUnsafeSend :: TestTransport -> Assertion
1548testUnsafeSend :: TestTransport -> Assertion
1373testUnsafeSend TestTransport{..} = do
1549testUnsafeSend TestTransport{..} = do
1374 serverAddr <- newEmptyMVar
1550 serverAddr <- newEmptyMVar
@@ -1384,8 +1560,7 @@ testUnsafeSend TestTransport{..} = do
1384 void $ forkProcess localNode $ do
1560 void $ forkProcess localNode $ do
1385 serverPid <- liftIO $ takeMVar serverAddr
1561 serverPid <- liftIO $ takeMVar serverAddr
1386 getSelfPid >>= unsafeSend serverPid
1562 getSelfPid >>= unsafeSend serverPid
1388− liftIO $ putMVar clientDone ()
1563+ expect >>= liftIO . putMVar clientDone
1390 takeMVar clientDone
1565 takeMVar clientDone
@@ -1404,8 +1579,7 @@ testUnsafeUSend TestTransport{..} = do
1404 void $ forkProcess localNode $ do
1579 void $ forkProcess localNode $ do
1405 serverPid <- liftIO $ takeMVar serverAddr
1580 serverPid <- liftIO $ takeMVar serverAddr
1406 getSelfPid >>= unsafeUSend serverPid
1581 getSelfPid >>= unsafeUSend serverPid
1408− liftIO $ putMVar clientDone ()
1582+ expect >>= liftIO . putMVar clientDone
1410 takeMVar clientDone
1584 takeMVar clientDone
@@ -1416,8 +1590,7 @@ testUnsafeNSend TestTransport{..} = do
1416 localNode <- newLocalNode testTransport initRemoteTable
1590 localNode <- newLocalNode testTransport initRemoteTable
1418 pid <- forkProcess localNode $ do
1592 pid <- forkProcess localNode $ do
1420− liftIO $ putMVar clientDone ()
1593+ expect >>= liftIO . putMVar clientDone
1422 void $ runProcess localNode $ do
1595 void $ runProcess localNode $ do
1423 register "foobar" pid
1596 register "foobar" pid
@@ -1435,8 +1608,7 @@ testUnsafeNSendRemote TestTransport{..} = do
1435 _ <- forkProcess localNode1 $ do
1608 _ <- forkProcess localNode1 $ do
1436 getSelfPid >>= register "foobar"
1609 getSelfPid >>= register "foobar"
1437 liftIO $ putMVar clientDone ()
1610 liftIO $ putMVar clientDone ()
1439− liftIO $ putMVar clientDone ()
1611+ expect >>= liftIO . putMVar clientDone
1441 takeMVar clientDone
1613 takeMVar clientDone
1442 void $ runProcess localNode2 $ do
1614 void $ runProcess localNode2 $ do
@@ -1460,7 +1632,7 @@ testUnsafeSendChan TestTransport{..} = do
1460 serverPid <- liftIO $ takeMVar serverAddr
1632 serverPid <- liftIO $ takeMVar serverAddr
1461 (sp, rp) <- newChan
1633 (sp, rp) <- newChan
1462 unsafeSend serverPid sp
1634 unsafeSend serverPid sp
1463− () <- receiveChan rp
1635+ receiveChan rp :: Process ()
1464 liftIO $ putMVar clientDone ()
1636 liftIO $ putMVar clientDone ()
1466 takeMVar clientDone
1638 takeMVar clientDone
@@ -1474,8 +1646,8 @@ testCallLocal TestTransport{..} = do
1474 runProcess node $ do
1646 runProcess node $ do
1475 r <- (/=) <$> getSelfPid <*> callLocal getSelfPid
1647 r <- (/=) <$> getSelfPid <*> callLocal getSelfPid
1476 liftIO $ putMVar result r
1648 liftIO $ putMVar result r
1477− True <- takeMVar result
1650+ takeMVar result >>= assertBool "Expected 'True'"
1480 -- Testing that when callLocal is interrupted, the worker is interrupted.
1652 -- Testing that when callLocal is interrupted, the worker is interrupted.
1481 ibox <- newIORef False
1653 ibox <- newIORef False
@@ -1492,10 +1664,9 @@ testCallLocal TestTransport{..} = do
1492 (send keeper ())
1664 (send keeper ())
1493 caller <- expect
1665 caller <- expect
1494 exit caller "test"
1666 exit caller "test"
1495− () <- expect
1667+ expect :: Process ()
1497− True <- readIORef ibox
1669+ readIORef ibox >>= assertBool "Expected 'True'"
1500 -- Testing that when the worker raises an exception, the exception is propagated to the parent.
1671 -- Testing that when the worker raises an exception, the exception is propagated to the parent.
1501 ibox2 <- newIORef False
1672 ibox2 <- newIORef False
@@ -1504,8 +1675,8 @@ testCallLocal TestTransport{..} = do
1504 liftIO $ writeIORef ibox2 $ case r of
1675 liftIO $ writeIORef ibox2 $ case r of
1505 Left (ErrorCall "e") -> True
1676 Left (ErrorCall "e") -> True
1506 _ -> False
1677 _ -> False
1507− True <- readIORef ibox
1679+ readIORef ibox >>= assertBool "Expected 'True'"
1510 -- Test that caller waits for the worker in correct situation
1681 -- Test that caller waits for the worker in correct situation
1511 ibox3 <- newIORef False
1682 ibox3 <- newIORef False
@@ -1522,8 +1693,8 @@ testCallLocal TestTransport{..} = do
1522 liftIO $ putMVar result3 =<< readIORef ibox3
1693 liftIO $ putMVar result3 =<< readIORef ibox3
1523 worker <- expect
1694 worker <- expect
1524 send worker ()
1695 send worker ()
1525− True <- takeMVar result3
1697+ takeMVar result3 >>= assertBool "Expected 'True'"
1528 -- Test that caller waits for the worker in case when caller gets an exception
1699 -- Test that caller waits for the worker in case when caller gets an exception
1529 ibox4 <- newIORef False
1700 ibox4 <- newIORef False
@@ -1539,13 +1710,9 @@ testCallLocal TestTransport{..} = do
1539 `finally` (liftIO $ putMVar result4 =<< readIORef ibox4)
1710 `finally` (liftIO $ putMVar result4 =<< readIORef ibox4)
1540 caller <- expect
1711 caller <- expect
1541 exit caller "hi!"
1712 exit caller "hi!"
1542− True <- takeMVar result4
1544− -- XXX: Testing that when mask_ $ callLocal p runs p in masked state.
1714+ takeMVar result4 >>= assertBool "Expected 'True'"
1715+ -- XXX: Testing that when mask_ $ callLocal p runs p in masked state.
1550tests :: TestTransport -> IO [Test]
1717tests :: TestTransport -> IO [Test]
1551tests testtrans = return [
1718tests testtrans = return [
@@ -1579,6 +1746,7 @@ tests testtrans = return [
1579 , testCase "MaskRestoreScope" (testMaskRestoreScope testtrans)
1746 , testCase "MaskRestoreScope" (testMaskRestoreScope testtrans)
1580 , testCase "ExitLocal" (testExitLocal testtrans)
1747 , testCase "ExitLocal" (testExitLocal testtrans)
1581 , testCase "ExitRemote" (testExitRemote testtrans)
1748 , testCase "ExitRemote" (testExitRemote testtrans)
1749+ , testCase "RegistryMonitoring" (testRegistryMonitoring testtrans)
1582 , testCase "TextCallLocal" (testCallLocal testtrans)
1750 , testCase "TextCallLocal" (testCallLocal testtrans)
1583 -- Unsafe Primitives
1751 -- Unsafe Primitives
1584 , testCase "TestUnsafeSend" (testUnsafeSend testtrans)
1752 , testCase "TestUnsafeSend" (testUnsafeSend testtrans)
@@ -1631,17 +1799,3 @@ tests testtrans = return [
1631 , testCase "MonitorUnreachable" (testMonitorUnreachable testtrans True False)
1799 , testCase "MonitorUnreachable" (testMonitorUnreachable testtrans True False)
1635−syncBreakConnection :: (NT.EndPointAddress -> NT.EndPointAddress -> IO ()) -> LocalNode -> LocalNode -> IO ()
1636−syncBreakConnection breakConnection nid0 nid1 = do
1638− _ <- forkProcess nid1 $ getSelfPid >>= liftIO . putMVar m
1639− runProcess nid0 $ do
1640− them <- liftIO $ takeMVar m
1641− pinger <- spawnLocal $ forever $ send them ()
1642− _ <- monitorNode (localNodeId nid1)
1643− liftIO $ breakConnection (nodeAddress $ localNodeId nid0)
1644− (nodeAddress $ localNodeId nid1)
1645− NodeMonitorNotification _ _ _ <- expect
1646− kill pinger "finished"