@@ -1,11 +1,23 @@
1−{-# LANGUAGE DeriveGeneric #-}
1+{-# LANGUAGE DeriveGeneric #-}
2+{-# LANGUAGE ParallelListComp #-}
2module Control.Distributed.Process.Tests.Mx (tests) where
4module Control.Distributed.Process.Tests.Mx (tests) where
4import Control.Distributed.Process.Tests.Internal.Utils
6import Control.Distributed.Process.Tests.Internal.Utils
5import Network.Transport.Test (TestTransport(..))
7import Network.Transport.Test (TestTransport(..))
6−
8+import Control.Exception (SomeException)
9+import Control.Distributed.Process hiding (bracket, finally, try)
7−import Control.Distributed.Process
10+import Control.Distributed.Process.Internal.Types
11+ ( ProcessExitException(..)
12+ , unsafeCreateUnencodedMessage
8import Control.Distributed.Process.Node
14import Control.Distributed.Process.Node
15+import qualified Control.Distributed.Process.UnsafePrimitives as Unsafe
9import Control.Distributed.Process.Management
21import Control.Distributed.Process.Management
10 ( MxEvent(..)
22 ( MxEvent(..)
11 , MxAgentId(..)
23 , MxAgentId(..)
@@ -22,12 +34,13 @@ import Control.Distributed.Process.Management
22 , mxBroadcast
34 , mxBroadcast
24import Control.Monad (void, unless)
36import Control.Monad (void, unless)
37+import Control.Monad.Catch(finally, bracket, try)
25import Control.Rematch (equalTo)
38import Control.Rematch (equalTo)
26import Data.Binary
39import Data.Binary
27−import Data.List (find, sort)
40+import Data.List (find, sort, intercalate)
28−import Data.Maybe (isJust, isNothing)
41+import Data.Maybe (isJust, fromJust, isNothing)
29import Data.Typeable
42import Data.Typeable
30−import GHC.Generics
43+import GHC.Generics hiding (from)
31#if ! MIN_VERSION_base(4,6,0)
44#if ! MIN_VERSION_base(4,6,0)
32import Prelude hiding (catch, log)
45import Prelude hiding (catch, log)
@@ -51,7 +64,7 @@ awaitExit pid =
51 (\_ -> return ())
64 (\_ -> return ())
54− withMonitorRef pid = bracket (monitor pid) unmonitor
67+ withMonitorRef p = bracket (monitor p) unmonitor
56testAgentBroadcast :: TestResult () -> Process ()
69testAgentBroadcast :: TestResult () -> Process ()
57testAgentBroadcast result = do
70testAgentBroadcast result = do
@@ -313,43 +326,162 @@ testMxRegMon remoteNode result = do
313ensure :: Process () -> Process () -> Process ()
326ensure :: Process () -> Process () -> Process ()
314ensure = flip finally
327ensure = flip finally
329+testNSend :: (String -> () -> Process ())
333+testNSend op n r = testMxSend n r $ \p1 sink -> do
335+ let label = "testMxSend"
336+ let isValid = isValidLabel n label
339+ reg1 <- receiveChanTimeout delay sink
341+ Just (MxRegistered pd lb)
342+ | pd == p1 && isValid lb -> return ()
343+ _ -> die $ "Reg-Failed: " ++ show reg1
348+ sent <- receiveChanTimeout delay sink
350+ Just (MxSentToName lb by _)
351+ | by == us && isValid lb -> return True
352+ _ -> die $ "Send-Failed: " ++ show sent
355+ isValidLabel n l1 l2
357+ | isJust n = l2 == l1 ++ "@" ++ show (localNodeId $ fromJust n)
360+testSend :: (ProcessId -> () -> Process ())
364+testSend op n r = testMxSend n r $ \p1 sink -> do
368+ -- verify the management event
370+ sent <- receiveChanTimeout 5000000 sink
372+ Just (MxSent pidTo pidFrom _)
373+ | pidTo == p1 && pidFrom == us -> return True
376+type SendTest = ProcessId -> ReceivePort MxEvent -> Process Bool
378+testMxSend :: Maybe LocalNode -> TestResult Bool -> SendTest -> Process ()
379+testMxSend mNode result test = do
381+ (chan, sink) <- newChan
382+ agent <- mxAgent (MxAgentId $ agentLabel us) () [
385+ m@(MxSent _ fromPid _)
386+ | fromPid == us -> liftMX $ sendChan chan m
387+ m@(MxSentToName _ fromPid _)
388+ | fromPid == us -> liftMX $ sendChan chan m
389+ m@(MxRegistered _ name)
390+ | name == label -> liftMX $ sendChan chan m
397+ Nothing -> void $ spawnLocal (proc sp)
398+ Just remoteNode -> void $ liftIO $ forkProcess remoteNode $ proc sp
400+ p1 <- receiveChan rp
401+ res <- try (test p1 sink)
403+ Left (ProcessExitException _ m) -> (liftIO $ putStrLn $ "SomeException-" ++ show m) >> stash result False
404+ Right tr -> stash result tr
409+ label = "testMxSend"
410+ agentLabel s = "mx-unsafe-check-agent-" ++ show s
411+ proc sp' = getSelfPid >>= sendChan sp' >> expect :: Process ()
316tests :: TestTransport -> IO [Test]
413tests :: TestTransport -> IO [Test]
317tests TestTransport{..} = do
414tests TestTransport{..} = do
318 node1 <- newLocalNode testTransport initRemoteTable
415 node1 <- newLocalNode testTransport initRemoteTable
319 node2 <- newLocalNode testTransport initRemoteTable
416 node2 <- newLocalNode testTransport initRemoteTable
321− testGroup "Mx Agents" [
418+ testGroup "MxAgents" [
322− testCase "Event Handling"
419+ testCase "EventHandling"
323 (delayedAssertion
420 (delayedAssertion
324 "expected True, but events where not as expected"
421 "expected True, but events where not as expected"
325 node1 True testAgentEventHandling)
422 node1 True testAgentEventHandling)
326− , testCase "Inter-Agent Broadcast"
423+ , testCase "InterAgentBroadcast"
327 (delayedAssertion
424 (delayedAssertion
328 "expected (), but no broadcast was received"
425 "expected (), but no broadcast was received"
329 node1 () testAgentBroadcast)
426 node1 () testAgentBroadcast)
330− , testCase "Agent Mailbox Handling"
427+ , testCase "AgentMailboxHandling"
331 (delayedAssertion
428 (delayedAssertion
332 "expected (Just ()), but no regular (mailbox) input was handled"
429 "expected (Just ()), but no regular (mailbox) input was handled"
333 node1 (Just ()) testAgentMailboxHandling)
430 node1 (Just ()) testAgentMailboxHandling)
334− , testCase "Agent Dual Input Handling"
431+ , testCase "AgentDualInputHandling"
335 (delayedAssertion
432 (delayedAssertion
336 "expected sum = 15, but the result was Nothing"
433 "expected sum = 15, but the result was Nothing"
337 node1 (Just 15 :: Maybe Int) testAgentDualInput)
434 node1 (Just 15 :: Maybe Int) testAgentDualInput)
338− , testCase "Agent Input Prioritisation"
435+ , testCase "AgentInputPrioritisation"
339 (delayedAssertion
436 (delayedAssertion
340 "expected [first, second, third, fourth, fifth], but result diverged"
437 "expected [first, second, third, fourth, fifth], but result diverged"
341 node1 (sort ["first", "second",
438 node1 (sort ["first", "second",
342 "third", "fourth",
439 "third", "fourth",
343 "fifth"]) testAgentPrioritisation)
440 "fifth"]) testAgentPrioritisation)
345− , testGroup "Mx Events" [
442+ , testGroup "MxEvents" [
346− testCase "Name Registration Events"
443+ testCase "NameRegistrationEvents"
347 (delayedAssertion
444 (delayedAssertion
348 "expected registration events to map to the correct ProcessId"
445 "expected registration events to map to the correct ProcessId"
349 node1 () testMxRegEvents)
446 node1 () testMxRegEvents)
350− , testCase "Post Death Name UnRegistration Events"
447+ , testCase "PostDeathNameUnRegistrationEvents"
351 (delayedAssertion
448 (delayedAssertion
352 "expected process deaths to result in unregistration events"
449 "expected process deaths to result in unregistration events"
353 node1 () (testMxRegMon node2))
450 node1 () (testMxRegMon node2))
451+ , testGroup "SendEvents" $ buildTestCases node1 node2
455+ buildTestCases n1 n2 =
456+ let nid = localNodeId n2 in build n2 [
458+ ("Unsafe.nsend", testNSend Unsafe.nsend)
459+ , ("Unsafe.nsendRemote", testNSend (Unsafe.nsendRemote nid))
460+ , ("nsend", testNSend nsend)
461+ , ("nsendRemote", testNSend (nsendRemote nid))
464+ ("Unsafe.send", testSend Unsafe.send)
465+ , ("Unsafe.usend", testSend Unsafe.usend)
466+ , ("send", testSend send)
467+ , ("usend", testSend usend)
470+ ("forward", testSend (\p m -> forward (unsafeCreateUnencodedMessage m) p))
471+ , ("uforward", testSend (\p m -> uforward (unsafeCreateUnencodedMessage m) p))
476+ -> [(String, [(String, (Maybe LocalNode -> TestResult Bool -> Process ()))])]
479+ [ testGroup (intercalate "-" [groupName, caseSuffix]) [
480+ testCase (intercalate "-" [caseName, caseSuffix])
481+ (delayedAssertion "expected mx events failed"
482+ ln True (caseImpl caseNode))
483+ | (caseName, caseImpl) <- groupCases
485+ | (groupName, groupCases) <- specs
486+ , (caseSuffix, caseNode) <- [("RemotePid", Just ln), ("LocalPid", Nothing)]