@@ -3,9 +3,19 @@ module Control.Distributed.Process.Tests.Mx (tests) where
33
44import Control.Distributed.Process.Tests.Internal.Utils
55import Network.Transport.Test (TestTransport(..))
6−
7−import Control.Distributed.Process
6+import Control.Exception (SomeException)
7+import Control.Distributed.Process hiding (bracket, finally, try)
8+import Control.Distributed.Process.Internal.Types
9+ ( ProcessExitException(..)
10+ , unsafeCreateUnencodedMessage
11+ )
812import Control.Distributed.Process.Node
13+import qualified Control.Distributed.Process.UnsafePrimitives as Unsafe
14+ ( send
15+ , nsend
16+ , nsendRemote
17+ , usend
18+ )
919import Control.Distributed.Process.Management
1020 ( MxEvent(..)
1121 , MxAgentId(..)
@@ -22,12 +32,13 @@ import Control.Distributed.Process.Management
2232 , mxBroadcast
2333 )
2434import Control.Monad (void, unless)
35+import Control.Monad.Catch(finally, bracket, try)
2536import Control.Rematch (equalTo)
2637import Data.Binary
2738import Data.List (find, sort)
28−import Data.Maybe (isJust, isNothing)
39+import Data.Maybe (isJust, fromJust, isNothing)
2940import Data.Typeable
30−import GHC.Generics
41+import GHC.Generics hiding (from)
3142#if ! MIN_VERSION_base(4,6,0)
3243import Prelude hiding (catch, log)
3344#endif
@@ -51,7 +62,7 @@ awaitExit pid =
5162 (\_ -> return ())
5263 ]
5364 where
54− withMonitorRef pid = bracket (monitor pid) unmonitor
65+ withMonitorRef p = bracket (monitor p) unmonitor
5566
5667testAgentBroadcast :: TestResult () -> Process ()
5768testAgentBroadcast result = do
@@ -313,43 +324,188 @@ testMxRegMon remoteNode result = do
313324ensure :: Process () -> Process () -> Process ()
314325ensure = flip finally
315326
327+testNSend :: (String -> () -> Process ())
328+ -> Maybe LocalNode
329+ -> TestResult Bool
330+ -> Process ()
331+testNSend op n r = testMxSend n r $ \p1 sink -> do
332+ let delay = 5000000
333+ let label = "testMxSend"
334+ let isValid = isValidLabel n label
335+
336+ register label p1
337+ reg1 <- receiveChanTimeout delay sink
338+ case reg1 of
339+ Just (MxRegistered pd lb)
340+ | pd == p1 && isValid lb -> return ()
341+ _ -> die $ "Reg-Failed: " ++ show reg1
342+
343+ op label ()
344+
345+ us <- getSelfPid
346+ sent <- receiveChanTimeout delay sink
347+ case sent of
348+ Just (MxSentToName lb by _)
349+ | by == us && isValid lb -> return True
350+ _ -> die $ "Send-Failed: " ++ show sent
351+
352+ where
353+ isValidLabel n l1 l2
354+ | l2 == l2 = True
355+ | isJust n = l2 == l1 ++ "@" ++ show (localNodeId $ fromJust n)
356+ | otherwise = False
357+
358+testSend :: (ProcessId -> () -> Process ())
359+ -> Maybe LocalNode
360+ -> TestResult Bool
361+ -> Process ()
362+testSend op n r = testMxSend n r $ \p1 sink -> do
363+ -- initiate a send
364+ op p1 ()
365+
366+ -- verify the management event
367+ us <- getSelfPid
368+ sent <- receiveChanTimeout 5000000 sink
369+ case sent of
370+ Just (MxSent pidTo pidFrom _)
371+ | pidTo == p1 && pidFrom == us -> return True
372+ _ -> return False
373+
374+type SendTest = ProcessId -> ReceivePort MxEvent -> Process Bool
375+
376+testMxSend :: Maybe LocalNode -> TestResult Bool -> SendTest -> Process ()
377+testMxSend mNode result test = do
378+ us <- getSelfPid
379+ (chan, sink) <- newChan
380+ agent <- mxAgent (MxAgentId $ agentLabel us) () [
381+ mxSink $ \ev -> do
382+ case ev of
383+ m@(MxSent _ fromPid _)
384+ | fromPid == us -> liftMX $ sendChan chan m
385+ m@(MxSentToName _ fromPid _)
386+ | fromPid == us -> liftMX $ sendChan chan m
387+ m@(MxRegistered _ name)
388+ | name == label -> liftMX $ sendChan chan m
389+ _ -> return ()
390+ mxReady
391+ ]
392+
393+ (sp, rp) <- newChan
394+ case mNode of
395+ Nothing -> void $ spawnLocal (proc sp)
396+ Just remoteNode -> void $ liftIO $ forkProcess remoteNode $ proc sp
397+
398+ p1 <- receiveChan rp
399+ res <- try (test p1 sink)
400+ case res of
401+ Left (ProcessExitException _ m) -> (liftIO $ putStrLn $ "SomeException-" ++ show m) >> stash result False
402+ Right tr -> stash result tr
403+ kill agent "bye"
404+ kill p1 "bye"
405+
406+ where
407+ label = "testMxSend"
408+ agentLabel s = "mx-unsafe-check-agent-" ++ show s
409+ proc sp' = getSelfPid >>= sendChan sp' >> expect :: Process ()
410+
316411tests :: TestTransport -> IO [Test]
317412tests TestTransport{..} = do
318413 node1 <- newLocalNode testTransport initRemoteTable
319414 node2 <- newLocalNode testTransport initRemoteTable
415+ let nid = localNodeId node2
320416 return [
321− testGroup "Mx Agents" [
322− testCase "Event Handling"
417+ testGroup "MxAgents" [
418+ testCase "EventHandling"
323419 (delayedAssertion
324420 "expected True, but events where not as expected"
325421 node1 True testAgentEventHandling)
326− , testCase "Inter-Agent Broadcast"
422+ , testCase "InterAgentBroadcast"
327423 (delayedAssertion
328424 "expected (), but no broadcast was received"
329425 node1 () testAgentBroadcast)
330− , testCase "Agent Mailbox Handling"
426+ , testCase "AgentMailboxHandling"
331427 (delayedAssertion
332428 "expected (Just ()), but no regular (mailbox) input was handled"
333429 node1 (Just ()) testAgentMailboxHandling)
334− , testCase "Agent Dual Input Handling"
430+ , testCase "AgentDualInputHandling"
335431 (delayedAssertion
336432 "expected sum = 15, but the result was Nothing"
337433 node1 (Just 15 :: Maybe Int) testAgentDualInput)
338− , testCase "Agent Input Prioritisation"
434+ , testCase "AgentInputPrioritisation"
339435 (delayedAssertion
340436 "expected [first, second, third, fourth, fifth], but result diverged"
341437 node1 (sort ["first", "second",
342438 "third", "fourth",
343439 "fifth"]) testAgentPrioritisation)
344440 ]
345− , testGroup "Mx Events" [
346− testCase "Name Registration Events"
441+ , testGroup "MxEvents" [
442+ testCase "NameRegistrationEvents"
347443 (delayedAssertion
348444 "expected registration events to map to the correct ProcessId"
349445 node1 () testMxRegEvents)
350− , testCase "Post Death Name UnRegistration Events"
446+ , testCase "PostDeathNameUnRegistrationEvents"
351447 (delayedAssertion
352448 "expected process deaths to result in unregistration events"
353449 node1 () (testMxRegMon node2))
450+ , testGroup "SentEvents" [
451+ testGroup "RemoteTargets" [
452+ testCase "Unsafe.nsend"
453+ (delayedAssertion "expected mx events failed"
454+ node1 True (testNSend Unsafe.nsend $ Just node2))
455+ , testCase "Unsafe.nsendRemote"
456+ (delayedAssertion "expected mx events failed"
457+ node1 True (testNSend (Unsafe.nsendRemote nid) $ Just node2))
458+ , testCase "Unsafe.send"
459+ (delayedAssertion "expected mx events failed"
460+ node1 True (testSend Unsafe.send $ Just node2))
461+ , testCase "Unsafe.usend"
462+ (delayedAssertion "expected mx events failed"
463+ node1 True (testSend Unsafe.usend $ Just node2))
464+ , testCase "nsend"
465+ (delayedAssertion "expected mx events failed"
466+ node1 True (testNSend nsend $ Just node2))
467+ , testCase "nsendRemote"
468+ (delayedAssertion "expected mx events failed"
469+ node1 True (testNSend (nsendRemote nid) $ Just node2))
470+ , testCase "send"
471+ (delayedAssertion "expected mx events failed"
472+ node1 True (testSend send $ Just node2))
473+ , testCase "usend"
474+ (delayedAssertion "expected mx events failed"
475+ node1 True (testSend usend $ Just node2))
476+ , testCase "forward"
477+ (delayedAssertion "expected mx events failed"
478+ node1 True (testSend (\p m -> forward (unsafeCreateUnencodedMessage m) p) $ Just node2))
479+ , testCase "uforward"
480+ (delayedAssertion "expected mx events failed"
481+ node1 True (testSend (\p m -> uforward (unsafeCreateUnencodedMessage m) p) $ Just node2))
482+ ]
483+ , testGroup "LocalTargets" [
484+ testCase "Unsafe.nsend"
485+ (delayedAssertion "expected mx events failed"
486+ node1 True (testNSend Unsafe.nsend Nothing))
487+ , testCase "Unsafe.send"
488+ (delayedAssertion "expected mx events failed"
489+ node1 True (testSend Unsafe.send Nothing))
490+ , testCase "Unsafe.usend"
491+ (delayedAssertion "expected mx events failed"
492+ node1 True (testSend Unsafe.usend Nothing))
493+ , testCase "nsend"
494+ (delayedAssertion "expected mx events failed"
495+ node1 True (testNSend nsend Nothing))
496+ , testCase "send"
497+ (delayedAssertion "expected mx events failed"
498+ node1 True (testSend send Nothing))
499+ , testCase "usend"
500+ (delayedAssertion "expected mx events failed"
501+ node1 True (testSend usend Nothing))
502+ , testCase "forward"
503+ (delayedAssertion "expected mx events failed"
504+ node1 True (testSend (\p m -> forward (unsafeCreateUnencodedMessage m) p) Nothing))
505+ , testCase "uforward"
506+ (delayedAssertion "expected mx events failed"
507+ node1 True (testSend (\p m -> uforward (unsafeCreateUnencodedMessage m) p) Nothing))
508+ ]
509+ ]
510+ ]
354511 ]
355− ]