@@ -3,9 +3,16 @@ 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 (ProcessExitException(..))
89import Control.Distributed.Process.Node
10+import qualified Control.Distributed.Process.UnsafePrimitives as Unsafe
11+ ( send
12+ , nsend
13+ , nsendRemote
14+ , usend
15+ )
916import Control.Distributed.Process.Management
1017 ( MxEvent(..)
1118 , MxAgentId(..)
@@ -22,12 +29,13 @@ import Control.Distributed.Process.Management
2229 , mxBroadcast
2330 )
2431import Control.Monad (void, unless)
32+import Control.Monad.Catch(finally, bracket, try)
2533import Control.Rematch (equalTo)
2634import Data.Binary
2735import Data.List (find, sort)
2836import Data.Maybe (isJust, isNothing)
2937import Data.Typeable
30−import GHC.Generics
38+import GHC.Generics hiding (from)
3139#if ! MIN_VERSION_base(4,6,0)
3240import Prelude hiding (catch, log)
3341#endif
@@ -51,7 +59,7 @@ awaitExit pid =
5159 (\_ -> return ())
5260 ]
5361 where
54− withMonitorRef pid = bracket (monitor pid) unmonitor
62+ withMonitorRef p = bracket (monitor p) unmonitor
5563
5664testAgentBroadcast :: TestResult () -> Process ()
5765testAgentBroadcast result = do
@@ -313,43 +321,163 @@ testMxRegMon remoteNode result = do
313321ensure :: Process () -> Process () -> Process ()
314322ensure = flip finally
315323
324+type SendTest = ProcessId -> ReceivePort MxEvent -> Process Bool
325+
326+testNSend :: (String -> () -> Process ()) -> Maybe LocalNode -> TestResult Bool -> Process ()
327+testNSend op n r = testMxSend n r $ \p1 sink -> do
328+ let delay = 5000000
329+ let label = "testMxSend"
330+
331+ register label p1
332+ reg1 <- receiveChanTimeout delay sink
333+ case reg1 of
334+ Just (MxRegistered pd lb)
335+ | pd == p1 && lb == label -> return ()
336+ _ -> die $ "Reg-Failed: " ++ show reg1
337+
338+ op label ()
339+
340+ us <- getSelfPid
341+ sent <- receiveChanTimeout delay sink
342+ case sent of
343+ Just (MxSentToName lb by _)
344+ | by == us && lb == label -> return True
345+ _ -> die $ "Send-Failed: " ++ show sent
346+
347+testSend :: (ProcessId -> () -> Process ()) -> Maybe LocalNode -> TestResult Bool -> Process ()
348+testSend op n r = testMxSend n r $ \p1 sink -> do
349+ -- initiate a send
350+ op p1 ()
351+
352+ -- verify the management event
353+ us <- getSelfPid
354+ sent <- receiveChanTimeout 5000000 sink
355+ case sent of
356+ Just (MxSent pidTo pidFrom _)
357+ | pidTo == p1 && pidFrom == us -> return True
358+ _ -> return False
359+
360+testMxSend :: Maybe LocalNode -> TestResult Bool -> SendTest -> Process ()
361+testMxSend mNode result test = do
362+ us <- getSelfPid
363+ (chan, sink) <- newChan
364+ agent <- mxAgent (MxAgentId $ agentLabel us) () [
365+ mxSink $ \ev -> do
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
371+ m@(MxRegistered _ name)
372+ | name == label -> liftMX $ sendChan chan m
373+ _ -> return ()
374+ mxReady
375+ ]
376+
377+ (sp, rp) <- newChan
378+ case mNode of
379+ Nothing -> void $ spawnLocal (proc sp)
380+ Just remoteNode -> void $ liftIO $ forkProcess remoteNode $ proc sp
381+
382+ p1 <- receiveChan rp
383+ res <- try (test p1 sink)
384+ case res of
385+ Left (ProcessExitException _ m) -> (liftIO $ putStrLn $ "SomeException-" ++ show m) >> stash result False
386+ Right tr -> stash result tr
387+ kill agent "bye"
388+ kill p1 "bye"
389+
390+ where
391+ label = "testMxSend"
392+ agentLabel s = "mx-unsafe-check-agent-" ++ show s
393+ proc sp' = getSelfPid >>= sendChan sp' >> expect :: Process ()
394+
316395tests :: TestTransport -> IO [Test]
317396tests TestTransport{..} = do
318397 node1 <- newLocalNode testTransport initRemoteTable
319398 node2 <- newLocalNode testTransport initRemoteTable
399+ let nid = localNodeId node2
320400 return [
321− testGroup "Mx Agents" [
322− testCase "Event Handling"
401+ testGroup "MxAgents" [
402+ testCase "EventHandling"
323403 (delayedAssertion
324404 "expected True, but events where not as expected"
325405 node1 True testAgentEventHandling)
326− , testCase "Inter-Agent Broadcast"
406+ , testCase "InterAgentBroadcast"
327407 (delayedAssertion
328408 "expected (), but no broadcast was received"
329409 node1 () testAgentBroadcast)
330− , testCase "Agent Mailbox Handling"
410+ , testCase "AgentMailboxHandling"
331411 (delayedAssertion
332412 "expected (Just ()), but no regular (mailbox) input was handled"
333413 node1 (Just ()) testAgentMailboxHandling)
334− , testCase "Agent Dual Input Handling"
414+ , testCase "AgentDualInputHandling"
335415 (delayedAssertion
336416 "expected sum = 15, but the result was Nothing"
337417 node1 (Just 15 :: Maybe Int) testAgentDualInput)
338− , testCase "Agent Input Prioritisation"
418+ , testCase "AgentInputPrioritisation"
339419 (delayedAssertion
340420 "expected [first, second, third, fourth, fifth], but result diverged"
341421 node1 (sort ["first", "second",
342422 "third", "fourth",
343423 "fifth"]) testAgentPrioritisation)
344424 ]
345− , testGroup "Mx Events" [
346− testCase "Name Registration Events"
425+ , testGroup "MxEvents" [
426+ testCase "NameRegistrationEvents"
347427 (delayedAssertion
348428 "expected registration events to map to the correct ProcessId"
349429 node1 () testMxRegEvents)
350− , testCase "Post Death Name UnRegistration Events"
430+ , testCase "PostDeathNameUnRegistrationEvents"
351431 (delayedAssertion
352432 "expected process deaths to result in unregistration events"
353433 node1 () (testMxRegMon node2))
434+ , testGroup "SentEvents" [
435+ testGroup "RemoteTargets" [
436+ testCase "Unsafe.nsend"
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))
448+ , testCase "nsend"
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))
454+ , testCase "send"
455+ (delayedAssertion "expected mx events failed"
456+ node1 True (testSend send $ Just node2))
457+ , testCase "usend"
458+ (delayedAssertion "expected mx events failed"
459+ node1 True (testSend usend $ Just node2))
460+ ]
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))
471+ , testCase "nsend"
472+ (delayedAssertion "expected mx events failed"
473+ node1 True (testNSend nsend Nothing))
474+ , testCase "send"
475+ (delayedAssertion "expected mx events failed"
476+ node1 True (testSend send Nothing))
477+ , testCase "usend"
478+ (delayedAssertion "expected mx events failed"
479+ node1 True (testSend usend Nothing))
480+ ]
481+ ]
482+ ]
354483 ]
355− ]