@@ -37,6 +37,9 @@ import Control.Distributed.Process.Internal.Types
37
37
, createUnencodedMessage
38
38
)
39
39
import Control.Distributed.Process.Node
40
+ import Control.Distributed.Process.Debug
41
+ import Control.Distributed.Process.Management.Internal.Types
42
+ import Control.Distributed.Process.Tests.Internal.Utils (shouldBe )
40
43
import Control.Distributed.Process.Serializable (Serializable )
41
44
42
45
import Test.HUnit (Assertion , assertBool , assertFailure )
@@ -1476,6 +1479,68 @@ testExitRemote TestTransport{..} = do
1476
1479
takeMVar supervisedDone
1477
1480
takeMVar supervisorDone
1478
1481
1482
+ testRegistryMonitoring :: TestTransport -> Assertion
1483
+ testRegistryMonitoring TestTransport {.. } = do
1484
+ node1 <- newLocalNode testTransport initRemoteTable
1485
+ node2 <- newLocalNode testTransport initRemoteTable
1486
+ waitH <- newEmptyMVar
1487
+
1488
+ let nid = localNodeId node2
1489
+ pid <- forkProcess node1 $ do
1490
+ getSelfPid >>= runUntilRegistered nid
1491
+ liftIO $ takeMVar waitH
1492
+
1493
+ runProcess node2 $ do
1494
+ register regName pid
1495
+ res <- whereis regName
1496
+ us <- getSelfPid
1497
+ liftIO $ do
1498
+ putMVar waitH ()
1499
+ assertBool " expected (Just pid)" $ res == (Just pid)
1500
+
1501
+ -- This delay isn't essential!
1502
+ -- The test case passes perfectly fine without it (feel free to comment out
1503
+ -- and see), however waiting a few seconds here, makes it much more likely
1504
+ -- that in delayUntilMaybeUnregistered we will hit the match case right
1505
+ -- away, and thus not be subjected to a 20 second delay. The value of 4
1506
+ -- seconds appears to work optimally on osx and across several linux distros
1507
+ -- running in virtual machines (which is essentially what we do in CI)
1508
+ void $ receiveTimeout 4000000 [ matchAny return ]
1509
+
1510
+ -- This delay doesn't serve much purpose in the happy path, however if some
1511
+ -- future patch breaks the cooperative behaviour of node controllers viz
1512
+ -- remote process registration and notification taking place via ncEffectDied,
1513
+ -- there would be the possibility of a race in the test case should we attempt
1514
+ -- to evaluate `whereis regName` on node2 right away. In case the name is still
1515
+ -- erroneously registered, observing the 20 second delay (or lack of), could at
1516
+ -- least give a hint that something is wrong, and we give up our time slice
1517
+ -- so that there's a higher change the registrations have been cleaned up
1518
+ -- in either case.
1519
+ runProcess node2 $ delayUntilMaybeUnregistered nid pid
1520
+
1521
+ regHere <- newEmptyMVar
1522
+ runProcess node2 $ whereis regName >>= liftIO . putMVar regHere
1523
+ res <- takeMVar regHere
1524
+ assertBool " expected Nothing, but process still registered" (res == Nothing )
1525
+
1526
+ where
1527
+ runUntilRegistered nid us = do
1528
+ whereisRemoteAsync nid regName
1529
+ receiveWait [
1530
+ matchIf (\ (WhereIsReply n (Just p)) -> n == regName && p == us)
1531
+ (const $ return () )
1532
+ ]
1533
+
1534
+ delayUntilMaybeUnregistered nid p = do
1535
+ whereisRemoteAsync nid regName
1536
+ receiveTimeout 20000000 {- 20 sec delay -} [
1537
+ matchIf (\ (WhereIsReply n p) -> n == regName && p == Nothing )
1538
+ (const $ return () )
1539
+ ]
1540
+ return ()
1541
+
1542
+ regName = " testRegisterRemote"
1543
+
1479
1544
testUnsafeSend :: TestTransport -> Assertion
1480
1545
testUnsafeSend TestTransport {.. } = do
1481
1546
serverAddr <- newEmptyMVar
@@ -1677,6 +1742,7 @@ tests testtrans = return [
1677
1742
, testCase " MaskRestoreScope" (testMaskRestoreScope testtrans)
1678
1743
, testCase " ExitLocal" (testExitLocal testtrans)
1679
1744
, testCase " ExitRemote" (testExitRemote testtrans)
1745
+ , testCase " RegistryMonitoring" (testRegistryMonitoring testtrans)
1680
1746
, testCase " TextCallLocal" (testCallLocal testtrans)
1681
1747
-- Unsafe Primitives
1682
1748
, testCase " TestUnsafeSend" (testUnsafeSend testtrans)
0 commit comments