1{-# LANGUAGE DeriveGeneric #-}
2module Control.Distributed.Process.Tests.Mx (tests) where
4import Control.Distributed.Process.Tests.Internal.Utils
5import Network.Transport.Test (TestTransport(..))
7import Control.Concurrent (threadDelay)
8import Control.Distributed.Process
9import Control.Distributed.Process.Node
10import Control.Distributed.Process.Management
26import Control.Monad (void)
28import Data.List (find, sort)
29import Data.Maybe (isJust)
32#if ! MIN_VERSION_base(4,6,0)
33import Prelude hiding (catch, log)
40import Test.Framework.Providers.HUnit (testCase)
43 deriving (Typeable, Generic, Eq)
45instance Binary Publish where
47testAgentBroadcast :: TestResult () -> Process ()
48testAgentBroadcast result = do
49 (resultSP, resultRP) <- newChan :: Process (SendPort (), ReceivePort ())
51 publisher <- mxAgent (MxAgentId "publisher-agent") () [
52 mxSink $ \() -> mxBroadcast Publish >> mxReady
55 consumer <- mxAgent (MxAgentId "consumer-agent") () [
56 mxSink $ \Publish -> (liftMX $ sendChan resultSP ()) >> mxReady
60 -- Once the publisher has seen our message, it will broadcast the Publish
61 -- and the consumer will see that and send the result to our typed channel.
62 stash result =<< receiveChan resultRP
64 kill publisher "finished"
65 kill consumer "finished"
67testAgentDualInput :: TestResult (Maybe Int) -> Process ()
68testAgentDualInput result = do
70 _ <- mxAgent (MxAgentId "sum-agent") (0 :: Int) [
71 mxSink $ (\(i :: Int) -> do
72 mxSetLocal . (+i) =<< mxGetLocal
75 then do mxGetLocal >>= liftMX . sendChan sp
76 mxDeactivate "finished"
81 nsend "sum-agent" (3 :: Int)
83 nsend "sum-agent" (4 :: Int)
86 stash result =<< receiveChanTimeout 10000000 rp
88testAgentPrioritisation :: TestResult [String] -> Process ()
89testAgentPrioritisation result = do
91 -- TODO: this isn't really testing how we /prioritise/ one source
92 -- over another at all, but I've not yet figured out the right way
93 -- to do so, since we're at the whim of the scheduler with regards
94 -- the timeliness of nsend versus mxNotify anyway.
96 let name = "prioritising-agent"
98 void $ mxAgent (MxAgentId name) ["first"] [
99 mxSink (\(s :: String) -> do
103 n | n == 5 -> do liftMX $ sendChan sp st
104 mxDeactivate "finished"
105 _ -> mxReceive -- go to the mailbox
114 stash result . sort =<< receiveChan rp
116testAgentMailboxHandling :: TestResult (Maybe ()) -> Process ()
117testAgentMailboxHandling result = do
119 agent <- mxAgent (MxAgentId "listener-agent") () [
120 mxSink $ \() -> (liftMX $ sendChan sp ()) >> mxReady
123 nsend "listener-agent" ()
125 stash result =<< receiveChanTimeout 1000000 rp
126 kill agent "finished"
128testAgentEventHandling :: TestResult Bool -> Process ()
129testAgentEventHandling result = do
130 let initState = [] :: [MxEvent]
131 agentPid <- mxAgent (MxAgentId "lifecycle-listener-agent") initState [
136 (MxSpawned _) -> mxSetLocal (ev:st)
137 (MxProcessDied _ _) -> mxSetLocal (ev:st)
140 (mxSink $ \(ev, sp :: SendPort Bool) -> do
145 isJust $ find (\ev' ->
147 (MxSpawned p') -> p' == p
150 isJust $ find (\ev' ->
152 (MxProcessDied p' r') -> p' == p && r == r'
155 liftMX $ sendChan sp found
159 _ <- monitor agentPid
161 pid <- spawnLocal $ sendChan sp ()
164 -- By waiting for a monitor notification, we have a
165 -- higher probably that the agent has seen
167 receiveWait [ match (\(ProcessMonitorNotification _ _ _) -> return ()) ]
169 (replyTo, reply) <- newChan :: Process (SendPort Bool, ReceivePort Bool)
170 mxNotify (MxSpawned pid, replyTo)
171 mxNotify (MxProcessDied pid DiedNormal, replyTo)
173 seenAlive <- receiveChan reply
174 seenDead <- receiveChan reply
176 stash result $ seenAlive && seenDead
178tests :: TestTransport -> IO [Test]
179tests TestTransport{..} = do
180 node1 <- newLocalNode testTransport initRemoteTable
182 testGroup "Mx Agents" [
183 testCase "Event Handling"
185 "expected True, but events where not as expected"
186 node1 True testAgentEventHandling)
187 , testCase "Inter-Agent Broadcast"
189 "expected (), but no broadcast was received"
190 node1 () testAgentBroadcast)
191 , testCase "Agent Mailbox Handling"
193 "expected (Just ()), but no regular (mailbox) input was handled"
194 node1 (Just ()) testAgentMailboxHandling)
195 , testCase "Agent Dual Input Handling"
197 "expected sum = 15, but the result was Nothing"
198 node1 (Just 15 :: Maybe Int) testAgentDualInput)
199 , testCase "Agent Input Prioritisation"
201 "expected [first, second, third, fourth, fifth], but result diverged"
202 node1 (sort ["first", "second",
204 "fifth"]) testAgentPrioritisation)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list