module Common ( module Common , module Test.Tasty , module Test.Tasty.HUnit , module Test.Tasty.Runners , module Control.Eff.Extend , module Control.Monad , module GHC.Stack , module Control.Concurrent , module Control.Concurrent.STM , module Control.DeepSeq , module Control.Eff , module Control.Eff.Concurrent , module Control.Eff.Concurrent.Misc , module Data.Default , module Data.Foldable , module Data.Typeable , module Data.Text , module Data.Either , module Data.Maybe , module Data.Type.Pretty ) where import Control.Concurrent import Control.Concurrent.STM import Control.DeepSeq import Control.Eff --import Control.Eff.Log import Control.Eff.Concurrent import Control.Eff.Concurrent.Misc import Control.Eff.Concurrent.Process.ForkIOScheduler as Scheduler import Control.Eff.Extend import Control.Monad import Data.Default import Data.Foldable import Data.Text ( Text , pack ) import Data.Typeable hiding ( cast ) import GHC.Stack import Test.Tasty hiding ( Timeout , defaultMain ) import qualified Test.Tasty as Tasty import Test.Tasty.HUnit import Test.Tasty.Runners import Data.Either ( fromRight , isLeft , isRight ) import Data.Maybe ( fromMaybe ) import Data.Type.Pretty import qualified System.IO as IO setTravisTestOptions :: TestTree -> TestTree setTravisTestOptions = localOption (timeoutSeconds 60) . localOption (NumThreads 1) timeoutSeconds :: Integer -> Tasty.Timeout timeoutSeconds seconds = Tasty.Timeout (seconds * 1000000) (show seconds ++ "s") runTestCase :: TestName -> Eff Effects () -> TestTree runTestCase msg et = testCase msg $ do lw <- stdoutLogWriter renderConsoleMinimalisticWide runLift $ withRichLogging lw "unit-tests" local0 allLogMessages $ Scheduler.schedule $ handleInterrupts onInt et where onInt = lift . assertFailure . show withTestLogC :: (e -> IO ()) -> (IO (e -> IO ()) -> TestTree) -> TestTree withTestLogC doSchedule k = k (return doSchedule) untilInterrupted :: Member t r => t (ResumeProcess v) -> Eff r () untilInterrupted pa = do r <- send pa case r of Interrupted _ -> return () _ -> untilInterrupted pa scheduleAndAssert :: forall r . (IoLogging r) => IO (Eff (Processes r) () -> IO ()) -> ((String -> Bool -> Eff (Processes r) ()) -> Eff (Processes r) ()) -> IO () scheduleAndAssert schedulerFactory testCaseAction = withFrozenCallStack $ do IO.hSetBuffering IO.stdout IO.LineBuffering resultVar <- newEmptyTMVarIO void (applySchedulerFactory schedulerFactory (testCaseAction (\title cond -> lift (atomically (putTMVar resultVar (title, cond)))) ) ) (title, result) <- atomically (takeTMVar resultVar) assertBool title result applySchedulerFactory :: forall r . (IoLogging r) => IO (Eff (Processes r) () -> IO ()) -> Eff (Processes r) () -> IO () applySchedulerFactory factory procAction = do scheduler <- factory scheduler (procAction >> lift (threadDelay 20000)) assertShutdown :: (Member Logs r, HasCallStack, HasProcesses r q, Lifted IO r) => ProcessId -> Interrupt 'NoRecovery -> Eff r () assertShutdown p r = do unlinkProcess p m <- monitor p sendShutdown p r logInfo ( "awaitProcessDown: " <> pack (show p) <> " " <> pack (show m) ) logCallStack debugSeverity receiveSelectedMessage (selectProcessDown m) >>= lift . assertEqual "bad exit reason" r . downReason awaitProcessDown :: (Member Logs r, HasCallStack, HasProcesses r q) => ProcessId -> Eff r ProcessDown awaitProcessDown p = do m <- monitor p logInfo ( "awaitProcessDown: " <> pack (show p) <> " " <> pack (show m) ) logCallStack debugSeverity receiveSelectedMessage (selectProcessDown m) awaitProcessDownAny :: (Member Logs r, HasCallStack, HasProcesses r q) => Eff r ProcessDown awaitProcessDownAny = do logInfo "awaitProcessDownAny" logCallStack debugSeverity receiveMessage