{-# OPTIONS_GHC -F -pgmF htfpp #-} module Main where import BasePrelude import Test.Framework import Test.QuickCheck.Instances import qualified SlaveThread as S import qualified Control.Concurrent.SSem as SSem main = htfMain $ htf_thisModulesTests test_forkedThreadsRunFine = replicateM 100 $ do var <- newIORef 0 let increment = modifyIORef var (+1) semaphore <- SSem.new 0 S.fork $ do increment semaphore' <- SSem.new (-1) S.fork $ do increment SSem.signal semaphore' S.fork $ do increment SSem.signal semaphore' SSem.wait semaphore' SSem.signal semaphore SSem.wait semaphore assertEqual 3 =<< readIORef var test_killingAThreadKillsDeepSlaves = replicateM 100 $ do var <- newIORef 0 let increment = modifyIORef var (+1) semaphore <- SSem.new 0 thread <- S.forkFinally (SSem.signal semaphore) $ do w <- forkWait $ do w <- forkWait $ do threadDelay $ 20*10^3 increment w w killThread thread SSem.wait semaphore assertEqual 0 =<< readIORef var test_dyingNormallyKillsSlaves = replicateM 100 $ do var <- newIORef 0 let increment = modifyIORef var (+1) semaphore <- SSem.new 0 S.forkFinally (SSem.signal semaphore) $ do S.fork $ do threadDelay $ 10^4 increment S.fork $ do threadDelay $ 10^4 increment SSem.wait semaphore assertEqual 0 =<< readIORef var test_finalizationOrder = replicateM 1000 $ do var <- newIORef 0 semaphore <- SSem.new 0 S.forkFinally (modifyIORef var (*2) >> SSem.signal semaphore) $ do S.forkFinally (modifyIORef var (+1)) $ return () S.forkFinally (modifyIORef var (+1)) $ return () SSem.wait semaphore assertEqual 4 =<< readIORef var test_exceptionsDontGetLost = replicateM 100 $ do assertThrowsSomeIO $ do S.fork $ do S.fork $ do error "!" threadDelay $ 10^4 threadDelay $ 10^4 forkWait :: IO a -> IO (IO ()) forkWait io = do v <- newEmptyMVar S.fork $ do r <- try io putMVar v () either (throwIO :: SomeException -> IO a) return r return $ takeMVar v