@@ -5,6 +5,7 @@ module Control.Distributed.Process.Tests.Tracing (tests) where
5import Control.Distributed.Process.Tests.Internal.Utils
5import Control.Distributed.Process.Tests.Internal.Utils
6import Network.Transport.Test (TestTransport(..))
6import Network.Transport.Test (TestTransport(..))
8+import Control.Applicative ((<*))
8import Control.Concurrent (threadDelay)
9import Control.Concurrent (threadDelay)
9import Control.Concurrent.MVar
10import Control.Concurrent.MVar
@@ -19,9 +20,13 @@ import Control.Distributed.Process.Debug
19import Control.Distributed.Process.Management
20import Control.Distributed.Process.Management
20 ( MxEvent(..)
21 ( MxEvent(..)
23+import qualified Control.Exception as IO (bracket)
24+import Data.List (isPrefixOf, isSuffixOf)
23#if ! MIN_VERSION_base(4,6,0)
26#if ! MIN_VERSION_base(4,6,0)
24import Prelude hiding (catch, log)
27import Prelude hiding (catch, log)
29+import Prelude hiding ((<*))
27import Test.Framework
32import Test.Framework
@@ -29,6 +34,10 @@ import Test.Framework
29 , testGroup
34 , testGroup
31import Test.Framework.Providers.HUnit (testCase)
36import Test.Framework.Providers.HUnit (testCase)
37+import System.Environment (getEnvironment)
38+-- These are available in System.Environment only since base 4.7
39+import System.SetEnv (setEnv, unsetEnv)
33testSpawnTracing :: TestResult Bool -> Process ()
42testSpawnTracing :: TestResult Bool -> Process ()
34testSpawnTracing result = do
43testSpawnTracing result = do
@@ -282,6 +291,82 @@ testRemoteTraceRelay TestTransport{..} result =
282 -- and just to be polite...
291 -- and just to be polite...
283 liftIO $ closeLocalNode node2
292 liftIO $ closeLocalNode node2
294+-- | Sets the value of an environment variable while executing the given IO
295+-- computation and restores the preceeding value upon completion.
296+withEnv :: String -> String -> IO a -> IO a
298+ IO.bracket (fmap (lookup var) getEnvironment <* setEnv var val)
299+ (maybe (unsetEnv var) (setEnv var))
302+-- | Tests that one and only one interesting trace message is produced when a
303+-- given action is performed. A message is considered interesting when the given
304+-- function return @True@.
305+testSystemLoggerMsg :: TestTransport
307+ -> (a -> String -> Bool)
309+testSystemLoggerMsg t action interestingMessage =
310+ withEnv "DISTRIBUTED_PROCESS_TRACE_CONSOLE" "yes" $
311+ withEnv "DISTRIBUTED_PROCESS_TRACE_FLAGS" "pdnusrl" $ do
312+ n <- newLocalNode (testTransport t) initRemoteTable
316+ reregister "trace.logger" self
318+ let interestingMessage' (_ :: String, msg) = interestingMessage a msg
319+ -- Wait for the trace message.
320+ receiveWait [ matchIf interestingMessage' $ const $ return () ]
321+ -- Only one interesting message should arrive.
322+ Nothing <- receiveTimeout 100000
323+ [ matchIf interestingMessage' $ const $ return () ]
327+-- | Tests that one and only one trace message is produced when a message is
329+testSystemLoggerMxReceive :: TestTransport -> IO ()
330+testSystemLoggerMxReceive t = testSystemLoggerMsg t
331+ (getSelfPid >>= flip send ())
332+ (\_ msg -> "MxReceived" `isPrefixOf` msg
333+ -- discard traces of internal messages
334+ && not (":: RegisterReply" `isSuffixOf` msg)
337+-- | Tests that one and only one trace message is produced when a message is
339+testSystemLoggerMxSent :: TestTransport -> IO ()
340+testSystemLoggerMxSent t = testSystemLoggerMsg t
341+ (getSelfPid >>= flip send ())
342+ (const $ isPrefixOf "MxSent")
344+-- | Tests that one and only one trace message is produced when a process dies.
345+testSystemLoggerMxProcessDied :: TestTransport -> IO ()
346+testSystemLoggerMxProcessDied t = testSystemLoggerMsg t
347+ (spawnLocal $ return ())
348+ (\pid -> isPrefixOf $ "MxProcessDied " ++ show pid)
350+-- | Tests that one and only one trace message appears when a process spawns.
351+testSystemLoggerMxSpawned :: TestTransport -> IO ()
352+testSystemLoggerMxSpawned t = testSystemLoggerMsg t
353+ (spawnLocal $ return ())
354+ (\pid -> isPrefixOf $ "MxSpawned " ++ show pid)
356+-- | Tests that one and only one trace message appears when a process is
358+testSystemLoggerMxRegistered :: TestTransport -> IO ()
359+testSystemLoggerMxRegistered t = testSystemLoggerMsg t
360+ (getSelfPid >>= register "a" >> getSelfPid)
361+ (\self -> isPrefixOf $ "MxRegistered " ++ show self ++ " " ++ show "a")
363+-- | Tests that one and only one trace message appears when a process is
365+testSystemLoggerMxUnRegistered :: TestTransport -> IO ()
366+testSystemLoggerMxUnRegistered t = testSystemLoggerMsg t
367+ (getSelfPid >>= register "a" >> unregister "a" >> getSelfPid)
368+ (\self -> isPrefixOf $ "MxUnRegistered " ++ show self ++ " " ++ show "a")
285tests :: TestTransport -> IO [Test]
370tests :: TestTransport -> IO [Test]
286tests testtrans@TestTransport{..} = do
371tests testtrans@TestTransport{..} = do
287 node1 <- newLocalNode testTransport initRemoteTable
372 node1 <- newLocalNode testTransport initRemoteTable
@@ -323,4 +408,12 @@ tests testtrans@TestTransport{..} = do
323 (synchronisedAssertion
408 (synchronisedAssertion
324 "expected blah"
409 "expected blah"
325 node1 True (testRemoteTraceRelay testtrans) lock)
410 node1 True (testRemoteTraceRelay testtrans) lock)
411+ , testGroup "SystemLoggerTracer"
412+ [ testCase "MxReceive" $ testSystemLoggerMxReceive testtrans
413+ , testCase "MxSent" $ testSystemLoggerMxSent testtrans
414+ , testCase "MxProcessDied" $ testSystemLoggerMxProcessDied testtrans
415+ , testCase "MxSpawned" $ testSystemLoggerMxSpawned testtrans
416+ , testCase "MxRegistered" $ testSystemLoggerMxRegistered testtrans
417+ , testCase "MxUnRegistered" $ testSystemLoggerMxUnRegistered testtrans