@@ -3,8 +3,9 @@ module Control.Distributed.Process.Tests.Mx (tests) where
4import Control.Distributed.Process.Tests.Internal.Utils
4import Control.Distributed.Process.Tests.Internal.Utils
5import Network.Transport.Test (TestTransport(..))
5import Network.Transport.Test (TestTransport(..))
6−
6+import Control.Exception (SomeException)
7−import Control.Distributed.Process
7+import Control.Distributed.Process hiding (bracket, finally, try)
8+import Control.Distributed.Process.Internal.Types (ProcessExitException(..))
8import Control.Distributed.Process.Node
9import Control.Distributed.Process.Node
9import qualified Control.Distributed.Process.UnsafePrimitives as Unsafe
10import qualified Control.Distributed.Process.UnsafePrimitives as Unsafe
@@ -28,12 +29,13 @@ import Control.Distributed.Process.Management
28 , mxBroadcast
29 , mxBroadcast
30import Control.Monad (void, unless)
31import Control.Monad (void, unless)
32+import Control.Monad.Catch(finally, bracket, try)
31import Control.Rematch (equalTo)
33import Control.Rematch (equalTo)
32import Data.Binary
34import Data.Binary
33import Data.List (find, sort)
35import Data.List (find, sort)
34import Data.Maybe (isJust, isNothing)
36import Data.Maybe (isJust, isNothing)
35import Data.Typeable
37import Data.Typeable
36−import GHC.Generics
38+import GHC.Generics hiding (from)
37#if ! MIN_VERSION_base(4,6,0)
39#if ! MIN_VERSION_base(4,6,0)
38import Prelude hiding (catch, log)
40import Prelude hiding (catch, log)
@@ -57,7 +59,7 @@ awaitExit pid =
57 (\_ -> return ())
59 (\_ -> return ())
60− withMonitorRef pid = bracket (monitor pid) unmonitor
62+ withMonitorRef p = bracket (monitor p) unmonitor
62testAgentBroadcast :: TestResult () -> Process ()
64testAgentBroadcast :: TestResult () -> Process ()
63testAgentBroadcast result = do
65testAgentBroadcast result = do
@@ -319,101 +321,163 @@ testMxRegMon remoteNode result = do
319ensure :: Process () -> Process () -> Process ()
321ensure :: Process () -> Process () -> Process ()
320ensure = flip finally
322ensure = flip finally
322−
324+type SendTest = ProcessId -> ReceivePort MxEvent -> Process Bool
323−testMxUnsafeSendEvents :: LocalNode -> Process ()
325+
324−testMxUnsafeSendEvents remoteNode = do
326+testNSend :: (String -> () -> Process ()) -> Maybe LocalNode -> TestResult Bool -> Process ()
325−
327+testNSend op n r = testMxSend n r $ \p1 sink -> do
326− -- ensure that when a registered process dies, we get a notification that
328+ let delay = 5000000
327− -- it has been unregistered as well as seeing the name get removed
329+ let label = "testMxSend"
329− let label1 = "aaaaa"
331+ register label p1
330− let label2 = "bbbbb"
332+ reg1 <- receiveChanTimeout delay sink
331− let isValid l = l ==label1 || l == label2
333+ case reg1 of
332− let agentLabel = "listener-agent"
334+ Just (MxRegistered pd lb)
333− let delay = 1000000
335+ | pd == p1 && lb == label -> return ()
334− (regChan, regSink) <- newChan
336+ _ -> die $ "Reg-Failed: " ++ show reg1
335− (unRegChan, unRegSink) <- newChan
337+
341+ sent <- receiveChanTimeout delay sink
343+ Just (MxSentToName lb by _)
344+ | by == us && lb == label -> return True
345+ _ -> die $ "Send-Failed: " ++ show sent
347+testSend :: (ProcessId -> () -> Process ()) -> Maybe LocalNode -> TestResult Bool -> Process ()
348+testSend op n r = testMxSend n r $ \p1 sink -> do
352+ -- verify the management event
354+ sent <- receiveChanTimeout 5000000 sink
356+ Just (MxSent pidTo pidFrom _)
357+ | pidTo == p1 && pidFrom == us -> return True
360+testMxSend :: Maybe LocalNode -> TestResult Bool -> SendTest -> Process ()
361+testMxSend mNode result test = do
363+ (chan, sink) <- newChan
336− agent <- mxAgent (MxAgentId agentLabel) () [
364+ agent <- mxAgent (MxAgentId $ agentLabel us) () [
337 mxSink $ \ev -> do
365 mxSink $ \ev -> do
338 case ev of
366 case ev of
367+ m@(MxSent _ fromPid _)
368+ | fromPid == us -> liftMX $ sendChan chan m
369+ m@(MxSentToName _ fromPid _)
370+ | fromPid == us -> liftMX $ sendChan chan m
339− MxRegistered pid label
371+ m@(MxRegistered _ name)
340− | isValid label -> liftMX $ sendChan regChan (label, pid)
341− MxUnRegistered pid label
342− | isValid label -> liftMX $ sendChan unRegChan (label, pid)
372+ | name == label -> liftMX $ sendChan chan m
343 _ -> return ()
373 _ -> return ()
347 (sp, rp) <- newChan
377 (sp, rp) <- newChan
379+ Nothing -> void $ spawnLocal (proc sp)
348− liftIO $ forkProcess remoteNode $ do
380+ Just remoteNode -> void $ liftIO $ forkProcess remoteNode $ proc sp
349− getSelfPid >>= sendChan sp
350− expect :: Process ()
352 p1 <- receiveChan rp
382 p1 <- receiveChan rp
383+ res <- try (test p1 sink)
385+ Left (ProcessExitException _ m) -> (liftIO $ putStrLn $ "SomeException-" ++ show m) >> stash result False
386+ Right tr -> stash result tr
354− register label1 p1
390+ where
355− reg1 <- receiveChanTimeout delay regSink
391+ label = "testMxSend"
356− reg1 `shouldBe` equalTo (Just (label1, p1))
392+ agentLabel s = "mx-unsafe-check-agent-" ++ show s
357−
393+ proc sp' = getSelfPid >>= sendChan sp' >> expect :: Process ()
359− reg2 <- receiveChanTimeout delay regSink
360− reg2 `shouldBe` equalTo (Just (label2, p1))
362− n1 <- whereis label1
363− n1 `shouldBe` equalTo (Just p1)
365− n2 <- whereis label2
366− n2 `shouldBe` equalTo (Just p1)
370− unreg1 <- receiveChanTimeout delay unRegSink
371− unreg2 <- receiveChanTimeout delay unRegSink
373− sort [unreg1, unreg2]
374− `shouldBe` equalTo [Just (label1, p1), Just (label2, p1)]
376− kill agent "test-complete"
378tests :: TestTransport -> IO [Test]
395tests :: TestTransport -> IO [Test]
379tests TestTransport{..} = do
396tests TestTransport{..} = do
380 node1 <- newLocalNode testTransport initRemoteTable
397 node1 <- newLocalNode testTransport initRemoteTable
381 node2 <- newLocalNode testTransport initRemoteTable
398 node2 <- newLocalNode testTransport initRemoteTable
399+ let nid = localNodeId node2
383− testGroup "Mx Agents" [
401+ testGroup "MxAgents" [
384− testCase "Event Handling"
402+ testCase "EventHandling"
385 (delayedAssertion
403 (delayedAssertion
386 "expected True, but events where not as expected"
404 "expected True, but events where not as expected"
387 node1 True testAgentEventHandling)
405 node1 True testAgentEventHandling)
388− , testCase "Inter-Agent Broadcast"
406+ , testCase "InterAgentBroadcast"
389 (delayedAssertion
407 (delayedAssertion
390 "expected (), but no broadcast was received"
408 "expected (), but no broadcast was received"
391 node1 () testAgentBroadcast)
409 node1 () testAgentBroadcast)
392− , testCase "Agent Mailbox Handling"
410+ , testCase "AgentMailboxHandling"
393 (delayedAssertion
411 (delayedAssertion
394 "expected (Just ()), but no regular (mailbox) input was handled"
412 "expected (Just ()), but no regular (mailbox) input was handled"
395 node1 (Just ()) testAgentMailboxHandling)
413 node1 (Just ()) testAgentMailboxHandling)
396− , testCase "Agent Dual Input Handling"
414+ , testCase "AgentDualInputHandling"
397 (delayedAssertion
415 (delayedAssertion
398 "expected sum = 15, but the result was Nothing"
416 "expected sum = 15, but the result was Nothing"
399 node1 (Just 15 :: Maybe Int) testAgentDualInput)
417 node1 (Just 15 :: Maybe Int) testAgentDualInput)
400− , testCase "Agent Input Prioritisation"
418+ , testCase "AgentInputPrioritisation"
401 (delayedAssertion
419 (delayedAssertion
402 "expected [first, second, third, fourth, fifth], but result diverged"
420 "expected [first, second, third, fourth, fifth], but result diverged"
403 node1 (sort ["first", "second",
421 node1 (sort ["first", "second",
404 "third", "fourth",
422 "third", "fourth",
405 "fifth"]) testAgentPrioritisation)
423 "fifth"]) testAgentPrioritisation)
407− , testGroup "Mx Events" [
425+ , testGroup "MxEvents" [
408− testCase "Name Registration Events"
426+ testCase "NameRegistrationEvents"
409 (delayedAssertion
427 (delayedAssertion
410 "expected registration events to map to the correct ProcessId"
428 "expected registration events to map to the correct ProcessId"
411 node1 () testMxRegEvents)
429 node1 () testMxRegEvents)
412− , testCase "Post Death Name UnRegistration Events"
430+ , testCase "PostDeathNameUnRegistrationEvents"
413 (delayedAssertion
431 (delayedAssertion
414 "expected process deaths to result in unregistration events"
432 "expected process deaths to result in unregistration events"
415 node1 () (testMxRegMon node2))
433 node1 () (testMxRegMon node2))
434+ , testGroup "SentEvents" [
435+ testGroup "RemoteTargets" [
416− , testCase "Monitor Events"
436+ testCase "Unsafe.nsend"
417− (runProcess node1 (testMxUnsafeSendEvents node2))
437+ (delayedAssertion "expected mx events failed"
438+ node1 True (testNSend Unsafe.nsend $ Just node2))
439+ , testCase "Unsafe.nsendRemote"
440+ (delayedAssertion "expected mx events failed"
441+ node1 True (testNSend (Unsafe.nsendRemote nid) $ Just node2))
442+ , testCase "Unsafe.send"
443+ (delayedAssertion "expected mx events failed"
444+ node1 True (testSend Unsafe.send $ Just node2))
445+ , testCase "Unsafe.usend"
446+ (delayedAssertion "expected mx events failed"
447+ node1 True (testSend Unsafe.usend $ Just node2))
449+ (delayedAssertion "expected mx events failed"
450+ node1 True (testNSend nsend $ Just node2))
451+ , testCase "nsendRemote"
452+ (delayedAssertion "expected mx events failed"
453+ node1 True (testNSend (nsendRemote nid) $ Just node2))
455+ (delayedAssertion "expected mx events failed"
456+ node1 True (testSend send $ Just node2))
458+ (delayedAssertion "expected mx events failed"
459+ node1 True (testSend usend $ Just node2))
461+ , testGroup "LocalTargets" [
462+ testCase "Unsafe.nsend"
463+ (delayedAssertion "expected mx events failed"
464+ node1 True (testNSend Unsafe.nsend Nothing))
465+ , testCase "Unsafe.send"
466+ (delayedAssertion "expected mx events failed"
467+ node1 True (testSend Unsafe.send Nothing))
468+ , testCase "Unsafe.usend"
469+ (delayedAssertion "expected mx events failed"
470+ node1 True (testSend Unsafe.usend Nothing))
472+ (delayedAssertion "expected mx events failed"
473+ node1 True (testNSend nsend Nothing))
475+ (delayedAssertion "expected mx events failed"
476+ node1 True (testSend send Nothing))
478+ (delayedAssertion "expected mx events failed"
479+ node1 True (testSend usend Nothing))