module Control.Distributed.Process.Tests.Stats (tests) where
import Control.Distributed.Process.Tests.Internal.Utils
import Network.Transport.Test (TestTransport(..))
import Control.Concurrent.MVar
( MVar
, newEmptyMVar
, putMVar
, takeMVar
)
import Control.Distributed.Process
import Control.Distributed.Process.Node
import Data.Binary ()
import Data.Typeable ()
#if ! MIN_VERSION_base(4,6,0)
import Prelude hiding (catch)
#endif
import Test.Framework
( Test
, testGroup
)
import Test.HUnit (Assertion)
import Test.Framework.Providers.HUnit (testCase)
testLocalDeadProcessInfo :: TestResult (Maybe ProcessInfo) -> Process ()
testLocalDeadProcessInfo result = do
pid <- spawnLocal $ do "finish" <- expect; return ()
mref <- monitor pid
send pid "finish"
_ <- receiveWait [
matchIf (\(ProcessMonitorNotification ref' pid' r) ->
ref' == mref && pid' == pid && r == DiedNormal)
(\p -> return p)
]
getProcessInfo pid >>= stash result
testLocalLiveProcessInfo :: TestResult Bool -> Process ()
testLocalLiveProcessInfo result = do
self <- getSelfPid
node <- getSelfNode
register "foobar" self
mon <- liftIO $ newEmptyMVar
pid <- spawnLocal $ do
link self
mRef <- monitor self
stash mon mRef
"die" <- expect
return ()
monRef <- liftIO $ takeMVar mon
mpInfo <- getProcessInfo self
case mpInfo of
Nothing -> stash result False
Just p -> verifyPInfo p pid monRef node
where verifyPInfo :: ProcessInfo
-> ProcessId
-> MonitorRef
-> NodeId
-> Process ()
verifyPInfo pInfo pid mref node =
stash result $ infoNode pInfo == node &&
infoLinks pInfo == [pid] &&
infoMonitors pInfo == [(pid, mref)] &&
infoRegisteredNames pInfo == ["foobar"]
testRemoteLiveProcessInfo :: TestTransport -> LocalNode -> Assertion
testRemoteLiveProcessInfo TestTransport{..} node1 = do
serverAddr <- liftIO $ newEmptyMVar :: IO (MVar ProcessId)
liftIO $ launchRemote serverAddr
serverPid <- liftIO $ takeMVar serverAddr
withActiveRemote node1 $ \result -> do
self <- getSelfPid
link serverPid
send serverPid (self, "ping")
"pong" <- expect
pInfo <- getProcessInfo serverPid
stash result $ pInfo /= Nothing
where
launchRemote :: MVar ProcessId -> IO ()
launchRemote locMV = do
node2 <- liftIO $ newLocalNode testTransport initRemoteTable
_ <- liftIO $ forkProcess node2 $ do
self <- getSelfPid
liftIO $ putMVar locMV self
_ <- receiveWait [
match (\(pid, "ping") -> send pid "pong")
]
"stop" <- expect
return ()
return ()
withActiveRemote :: LocalNode
-> ((TestResult Bool -> Process ()) -> Assertion)
withActiveRemote n = do
a <- delayedAssertion "getProcessInfo remotePid failed" n True
return a
tests :: TestTransport -> IO [Test]
tests testtrans@TestTransport{..} = do
node1 <- newLocalNode testTransport initRemoteTable
return [
testGroup "Process Info" [
testCase "testLocalDeadProcessInfo"
(delayedAssertion
"expected dead process-info to be ProcessInfoNone"
node1 (Nothing) testLocalDeadProcessInfo)
, testCase "testLocalLiveProcessInfo"
(delayedAssertion
"expected process-info to be correctly populated"
node1 True testLocalLiveProcessInfo)
, testCase "testRemoveLiveProcessInfo"
(testRemoteLiveProcessInfo testtrans node1)
] ]