@@ -25,18 +25,13 @@ import Control.Concurrent.MVar
2525 )
2626import Control.Monad (replicateM_, replicateM, forever, void, unless, join)
2727import Control.Exception (SomeException, throwIO, ErrorCall(..))
28−import Control.Monad.Catch (try, catch, finally, mask, onException)
29−import Control.Applicative ((<|>))
28+import qualified Control.Exception as Ex (catch)
29+import Control.Applicative ((<$>), (<*>), pure, (<|>))
3030import qualified Network.Transport as NT (closeEndPoint, EndPointAddress)
31−import Control.Distributed.Process hiding
32− ( try
33− , catch
34− , finally
35− , mask
36− , onException
37− )
31+import Control.Distributed.Process
3832import Control.Distributed.Process.Internal.Types
39− ( LocalNode(localEndPoint)
33+ ( NodeId(nodeAddress)
34+ , LocalNode(localEndPoint)
4035 , ProcessExitException(..)
4136 , nullProcessId
4237 , createUnencodedMessage
@@ -44,13 +39,13 @@ import Control.Distributed.Process.Internal.Types
4439import Control.Distributed.Process.Node
4540import Control.Distributed.Process.Debug
4641import Control.Distributed.Process.Management.Internal.Types
47−import Control.Distributed.Process.Tests.Internal.Utils (shouldBe, pause)
42+import Control.Distributed.Process.Tests.Internal.Utils (shouldBe)
4843import Control.Distributed.Process.Serializable (Serializable)
49−import Data.Maybe (isNothing, isJust)
50−import Test.HUnit (Assertion, assertBool, assertFailure)
44+
45+import Test.HUnit (Assertion, assertFailure, assertBool)
5146import Test.Framework (Test, testGroup)
5247import Test.Framework.Providers.HUnit (testCase)
53−import Control.Rematch hiding (match, isNothing, isJust)
48+import Control.Rematch hiding (match)
5449import Control.Rematch.Run (Match(..))
5550
5651newtype Ping = Ping ProcessId
@@ -73,7 +68,7 @@ expectThat a matcher = case res of
7368forkTry :: IO () -> IO ThreadId
7469forkTry p = do
7570 tid <- myThreadId
76− forkIO $ catch p (\e -> throwTo tid (e :: SomeException))
71+ forkIO $ Ex.catch p (\e -> throwTo tid (e :: SomeException))
7772
7873-- | The ping server from the paper
7974ping :: Process ()
@@ -83,46 +78,12 @@ ping = do
8378 send partner (Ping self)
8479 ping
8580
86−verifyClient :: String -> MVar Bool -> IO ()
87−verifyClient s b = takeMVar b >>= assertBool s
88−
89−expectPing :: MVar Bool -> Process ()
90−expectPing mv = expect >>= liftIO . putMVar mv . checkPing
91− where
92− checkPing (Ping _) = True
93−
9481-- | Quick and dirty synchronous version of whereisRemoteAsync
9582whereisRemote :: NodeId -> String -> Process (Maybe ProcessId)
9683whereisRemote nid string = do
9784 whereisRemoteAsync nid string
98− receiveWait [
99− match (\(WhereIsReply _ mPid) -> return mPid)
100− ]
101−
102−verifyWhereIsRemote :: NodeId -> String -> Process ProcessId
103−verifyWhereIsRemote n s = whereisRemote n s >>= maybe (die "remote name not found") return
104−
105−waitForExit :: ProcessId -> Process DiedReason
106−waitForExit pid = monitor pid >>= waitForDown
107−
108−waitForDown :: MonitorRef -> Process DiedReason
109−waitForDown ref =
110− receiveWait [ matchIf (\(ProcessMonitorNotification ref' _ _) -> ref == ref')
111− (\(ProcessMonitorNotification _ _ dr) -> return dr) ]
112−
113−syncBreakConnection :: (NT.EndPointAddress -> NT.EndPointAddress -> IO ()) -> LocalNode -> LocalNode -> IO ()
114−syncBreakConnection breakConnection nid0 nid1 = do
115− m <- newEmptyMVar
116− _ <- forkProcess nid1 $ getSelfPid >>= liftIO . putMVar m
117− runProcess nid0 $ do
118− them <- liftIO $ takeMVar m
119− pinger <- spawnLocal $ forever $ send them ()
120− _ <- monitorNode (localNodeId nid1)
121− liftIO $ breakConnection (nodeAddress $ localNodeId nid0)
122− (nodeAddress $ localNodeId nid1)
123− NodeMonitorNotification _ _ _ <- expect
124− kill pinger "finished"
125− return ()
85+ WhereIsReply _ mPid <- expect
86+ return mPid
12687
12788data Add = Add ProcessId Double Double deriving (Typeable)
12889data Divide = Divide ProcessId Double Double deriving (Typeable)
@@ -197,18 +158,12 @@ monitorTestProcess theirAddr mOrL un reason monitorSetup done =
197158 unmonitor ref
198159 liftIO $ putMVar done ()
199160 (False, ref) -> do
200− receiveWait [
201− match (\(ProcessMonitorNotification ref' pid reason') -> do
202− liftIO $ do
203− assertBool "Bad Monitor Signal"
204− (Just ref' == ref && pid == theirAddr &&
205− mOrL && reason == reason')
206− putMVar done ())
207− ]
161+ ProcessMonitorNotification ref' pid reason' <- expect
162+ True <- return $ Just ref' == ref && pid == theirAddr && mOrL && reason == reason'
163+ liftIO $ putMVar done ()
208164 )
209165 (\(ProcessLinkException pid reason') -> do
210− (liftIO $ assertBool "link exception unmatched" $
211− pid == theirAddr && not mOrL && not un && reason == reason')
166+ True <- return $ pid == theirAddr && not mOrL && not un && reason == reason'
212167 liftIO $ putMVar done ()
213168 )
214169
@@ -239,10 +194,8 @@ testPing TestTransport{..} = do
239194 pid <- getSelfPid
240195 replicateM_ numPings $ do
241196 send pingServer (Pong pid)
242− p <- expectTimeout 3000000
243− case p of
244− Just (Ping _) -> return ()
245− Nothing -> die "Failed to receive Ping"
197+ Ping _ <- expect
198+ return ()
246199
247200 putMVar clientDone ()
248201
@@ -329,7 +282,7 @@ testMonitorLocalDeadProcess TestTransport{..} mOrL un = do
329282 runProcess localNode $ do
330283 monitor theirAddr
331284 -- wait for the process to die
332− expect :: Process ProcessMonitorNotification
285+ ProcessMonitorNotification _ _ _ <- expect
333286 monitorTestProcess theirAddr mOrL un DiedUnknownId Nothing done
334287
335288 takeMVar done
@@ -403,17 +356,14 @@ testMath TestTransport{..} = do
403356 runProcess localNode $ do
404357 pid <- getSelfPid
405358 send mathServer (Add pid 1 2)
406− three <- expect :: Process Double
359+ 3 <- expect :: Process Double
407360 send mathServer (Divide pid 8 2)
408− four <- expect :: Process Double
361+ 4 <- expect :: Process Double
409362 send mathServer (Divide pid 8 0)
410− divByZ <- expect
411− liftIO $ putMVar clientDone (three, four, divByZ)
363+ DivByZero <- expect
364+ liftIO $ putMVar clientDone ()
412365
413− res <- takeMVar clientDone
414− case res of
415− (3, 4, DivByZero) -> return ()
416− _ -> error $ "Something went horribly wrong"
366+ takeMVar clientDone
417367
418368-- | Send first message (i.e. connect) to an already terminated process
419369-- (without monitoring); then send another message to a second process on
@@ -441,9 +391,11 @@ testSendToTerminated TestTransport{..} = do
441391 pid <- getSelfPid
442392 send server1 "Hi"
443393 send server2 (Pong pid)
444− expectPing clientDone
394+ Ping pid' <- expect
395+ True <- return $ pid' == server2
396+ liftIO $ putMVar clientDone ()
445397
446− verifyClient "Expected Ping from server" clientDone
398+ takeMVar clientDone
447399
448400-- | Test (non-zero) timeout
449401testTimeout :: TestTransport -> Assertion
@@ -452,10 +404,10 @@ testTimeout TestTransport{..} = do
452404 done <- newEmptyMVar
453405
454406 runProcess localNode $ do
455− res <- receiveTimeout 1000000 [match (\Add{} -> return ())]
456− liftIO $ putMVar done $ res == Nothing
407+ Nothing <- receiveTimeout 1000000 [match (\(Add _ _ _) -> return ())]
408+ liftIO $ putMVar done ()
457409
458− verifyClient "Expected receiveTimeout to timeout..." done
410+ takeMVar done
459411
460412-- | Test zero timeout
461413testTimeout0 :: TestTransport -> Assertion
@@ -483,9 +435,10 @@ testTimeout0 TestTransport{..} = do
483435 -- is not interested in, and then a single message that it wants
484436 replicateM_ 10000 $ send server "Irrelevant message"
485437 send server (Pong pid)
486− expectPing clientDone
438+ Ping _ <- expect
439+ liftIO $ putMVar clientDone ()
487440
488− verifyClient "Expected Ping from server" clientDone
441+ takeMVar clientDone
489442
490443-- | Test typed channels
491444testTypedChannels :: TestTransport -> Assertion
@@ -508,10 +461,10 @@ testTypedChannels TestTransport{..} = do
508461 runProcess localNode $ do
509462 (clientSendPort, rport) <- newChan
510463 sendChan serverSendPort (clientSendPort, 5)
511− ch <- receiveChan rport
512− liftIO $ putMVar clientDone $ ch == False
464+ False <- receiveChan rport
465+ liftIO $ putMVar clientDone ()
513466
514− verifyClient "Expected channel to send 'False'" clientDone
467+ takeMVar clientDone
515468
516469-- | Test merging receive ports
517470testMergeChannels :: TestTransport -> Assertion
@@ -534,8 +487,9 @@ testMergeChannels TestTransport{..} = do
534487 rs <- mapM charChannel "abc"
535488 m <- mergePorts biased rs
536489 xs <- replicateM 9 $ receiveChan m
537− liftIO $ putMVar done $ xs == expected
538− verifyClient "Expected single layer merge to match expected ordering" done
490+ True <- return $ xs == expected
491+ liftIO $ putMVar done ()
492+ takeMVar done
539493
540494 -- Two layers of merging
541495 testNested :: LocalNode -> Bool -> Bool -> String -> IO ()
@@ -546,8 +500,9 @@ testMergeChannels TestTransport{..} = do
546500 ms <- mapM (mergePorts biasedInner) rss
547501 m <- mergePorts biasedOuter ms
548502 xs <- replicateM (9 * 3) $ receiveChan m
549− liftIO $ putMVar done $ xs == expected
550− verifyClient "Expected nested channels to match expeted ordering" done
503+ True <- return $ xs == expected
504+ liftIO $ putMVar done ()
505+ takeMVar done
551506
552507 -- Test that if no messages are (immediately) available, the scheduler makes no difference
553508 testBlocked :: LocalNode -> Bool -> IO ()
@@ -556,45 +511,43 @@ testMergeChannels TestTransport{..} = do
556511 done <- newEmptyMVar
557512
558513 forkProcess localNode $ do
559− ss <- liftIO $ mapM readMVar vs
560− case ss of
561− [sa, sb, sc] ->
562− mapM_ ((>> pause 10000) . uncurry sendChan)
563− [ -- a, b, c
564− (sa, 'a')
565− , (sb, 'b')
566− , (sc, 'c')
567− -- a, c, b
568− , (sa, 'a')
569− , (sc, 'c')
570− , (sb, 'b')
571− -- b, a, c
572− , (sb, 'b')
573− , (sa, 'a')
574− , (sc, 'c')
575− -- b, c, a
576− , (sb, 'b')
577− , (sc, 'c')
578− , (sa, 'a')
579− -- c, a, b
580− , (sc, 'c')
581− , (sa, 'a')
582− , (sb, 'b')
583− -- c, b, a
584− , (sc, 'c')
585− , (sb, 'b')
586− , (sa, 'a')
587− ]
588− _ -> die "Something went horribly wrong"
514+ [sa, sb, sc] <- liftIO $ mapM readMVar vs
515+ mapM_ ((>> liftIO (threadDelay 10000)) . uncurry sendChan)
516+ [ -- a, b, c
517+ (sa, 'a')
518+ , (sb, 'b')
519+ , (sc, 'c')
520+ -- a, c, b
521+ , (sa, 'a')
522+ , (sc, 'c')
523+ , (sb, 'b')
524+ -- b, a, c
525+ , (sb, 'b')
526+ , (sa, 'a')
527+ , (sc, 'c')
528+ -- b, c, a
529+ , (sb, 'b')
530+ , (sc, 'c')
531+ , (sa, 'a')
532+ -- c, a, b
533+ , (sc, 'c')
534+ , (sa, 'a')
535+ , (sb, 'b')
536+ -- c, b, a
537+ , (sc, 'c')
538+ , (sb, 'b')
539+ , (sa, 'a')
540+ ]
589541
590542 forkProcess localNode $ do
591543 (ss, rs) <- unzip <$> replicateM 3 newChan
592544 liftIO $ mapM_ (uncurry putMVar) $ zip vs ss
593545 m <- mergePorts biased rs
594546 xs <- replicateM (6 * 3) $ receiveChan m
595− liftIO $ putMVar done $ xs == "abcacbbacbcacabcba"
547+ True <- return $ xs == "abcacbbacbcacabcba"
548+ liftIO $ putMVar done ()
596549
597− verifyClient "Expected merged ports to match expected ordering" done
550+ takeMVar done
598551
599552 mergePorts :: Serializable a => Bool -> [ReceivePort a] -> Process (ReceivePort a)
600553 mergePorts True = mergePortsBiased
@@ -612,9 +565,8 @@ testTerminate TestTransport{..} = do
612565 localNode <- newLocalNode testTransport initRemoteTable
613566 runProcess localNode $ do
614567 e <- try terminate :: Process (Either ProcessTerminationException ())
615− if either show show e == show ProcessTerminationException
616− then return ()
617− else die "Unexpected result from terminate"
568+ True <- return $ either show show e == show ProcessTerminationException
569+ return ()
618570
619571testMonitorNode :: TestTransport -> Assertion
620572testMonitorNode TestTransport{..} = do
@@ -625,12 +577,11 @@ testMonitorNode TestTransport{..} = do
625577
626578 runProcess node2 $ do
627579 ref <- monitorNode (localNodeId node1)
628− receiveWait [
629− match (\(NodeMonitorNotification ref' nid DiedDisconnect) ->
630− return $ ref == ref' && nid == localNodeId node1)
631− ] >>= liftIO . putMVar done
580+ NodeMonitorNotification ref' nid DiedDisconnect <- expect
581+ True <- return $ ref == ref' && nid == localNodeId node1
582+ liftIO $ putMVar done ()
632583
633− verifyClient "Expected NodeMonitorNotification with matching ref & nodeId" done
584+ takeMVar done
634585
635586testMonitorLiveNode :: TestTransport -> Assertion
636587testMonitorLiveNode TestTransport{..} = do
@@ -645,16 +596,15 @@ testMonitorLiveNode TestTransport{..} = do
645596 liftIO $ putMVar ready ()
646597 liftIO $ takeMVar readyr
647598 send p ()
648− receiveWait [
649− match (\(NodeMonitorNotification ref' nid _) ->
650− (return $ ref == ref' && nid == localNodeId node1))
651− ] >>= liftIO . putMVar done
599+ NodeMonitorNotification ref' nid _ <- expect
600+ True <- return $ ref == ref' && nid == localNodeId node1
601+ liftIO $ putMVar done ()
652602
653603 takeMVar ready
654604 closeLocalNode node1
655605 putMVar readyr ()
656606
657− verifyClient "Expected NodeMonitorNotification for LIVE node" done
607+ takeMVar done
658608
659609testMonitorChannel :: TestTransport -> Assertion
660610testMonitorChannel TestTransport{..} = do
@@ -664,20 +614,18 @@ testMonitorChannel TestTransport{..} = do
664614 pid <- forkProcess node1 $ do
665615 sport <- expect :: Process (SendPort ())
666616 ref <- monitorPort sport
667− receiveWait [
668− -- reason might be DiedUnknownId if the receive port is GCed before the
669− -- monitor is established (TODO: not sure that this is reasonable)
670− match (\(PortMonitorNotification ref' port' reason) ->
671− return $ ref' == ref && port' == sendPortId sport &&
672− (reason == DiedNormal || reason == DiedUnknownId))
673− ] >>= liftIO . putMVar gotNotification
617+ PortMonitorNotification ref' port' reason <- expect
618+ -- reason might be DiedUnknownId if the receive port is GCed before the
619+ -- monitor is established (TODO: not sure that this is reasonable)
620+ return $ ref' == ref && port' == sendPortId sport && (reason == DiedNormal || reason == DiedUnknownId)
621+ liftIO $ putMVar gotNotification ()
674622
675623 runProcess node2 $ do
676624 (sport, _) <- newChan :: Process (SendPort (), ReceivePort ())
677625 send pid sport
678626 liftIO $ threadDelay 100000
679627
680− verifyClient "Expected PortMonitorNotification" gotNotification
628+ takeMVar gotNotification
681629
682630testRegistry :: TestTransport -> Assertion
683631testRegistry TestTransport{..} = do
@@ -689,28 +637,20 @@ testRegistry TestTransport{..} = do
689637
690638 runProcess node $ do
691639 register "ping" pingServer
692− whereis "ping" >>= liftIO . assertBool "Unexpected ping" . (== Just pingServer)
640+ Just pid <- whereis "ping"
641+ True <- return $ pingServer == pid
693642 us <- getSelfPid
694643 nsend "ping" (Pong us)
695− receiveWait [
696− matchIf (\(Ping pid') -> pingServer == pid') (const $ return ())
697− ]
698− checkRegException "dead" Nothing deadProcess
699− checkRegException "ping" (Just pingServer) deadProcess
700− try (unregister "dead") >>= checkReg "dead" Nothing
644+ Ping pid' <- expect
645+ True <- return $ pingServer == pid'
646+ Left (ProcessRegistrationException "dead" Nothing) <- try $ register "dead" deadProcess
647+ Left (ProcessRegistrationException "ping" (Just x)) <- try $ register "ping" deadProcess
648+ True <- return $ x == pingServer
649+ Left (ProcessRegistrationException "dead" Nothing) <- try $ unregister "dead"
701650 liftIO $ putMVar done ()
702651
703652 takeMVar done
704653
705− where
706− checkRegException name pid dead =
707− try (register name dead) >>= checkReg name pid
708−
709− checkReg name pid res =
710− case res of
711− Left (ProcessRegistrationException name pid) -> return ()
712− _ -> die $ "Unexpected Registration" ++ show res
713−
714654testRegistryRemoteProcess :: TestTransport -> Assertion
715655testRegistryRemoteProcess TestTransport{..} = do
716656 node1 <- newLocalNode testTransport initRemoteTable
@@ -721,13 +661,13 @@ testRegistryRemoteProcess TestTransport{..} = do
721661
722662 runProcess node2 $ do
723663 register "ping" pingServer
724− whereis "ping" >>= liftIO . assertBool "Unexpected ping" . (== Just pingServer)
664+ Just pid <- whereis "ping"
665+ True <- return $ pingServer == pid
725666 us <- getSelfPid
726667 nsend "ping" (Pong us)
727− receiveWait [
728− matchIf (\(Ping pid') -> pingServer == pid')
729− (const $ liftIO $ putMVar done ())
730− ]
668+ Ping pid' <- expect
669+ True <- return $ pingServer == pid'
670+ liftIO $ putMVar done ()
731671
732672 takeMVar done
733673
@@ -735,6 +675,7 @@ testRemoteRegistry :: TestTransport -> Assertion
735675testRemoteRegistry TestTransport{..} = do
736676 node1 <- newLocalNode testTransport initRemoteTable
737677 node2 <- newLocalNode testTransport initRemoteTable
678+ done <- newEmptyMVar
738679
739680 pingServer <- forkProcess node1 ping
740681 deadProcess <- forkProcess node1 (return ())
@@ -747,34 +688,32 @@ testRemoteRegistry TestTransport{..} = do
747688 "ping" == label' && pid == pingServer)
748689 (\(RegisterReply _ _ _) -> return ()) ]
749690
750− pid <- verifyWhereIsRemote nid1 "ping"
751− liftIO $ assertBool "Expected pindServer to match pid" $ pingServer == pid
752−
691+ Just pid <- whereisRemote nid1 "ping"
692+ True <- return $ pingServer == pid
753693 us <- getSelfPid
754694 nsendRemote nid1 "ping" (Pong us)
755− receiveWait [
756− match (\(Ping pid') -> return $ pingServer == pid')
757− ] >>= liftIO . assertBool "Expected Ping with ping server's ProcessId"
695+ Ping pid' <- expect
696+ True <- return $ pingServer == pid'
758697
759698 -- test that if process was not registered Nothing is returned
760699 -- in owner field.
761700 registerRemoteAsync nid1 "dead" deadProcess
762− receiveWait [ matchIf (\(RegisterReply label' f mPid) -> "dead" == label')
763− (\(RegisterReply _ f mPid) -> return (not f && isNothing mPid))
764− ] >>= liftIO . assertBool "Expected False Nothing in RegisterReply"
765−
701+ receiveWait [
702+ matchIf (\(RegisterReply label' False Nothing) -> "dead" == label')
703+ (\(RegisterReply _ _ _) -> return ()) ]
766704 registerRemoteAsync nid1 "ping" deadProcess
767705 receiveWait [
768− matchIf (\(RegisterReply label' False mPid) ->
769− "ping" == label' && isJust mPid)
770− (\(RegisterReply _ f (Just pid'')) -> return (not f && pid'' == pingServer))
771− ] >>= liftIO . assertBool "Expected False and (Just alreadyRegisteredPid) in RegisterReply"
772−
706+ matchIf (\(RegisterReply label' False (Just pid)) ->
707+ "ping" == label' && pid == pingServer)
708+ (\(RegisterReply _ _ _) -> return ()) ]
773709 unregisterRemoteAsync nid1 "dead"
774710 receiveWait [
775− matchIf (\(RegisterReply label' _ _) -> "dead" == label')
776− (\(RegisterReply _ f mPid) -> return (not f && isNothing mPid))
777− ] >>= liftIO . assertBool "Expected False and Nothing in RegisterReply"
711+ matchIf (\(RegisterReply label' False Nothing) ->
712+ "dead" == label' && pid == pingServer)
713+ (\(RegisterReply _ _ _) -> return ()) ]
714+ liftIO $ putMVar done ()
715+
716+ takeMVar done
778717
779718testRemoteRegistryRemoteProcess :: TestTransport -> Assertion
780719testRemoteRegistryRemoteProcess TestTransport{..} = do
@@ -790,15 +729,15 @@ testRemoteRegistryRemoteProcess TestTransport{..} = do
790729 receiveWait [
791730 matchIf (\(RegisterReply label' _ _) -> "ping" == label')
792731 (\(RegisterReply _ _ _) -> return ()) ]
793− pid <- verifyWhereIsRemote nid1 "ping"
794− liftIO $ assertBool "Expected pingServer to match remote name" $ pingServer == pid
732+ Just pid <- whereisRemote nid1 "ping"
733+ True <- return $ pingServer == pid
795734 us <- getSelfPid
796735 nsendRemote nid1 "ping" (Pong us)
797− receiveWait [
798− match (\(Ping pid') -> return $ pingServer == pid')
799− ] >>= liftIO . putMVar done
736+ Ping pid' <- expect
737+ True <- return $ pingServer == pid'
738+ liftIO $ putMVar done ()
800739
801− verifyClient "Expected Ping with ping server's ProcessId" done
740+ takeMVar done
802741
803742testSpawnLocal :: TestTransport -> Assertion
804743testSpawnLocal TestTransport{..} = do
@@ -812,14 +751,15 @@ testSpawnLocal TestTransport{..} = do
812751 sport <- expect
813752 sendChan sport (1234 :: Int)
814753
815− sport <- spawnChannelLocal $
816− \rport -> (receiveChan rport :: Process Int) >>= send us
754+ sport <- spawnChannelLocal $ \rport -> do
755+ (1234 :: Int) <- receiveChan rport
756+ send us ()
817757
818758 send pid sport
819− expect >>= liftIO . putMVar done
759+ () <- expect
760+ liftIO $ putMVar done ()
820761
821− res <- takeMVar done
822− assertBool "Expected 1234 :: Int" $ res == (1234 :: Int)
762+ takeMVar done
823763
824764testSpawnAsyncStrictness :: TestTransport -> Assertion
825765testSpawnAsyncStrictness TestTransport{..} = do
@@ -848,9 +788,8 @@ testReconnect TestTransport{..} = do
848788 liftIO $ putMVar processA us
849789 msg1 <- expect
850790 msg2 <- expect
851− liftIO $ do
852− assertBool "messages did not match" $ msg1 == "message 1" && msg2 == "message 3"
853− putMVar sendTestOk ()
791+ True <- return $ msg1 == "message 1" && msg2 == "message 3"
792+ liftIO $ putMVar sendTestOk ()
854793
855794 forkProcess node2 $ do
856795 {-
@@ -883,7 +822,7 @@ testReconnect TestTransport{..} = do
883822 matchIf (\(RegisterReply label' _ _) -> "a" == label')
884823 (\(RegisterReply _ _ _) -> return ()) ]
885824
886− _ <- whereisRemote nid1 "a"
825+ Just _ <- whereisRemote nid1 "a"
887826
888827
889828 -- Simulate network failure
@@ -902,10 +841,9 @@ testReconnect TestTransport{..} = do
902841 (\(RegisterReply _ _ _) -> return ()) ]
903842
904843 -- Check
905− mPid <- whereisRemote nid1 "a" -- this will fail because the name is removed when the node is disconnected
906− liftIO $ assertBool "Expected remote name to be lost" $ mPid == Nothing
907− verifyWhereIsRemote nid1 "b" -- this will suceed because the value is set after thereconnect
908− verifyWhereIsRemote nid1 "c"
844+ Nothing <- whereisRemote nid1 "a" -- this will fail because the name is removed when the node is disconnected
845+ Just _ <- whereisRemote nid1 "b" -- this will suceed because the value is set after thereconnect
846+ Just _ <- whereisRemote nid1 "c"
909847
910848 liftIO $ putMVar registerTestOk ()
911849
@@ -946,19 +884,19 @@ testUSend usendPrim TestTransport{..} numMessages = do
946884 isSorted _ = True
947885 -- The list can't be null since there are no failures after sending
948886 -- the last message.
949− liftIO $ putMVar usendTestOk $ isSorted msgs && not (null msgs)
887+ True <- return $ isSorted msgs && not (null msgs)
888+ liftIO $ putMVar usendTestOk ()
950889
951890 forkProcess node2 $ do
952891 them <- liftIO $ readMVar processA
953892 getSelfPid >>= send them
954− expect :: Process ()
893+ () <- expect
955894 forM_ [1..numMessages] $ \i -> do
956895 liftIO $ testBreakConnection (nodeAddress nid1) (nodeAddress nid2)
957896 usendPrim them i
958897 liftIO (threadDelay 30000)
959898
960− res <- takeMVar usendTestOk
961− assertBool "Unexpected failure after sending last msg" res
899+ takeMVar usendTestOk
962900
963901-- | Test 'matchAny'. This repeats the 'testMath' but with a proxy server
964902-- in between
@@ -984,17 +922,14 @@ testMatchAny TestTransport{..} = do
984922 runProcess localNode $ do
985923 pid <- getSelfPid
986924 send mathServer (Add pid 1 2)
987− three <- expect :: Process Double
925+ 3 <- expect :: Process Double
988926 send mathServer (Divide pid 8 2)
989− four <- expect :: Process Double
927+ 4 <- expect :: Process Double
990928 send mathServer (Divide pid 8 0)
991− divByZ <- expect
992− liftIO $ putMVar clientDone (three, four, divByZ)
929+ DivByZero <- expect
930+ liftIO $ putMVar clientDone ()
993931
994− res <- takeMVar clientDone
995− case res of
996− (3, 4, DivByZero) -> return ()
997− _ -> error "Unexpected result"
932+ takeMVar clientDone
998933
999934-- | Test 'matchAny'. This repeats the 'testMath' but with a proxy server
1000935-- in between, however we block 'Divide' requests ....
@@ -1021,13 +956,12 @@ testMatchAnyHandle TestTransport{..} = do
1021956 runProcess localNode $ do
1022957 pid <- getSelfPid
1023958 send mathServer (Add pid 1 2)
1024− three <- expect :: Process Double
959+ 3 <- expect :: Process Double
1025960 send mathServer (Divide pid 8 2)
1026− res <- (expectTimeout 100000) :: Process (Maybe Double)
1027− liftIO $ putMVar clientDone $ three == 3 && res == Nothing
1028−
1029− verifyClient "Expected Nothing (i.e. timeout)" clientDone
961+ Nothing <- (expectTimeout 100000) :: Process (Maybe Double)
962+ liftIO $ putMVar clientDone ()
1030963
964+ takeMVar clientDone
1031965 where maybeForward :: ProcessId -> Message -> Process (Maybe ())
1032966 maybeForward s msg =
1033967 handleMessage msg (\m@(Add _ _ _) -> send s m)
@@ -1055,10 +989,8 @@ testMatchAnyNoHandle TestTransport{..} = do
1055989 Just _ -> die "NONSENSE")
1056990 ]
1057991 -- we *must* have removed the message from our mailbox though!!!
1058− res <- receiveTimeout 100000 [ match (\(Add _ _ _) -> return ()) ]
1059− liftIO $ do
1060− assertBool "Expected timeout!" $ res == Nothing
1061− putMVar serverDone ()
992+ Nothing <- receiveTimeout 100000 [ match (\(Add _ _ _) -> return ()) ]
993+ liftIO $ putMVar serverDone ()
1062994 putMVar addr server
1063995
1064996 -- Client
@@ -1101,21 +1033,14 @@ testMatchAnyIf TestTransport{..} = do
11011033 runProcess localNode $ do
11021034 pid <- getSelfPid
11031035 send server (pid, "foo")
1104− foo <- expect
1105− -- provoking what would be the wrong ordering is informative here...
1106−
1107− send server (pid, "bar")
1108− bar <- (expectTimeout 100000) :: Process (Maybe String) -- was Double o_O !?
1109−
1036+ "foo" <- expect
11101037 send server (pid, "baz")
1111− baz <- expect
1112−
1113− liftIO $ putMVar clientDone (foo, bar, baz)
1114−
1115− res <- takeMVar clientDone
1116− let res' = res == ("foo", Nothing, "baz")
1117− assertBool "Expected timeout due to type mismatch" res'
1038+ "baz" <- expect
1039+ send server (pid, "bar")
1040+ Nothing <- (expectTimeout 100000) :: Process (Maybe Double)
1041+ liftIO $ putMVar clientDone ()
11181042
1043+ takeMVar clientDone
11191044 where tryHandleMessage :: Message -> Process (Maybe ())
11201045 tryHandleMessage msg =
11211046 handleMessage msg (\(pid :: ProcessId, (m :: String))
@@ -1148,13 +1073,12 @@ testMatchMessageWithUnwrap TestTransport{..} = do
11481073 runProcess localNode $ do
11491074 pid <- getSelfPid
11501075 send server (pid, wrapMessage ("foo" :: String))
1151− foo <- expect
1076+ "foo" <- expect
11521077 send server (pid, wrapMessage ("baz" :: String))
1153− baz <- expect
1154− liftIO $ putMVar clientDone (foo, baz)
1078+ "baz" <- expect
1079+ liftIO $ putMVar clientDone ()
11551080
1156− res <- takeMVar clientDone
1157− assertBool "Unexpected unwrapped results" $ res == ("foo", "baz")
1081+ takeMVar clientDone
11581082
11591083-- Test 'receiveChanTimeout'
11601084testReceiveChanTimeout :: TestTransport -> Assertion
@@ -1172,19 +1096,18 @@ testReceiveChanTimeout TestTransport{..} = do
11721096
11731097 -- Wait for a message with a delay. No message arrives, we should get
11741098 -- Nothing after the delay.
1175− receiveChanTimeout 100000 rp >>= maybe (return ()) (const $ die "Expected Timeout")
1099+ Nothing <- receiveChanTimeout 100000 rp
11761100
11771101 -- Let the sender know that it can send a message.
11781102 liftIO $ putMVar mvSender ()
11791103
11801104 -- Wait for a message with a delay again. Now a message arrives after
11811105 -- 0.1 seconds
1182− res <- receiveChanTimeout 20000000 rp >>= maybe (die "Timeout") return
1183− liftIO $ assertBool "Expected result to be 'True'" res
1106+ Just True <- receiveChanTimeout 20000000 rp
11841107
11851108 -- Wait for a message with zero timeout: non-blocking check. No message is
11861109 -- available, we get Nothing
1187− receiveChanTimeout 0 rp >>= maybe (return ()) (const $ die "Expected Timeout")
1110+ Nothing <- receiveChanTimeout 0 rp
11881111
11891112 -- Let the sender know that it can send a message.
11901113 liftIO $ putMVar mvSender ()
@@ -1194,7 +1117,7 @@ testReceiveChanTimeout TestTransport{..} = do
11941117 liftIO $ threadDelay 100000
11951118 mb <- receiveChanTimeout 0 rp
11961119 case mb of
1197− Just b -> do liftIO $ assertBool "Unexpected Message" $ not b
1120+ Just b -> do False <- return b; return ()
11981121 _ -> loop
11991122
12001123 liftIO $ putMVar done ()
@@ -1231,8 +1154,8 @@ testReceiveChanFeatures TestTransport{..} = do
12311154
12321155 rp1 <- mergePortsBiased [even <$> rpInt, rpBool]
12331156
1234− receiveChan rp1 >>= liftIO . assertBool "Expected True"
1235− receiveChan rp1 >>= liftIO . assertBool "Expected False" . not
1157+ True <- receiveChan rp1
1158+ False <- receiveChan rp1
12361159
12371160 -- Test Applicative instance
12381161
@@ -1241,7 +1164,7 @@ testReceiveChanFeatures TestTransport{..} = do
12411164
12421165 let rp2 = pure (+) <*> rpInt <*> rpInt
12431166
1244− receiveChan rp2 >>= liftIO . assertBool "Expected 7" . (== 7)
1167+ 7 <- receiveChan rp2
12451168
12461169 -- Test Alternative instance
12471170
@@ -1250,8 +1173,8 @@ testReceiveChanFeatures TestTransport{..} = do
12501173
12511174 let rp3 = (even <$> rpInt) <|> rpBool
12521175
1253− receiveChan rp3 >>= liftIO . assertBool "Expected False" . not
1254− receiveChan rp3 >>= liftIO . assertBool "Expected True"
1176+ False <- receiveChan rp3
1177+ True <- receiveChan rp3
12551178
12561179 -- Test Monad instance
12571180
@@ -1265,86 +1188,17 @@ testReceiveChanFeatures TestTransport{..} = do
12651188 then rpInt
12661189 else return 7
12671190
1268− receiveChan rp4 >>= liftIO . assertBool "Expected 5" . (== 5)
1269− receiveChan rp4 >>= liftIO . assertBool "Expected 7" . (== 7)
1191+ 5 <- receiveChan rp4
1192+ 7 <- receiveChan rp4
12701193
12711194 liftIO $ putMVar done ()
12721195
12731196 takeMVar done
12741197
1275−testChanLifecycle :: TestTransport -> Assertion
1276−testChanLifecycle TestTransport{..} = let delay = 3000000 in do
1277− result <- newEmptyMVar
1278− tchMV <- newEmptyMVar
1279− localNode <- newLocalNode testTransport initRemoteTable
1280− runProcess localNode $ do
1281−
1282− pid <- spawnLocal $ do tCh <- newChan :: Process (SendPort (), ReceivePort ())
1283− liftIO $ putMVar tchMV tCh
1284− expect :: Process ()
1285− let (sp, _) = tCh
1286− sendChan sp ()
1287− expect :: Process ()
1288−
1289− mRefPid <- monitor pid
1290−
1291− cPid <- spawnLocal $ do
1292− (sp', rp) <- liftIO $ takeMVar tchMV
1293− -- say "picked up our test channel"
1294− send pid ()
1295− -- say "told pid to continue"
1296− res <- receiveChanTimeout delay rp
1297− case res of
1298− Nothing -> say "initial chan () missing!" >> (liftIO $ putMVar result False)
1299− Just () -> do mr <- monitor pid
1300− pause 10000
1301− -- say "sending pid a second () will cause it to exit"
1302− send pid ()
1303−
1304− -- say "make sure we see a DOWN notification for pid having stopped"
1305− receiveWait [ match (\(_ :: ProcessMonitorNotification) -> return ()) ]
1306−
1307− -- now that pid has died, the send port should be useless...
1308− liftIO $ putMVar tchMV (sp', rp)
1309−
1310− -- let's verify that we do not see the message from our
1311− -- parent process on the channel, once pid has died...
1312− recv <- receiveChanTimeout delay rp
1313− -- say $ "finished waiting for second (), writing result" ++ (show recv)
1314− liftIO $ putMVar result $ isNothing recv
1315−
1316− mRefCPid <- monitor cPid
1317−
1318− receiveWait
1319− [ matchIf (\(ProcessMonitorNotification r _ _) -> r == mRefPid)
1320− (\_ -> return ())
1321− ]
1322−
1323− -- say "seen first pid die..."
1324−
1325− (sendPort, _) <- liftIO $ takeMVar tchMV
1326− sendChan sendPort ()
1327− -- say "sent () after owning pid died"
1328−
1329− -- let cPid know we've written to the channel...
1330− send cPid ()
1331−
1332− receiveWait
1333− [ matchIf (\(ProcessMonitorNotification r _ _) -> r == mRefCPid)
1334− (\_ -> return ())
1335− ]
1336−
1337− -- say "seen both pids die now..."
1338−
1339− -- and wait on the result back in IO land...
1340− testRes <- takeMVar result
1341− -- runProcess localNode $ say "got result..."
1342− assertBool "Expected sending on the channel to fail, but received data!" testRes
1343−
1344−
13451198testKillLocal :: TestTransport -> Assertion
13461199testKillLocal TestTransport{..} = do
13471200 localNode <- newLocalNode testTransport initRemoteTable
1201+ done <- newEmptyMVar
13481202
13491203 pid <- forkProcess localNode $ do
13501204 liftIO $ threadDelay 1000000
@@ -1353,18 +1207,17 @@ testKillLocal TestTransport{..} = do
13531207 ref <- monitor pid
13541208 us <- getSelfPid
13551209 kill pid "TestKill"
1356− mn <- expect
1357− case mn of
1358− ProcessMonitorNotification ref' pid' (DiedException ex) ->
1359− case ref == ref' && pid == pid' && ex == "killed-by=" ++ show us ++ ",reason=TestKill" of
1360− True -> return ()
1361− False -> die "Invalid ProcessMonitorNotification received"
1362− _ -> die "Something went horribly wrong"
1210+ ProcessMonitorNotification ref' pid' (DiedException ex) <- expect
1211+ True <- return $ ref == ref' && pid == pid' && ex == "killed-by=" ++ show us ++ ",reason=TestKill"
1212+ liftIO $ putMVar done ()
1213+
1214+ takeMVar done
13631215
13641216testKillRemote :: TestTransport -> Assertion
13651217testKillRemote TestTransport{..} = do
13661218 node1 <- newLocalNode testTransport initRemoteTable
13671219 node2 <- newLocalNode testTransport initRemoteTable
1220+ done <- newEmptyMVar
13681221
13691222 pid <- forkProcess node1 $ do
13701223 liftIO $ threadDelay 1000000
@@ -1373,17 +1226,11 @@ testKillRemote TestTransport{..} = do
13731226 ref <- monitor pid
13741227 us <- getSelfPid
13751228 kill pid "TestKill"
1376− mn <- expect
1377− case mn of
1378− ProcessMonitorNotification ref' pid' (DiedException reason) ->
1379− case (ref == ref', pid == pid', reason == "killed-by=" ++ show us ++ ",reason=TestKill") of
1380− (True, True, True) -> return ()
1381− (a, b, c) -> do
1382− let a' = if a then "" else "Invalid ref"
1383− let b' = if b then "" else "Invalid pid"
1384− let c' = if c then "" else "Invalid message"
1385− die $ unwords [a', b', c']
1386− _ -> die "Received unexpected message"
1229+ ProcessMonitorNotification ref' pid' (DiedException reason) <- expect
1230+ True <- return $ ref == ref' && pid == pid' && reason == "killed-by=" ++ show us ++ ",reason=TestKill"
1231+ liftIO $ putMVar done ()
1232+
1233+ takeMVar done
13871234
13881235testCatchesExit :: TestTransport -> Assertion
13891236testCatchesExit TestTransport{..} = do
@@ -1409,10 +1256,7 @@ testHandleMessageIf TestTransport{..} = do
14091256 self <- getSelfPid
14101257 send self (5 :: Integer, 10 :: Integer)
14111258 msg <- receiveWait [ matchMessage return ]
1412− handleMessageIf msg
1413− (\() -> True)
1414− (\() -> die "whoops") >>= maybe (return ())
1415− (const $ die "Expected Mismatch")
1259+ Nothing <- handleMessageIf msg (\() -> True) (\() -> die $ "whoops")
14161260 handleMessageIf msg (\(x :: Integer, y :: Integer) -> x == 5 && y == 10)
14171261 (\input -> liftIO $ putMVar done input)
14181262 return ()
@@ -1457,11 +1301,8 @@ testDie TestTransport{..} = do
14571301 (die ("foobar", 123 :: Int))
14581302 `catchExit` \_from reason -> do
14591303 -- TODO: should verify that 'from' has the right value
1460− let res = reason == ("foobar", 123 :: Int)
1304+ True <- return $ reason == ("foobar", 123 :: Int)
14611305 liftIO $ putMVar done ()
1462− if res
1463− then return ()
1464− else die "Something went horribly wrong"
14651306
14661307 takeMVar done
14671308
@@ -1475,11 +1316,8 @@ testPrettyExit TestTransport{..} = do
14751316 `catch` \ex@(ProcessExitException from _) ->
14761317 let expected = "exit-from=" ++ (show from)
14771318 in do
1478− let res = (show ex) == expected
1319+ True <- return $ (show ex) == expected
14791320 liftIO $ putMVar done ()
1480− if res
1481− then return ()
1482− else die "Something went horribly wrong"
14831321
14841322 takeMVar done
14851323
@@ -1495,26 +1333,17 @@ testExitLocal TestTransport{..} = do
14951333 pid <- forkProcess localNode $ do
14961334 (liftIO (putMVar handlerSetUp ()) >> expect) `catchExit` \_from reason -> do
14971335 -- TODO: should verify that 'from' has the right value
1498− res <- return $ reason == "TestExit"
1336+ True <- return $ reason == "TestExit"
14991337 liftIO $ putMVar supervisedDone ()
1500− if res
1501− then return ()
1502− else die "Something went horribly wrong"
15031338
15041339 runProcess localNode $ do
15051340 liftIO $ takeMVar handlerSetUp
15061341 ref <- monitor pid
15071342 exit pid "TestExit"
15081343 -- This time the client catches the exception, so it dies normally
1509− mn <- expect
1510− case mn of
1511− ProcessMonitorNotification ref' pid' DiedNormal -> do
1512− let res = ref == ref' && pid == pid'
1513− liftIO $ putMVar supervisorDone ()
1514− if res
1515− then return ()
1516− else die "Something went horribly wrong"
1517− _ -> die "Something went horribly wrong"
1344+ ProcessMonitorNotification ref' pid' DiedNormal <- expect
1345+ True <- return $ ref == ref' && pid == pid'
1346+ liftIO $ putMVar supervisorDone ()
15181347
15191348 takeMVar supervisedDone
15201349 takeMVar supervisorDone
@@ -1530,97 +1359,128 @@ testExitRemote TestTransport{..} = do
15301359 (receiveWait [] :: Process ()) -- block forever
15311360 `catchExit` \_from reason -> do
15321361 -- TODO: should verify that 'from' has the right value
1533− res <- return $ reason == "TestExit"
1362+ True <- return $ reason == "TestExit"
15341363 liftIO $ putMVar supervisedDone ()
1535− if res
1536− then return ()
1537− else die "Something went horribly wrong"
15381364
15391365 runProcess node2 $ do
15401366 ref <- monitor pid
15411367 exit pid "TestExit"
1542− mn <- expect
1543− case mn of
1544− ProcessMonitorNotification ref' pid' DiedNormal -> do
1545− res' <- return $ ref == ref' && pid == pid'
1546− liftIO $ putMVar supervisorDone ()
1547− if res'
1548− then return ()
1549− else die "Something went horribly wrong"
1550− _ -> die "Something went horribly wrong"
1368+ ProcessMonitorNotification ref' pid' DiedNormal <- expect
1369+ True <- return $ ref == ref' && pid == pid'
1370+ liftIO $ putMVar supervisorDone ()
15511371
15521372 takeMVar supervisedDone
15531373 takeMVar supervisorDone
15541374
15551375testRegistryMonitoring :: TestTransport -> Assertion
15561376testRegistryMonitoring TestTransport{..} = do
1557− node1 <- newLocalNode testTransport initRemoteTable
1558− node2 <- newLocalNode testTransport initRemoteTable
1559−
1560− let nid = localNodeId node2
1561− pid <- forkProcess node1 $ do
1562− self <- getSelfPid
1563− runUntilRegistered nid self
1564− say $ (show self) ++ " registered as " ++ regName
1565− expect :: Process ()
1566− say $ (show self) ++ " exiting normally"
1377+ localNode <- newLocalNode testTransport initRemoteTable
1378+ remoteNode <- newLocalNode testTransport initRemoteTable
1379+ return ()
15671380
1568− runProcess node2 $ do
1569− register regName pid
1570− say $ regName ++ " registered to " ++ show pid
1571− res <- whereis regName
1572− send pid ()
1573− say $ " sent finish signal to " ++ show pid
1574− us <- getSelfPid
1575− liftIO $ assertBool "expected (Just pid)" $ res == (Just pid)
1576−
1577−
1578− -- This delay isn't essential!
1579− -- The test case passes perfectly fine without it (feel free to comment out
1580− -- and see), however waiting a few seconds here, makes it much more likely
1581− -- that in delayUntilMaybeUnregistered we will hit the match case right
1582− -- away, and thus not be subjected to a 20 second delay. The value of 4
1583− -- seconds appears to work optimally on osx and across several linux distros
1584− -- running in virtual machines (which is essentially what we do in CI)
1585− void $ receiveTimeout 4000000 [ matchAny return ]
1586−
1587− -- This delay doesn't serve much purpose in the happy path, however if some
1588− -- future patch breaks the cooperative behaviour of node controllers viz
1589− -- remote process registration and notification taking place via ncEffectDied,
1590− -- there would be the possibility of a race in the test case should we attempt
1591− -- to evaluate `whereis regName` on node2 right away. In case the name is still
1592− -- erroneously registered, observing the 20 second delay (or lack of), could at
1593− -- least give a hint that something is wrong, and we give up our time slice
1594− -- so that there's a higher change the registrations have been cleaned up
1595− -- in either case.
1596− runProcess node2 $ delayUntilMaybeUnregistered nid pid
1597−
1598− regHere <- newEmptyMVar
1599− runProcess node2 $ whereis regName >>= liftIO . putMVar regHere
1600− res <- takeMVar regHere
1601− case res of
1602− Nothing -> return ()
1603− Just pid -> assertBool ("expected Nothing, but got " ++ show pid) False
1381+ -- Local process. Test if local process will be removed from
1382+ -- registry when it dies.
1383+ box <- newEmptyMVar
1384+ runProcess localNode $ do
1385+ pid <- spawnLocal $ do
1386+ expect
1387+ register "test" pid
1388+ tpid <- whereis "test"
1389+ if tpid == Just pid
1390+ then do _ <- monitor pid
1391+ send pid ()
1392+ ProcessMonitorNotification{} <- expect
1393+ tpid1 <- whereis "test"
1394+ liftIO $ putMVar box (Nothing == tpid1)
1395+ else liftIO $ putMVar box False
1396+
1397+ takeMVar box >>= assertBool "expected local process to not be registered"
1398+ return ()
1399+
1400+ -- Remote process. Test if remote process entry is removed
1401+ -- from registry when process dies.
1402+ remote1 <- testRemote remoteNode
1403+ runProcess localNode $
1404+ let waitpoll = do
1405+ w <- whereis "test" :: Process (Maybe ProcessId)
1406+ forM_ w (const waitpoll)
1407+ in do register "test" remote1
1408+ -- [race-condition] invalid test if we force exit before waitpoll runs
1409+ registered <- whereis "test"
1410+ registered `shouldBe` (equalTo (Just remote1))
1411+ send remote1 ()
1412+ waitpoll
1413+ return ()
1414+ return ()
1415+
1416+ -- Many labels. Test if all labels associated with process
1417+ -- are removed from registry when it dies.
1418+ remote2 <- testRemote remoteNode
1419+ runProcess localNode $
1420+ let waitpoll = do
1421+ w1 <- whereis "test-3" :: Process (Maybe ProcessId)
1422+ w2 <- whereis "test-4" :: Process (Maybe ProcessId)
1423+ forM_ (w1 <|> w2) (const waitpoll)
1424+ in do register "test-3" remote2
1425+ register "test-4" remote2
1426+ send remote2 ()
1427+ waitpoll
1428+ return ()
1429+
1430+{- XXX: waiting including patch for nsend for remote process
1431+ remote3 <- testRemote remoteNode
1432+ remote4 <- testRemote remoteNode
1433+ -- test many labels
1434+ runProcess localNode $ do
1435+ register "test-3" remote3
1436+ reregister "test-3" remote4
1437+ send remote3 ()
1438+ liftIO $ threadDelay 50000 -- XXX: racy
1439+ monitor remote4
1440+ nsend "test-3" ()
1441+ ProcessMonitorNotification{} <- expect
1442+ return ()
1443+-}
1444+
1445+ -- Test registerRemoteAsync properties. Add a local process to
1446+ -- remote registry and checks that it is removed
1447+ -- when the process dies.
1448+ remote5 <- testRemote remoteNode
1449+ runProcess localNode $ do
1450+ registerRemoteAsync (localNodeId remoteNode) "test" remote5
1451+ receiveWait [
1452+ match (\(RegisterReply _ True _) -> return ())
1453+ ] >>= send remote5
1454+ let waitpoll = do
1455+ whereisRemoteAsync (localNodeId remoteNode) "test"
1456+ receiveWait [
1457+ match (\(WhereIsReply _ mr) -> forM_ mr (const waitpoll))
1458+ ]
1459+ waitpoll
16041460
1605− where
1606− runUntilRegistered nid us = do
1607− whereisRemoteAsync nid regName
1608− receiveWait [
1609− matchIf (\(WhereIsReply n (Just p)) -> n == regName && p == us)
1610− (const $ return ())
1611− ]
1612−
1613− delayUntilMaybeUnregistered nid p = do
1614− whereisRemoteAsync nid regName
1615− res <- receiveTimeout 20000000 {- 20 sec delay -} [
1616− matchIf (\(WhereIsReply n p) -> n == regName && isNothing p)
1617− (const $ return ())
1618− ]
1619− case res of
1620− Just () -> return ()
1621− Nothing -> delayUntilMaybeUnregistered nid p
1622−
1623− regName = "testRegisterRemote"
1461+ -- Add remote process to remote registry and checks if
1462+ -- entry is removed then process is dead.
1463+ remote6 <- testRemote localNode
1464+ runProcess localNode $ do
1465+ registerRemoteAsync (localNodeId remoteNode) "test" remote6
1466+ receiveWait [
1467+ match (\(RegisterReply _ True _) -> return ())
1468+ ] >>= send remote6
1469+ let waitpoll = do
1470+ whereisRemoteAsync (localNodeId remoteNode) "test"
1471+ receiveWait [
1472+ match (\(WhereIsReply _ mr) -> forM_ mr (const waitpoll))
1473+ ]
1474+ waitpoll
1475+ where
1476+ testRemote node = do
1477+ -- test many labels
1478+ pidBox <- newEmptyMVar
1479+ forkProcess node $ do
1480+ us <- getSelfPid
1481+ liftIO $ putMVar pidBox us
1482+ expect :: Process ()
1483+ takeMVar pidBox
16241484
16251485testUnsafeSend :: TestTransport -> Assertion
16261486testUnsafeSend TestTransport{..} = do
@@ -1637,7 +1497,8 @@ testUnsafeSend TestTransport{..} = do
16371497 void $ forkProcess localNode $ do
16381498 serverPid <- liftIO $ takeMVar serverAddr
16391499 getSelfPid >>= unsafeSend serverPid
1640− expect >>= liftIO . putMVar clientDone
1500+ () <- expect
1501+ liftIO $ putMVar clientDone ()
16411502
16421503 takeMVar clientDone
16431504
@@ -1656,7 +1517,8 @@ testUnsafeUSend TestTransport{..} = do
16561517 void $ forkProcess localNode $ do
16571518 serverPid <- liftIO $ takeMVar serverAddr
16581519 getSelfPid >>= unsafeUSend serverPid
1659− expect >>= liftIO . putMVar clientDone
1520+ () <- expect
1521+ liftIO $ putMVar clientDone ()
16601522
16611523 takeMVar clientDone
16621524
@@ -1667,7 +1529,8 @@ testUnsafeNSend TestTransport{..} = do
16671529 localNode <- newLocalNode testTransport initRemoteTable
16681530
16691531 pid <- forkProcess localNode $ do
1670− expect >>= liftIO . putMVar clientDone
1532+ () <- expect
1533+ liftIO $ putMVar clientDone ()
16711534
16721535 void $ runProcess localNode $ do
16731536 register "foobar" pid
@@ -1685,7 +1548,8 @@ testUnsafeNSendRemote TestTransport{..} = do
16851548 _ <- forkProcess localNode1 $ do
16861549 getSelfPid >>= register "foobar"
16871550 liftIO $ putMVar clientDone ()
1688− expect >>= liftIO . putMVar clientDone
1551+ () <- expect
1552+ liftIO $ putMVar clientDone ()
16891553
16901554 takeMVar clientDone
16911555 void $ runProcess localNode2 $ do
@@ -1709,7 +1573,7 @@ testUnsafeSendChan TestTransport{..} = do
17091573 serverPid <- liftIO $ takeMVar serverAddr
17101574 (sp, rp) <- newChan
17111575 unsafeSend serverPid sp
1712− receiveChan rp :: Process ()
1576+ () <- receiveChan rp
17131577 liftIO $ putMVar clientDone ()
17141578
17151579 takeMVar clientDone
@@ -1723,8 +1587,8 @@ testCallLocal TestTransport{..} = do
17231587 runProcess node $ do
17241588 r <- (/=) <$> getSelfPid <*> callLocal getSelfPid
17251589 liftIO $ putMVar result r
1726−
1727− takeMVar result >>= assertBool "Expected 'True'"
1590+ True <- takeMVar result
1591+ return ()
17281592
17291593 -- Testing that when callLocal is interrupted, the worker is interrupted.
17301594 ibox <- newIORef False
@@ -1741,9 +1605,10 @@ testCallLocal TestTransport{..} = do
17411605 (send keeper ())
17421606 caller <- expect
17431607 exit caller "test"
1744− expect :: Process ()
1745−
1746− readIORef ibox >>= assertBool "Expected 'True'"
1608+ () <- expect
1609+ return ()
1610+ True <- readIORef ibox
1611+ return ()
17471612
17481613 -- Testing that when the worker raises an exception, the exception is propagated to the parent.
17491614 ibox2 <- newIORef False
@@ -1752,8 +1617,8 @@ testCallLocal TestTransport{..} = do
17521617 liftIO $ writeIORef ibox2 $ case r of
17531618 Left (ErrorCall "e") -> True
17541619 _ -> False
1755−
1756− readIORef ibox >>= assertBool "Expected 'True'"
1620+ True <- readIORef ibox
1621+ return ()
17571622
17581623 -- Test that caller waits for the worker in correct situation
17591624 ibox3 <- newIORef False
@@ -1770,8 +1635,8 @@ testCallLocal TestTransport{..} = do
17701635 liftIO $ putMVar result3 =<< readIORef ibox3
17711636 worker <- expect
17721637 send worker ()
1773−
1774− takeMVar result3 >>= assertBool "Expected 'True'"
1638+ True <- takeMVar result3
1639+ return ()
17751640
17761641 -- Test that caller waits for the worker in case when caller gets an exception
17771642 ibox4 <- newIORef False
@@ -1787,10 +1652,14 @@ testCallLocal TestTransport{..} = do
17871652 `finally` (liftIO $ putMVar result4 =<< readIORef ibox4)
17881653 caller <- expect
17891654 exit caller "hi!"
1790−
1791− takeMVar result4 >>= assertBool "Expected 'True'"
1655+ True <- takeMVar result4
1656+ return ()
17921657 -- XXX: Testing that when mask_ $ callLocal p runs p in masked state.
17931658
1659+
1660+
1661+
1662+
17941663tests :: TestTransport -> IO [Test]
17951664tests testtrans = return [
17961665 testGroup "Basic features" [
@@ -1814,7 +1683,6 @@ tests testtrans = return [
18141683 , testCase "MatchMessageUnwrap" (testMatchMessageWithUnwrap testtrans)
18151684 , testCase "ReceiveChanTimeout" (testReceiveChanTimeout testtrans)
18161685 , testCase "ReceiveChanFeatures" (testReceiveChanFeatures testtrans)
1817− , testCase "ChanLifecycle" (testChanLifecycle testtrans)
18181686 , testCase "KillLocal" (testKillLocal testtrans)
18191687 , testCase "KillRemote" (testKillRemote testtrans)
18201688 , testCase "Die" (testDie testtrans)
@@ -1824,7 +1692,7 @@ tests testtrans = return [
18241692 , testCase "MaskRestoreScope" (testMaskRestoreScope testtrans)
18251693 , testCase "ExitLocal" (testExitLocal testtrans)
18261694 , testCase "ExitRemote" (testExitRemote testtrans)
1827− , testCase "RegistryMonitoring" (testRegistryMonitoring testtrans)
1695+ , testCase "TestRegistryMonitor" (testRegistryMonitoring testtrans)
18281696 , testCase "TextCallLocal" (testCallLocal testtrans)
18291697 -- Unsafe Primitives
18301698 , testCase "TestUnsafeSend" (testUnsafeSend testtrans)
@@ -1877,3 +1745,17 @@ tests testtrans = return [
18771745 , testCase "MonitorUnreachable" (testMonitorUnreachable testtrans True False)
18781746 ]
18791747 ]
1748+
1749+syncBreakConnection :: (NT.EndPointAddress -> NT.EndPointAddress -> IO ()) -> LocalNode -> LocalNode -> IO ()
1750+syncBreakConnection breakConnection nid0 nid1 = do
1751+ m <- newEmptyMVar
1752+ _ <- forkProcess nid1 $ getSelfPid >>= liftIO . putMVar m
1753+ runProcess nid0 $ do
1754+ them <- liftIO $ takeMVar m
1755+ pinger <- spawnLocal $ forever $ send them ()
1756+ _ <- monitorNode (localNodeId nid1)
1757+ liftIO $ breakConnection (nodeAddress $ localNodeId nid0)
1758+ (nodeAddress $ localNodeId nid1)
1759+ NodeMonitorNotification _ _ _ <- expect
1760+ kill pinger "finished"
1761+ return ()