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 Data.Default,
module Data.Foldable,
module Data.Typeable,
module Data.Text,
module Data.Either,
module Data.Maybe,
)
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.Process.ForkIOScheduler as Scheduler
import Control.Eff.Extend
import Control.Monad
import Data.Default
import Data.Either
( fromRight,
isLeft,
isRight,
)
import Data.Foldable
import Data.Maybe (fromMaybe)
import Data.Text
( Text,
pack,
)
import Data.Typeable hiding (cast)
import GHC.Stack
import qualified System.IO as IO
import Test.Tasty hiding
( Timeout,
defaultMain,
)
import qualified Test.Tasty as Tasty
import Test.Tasty.HUnit
import Test.Tasty.Runners
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 allLogEvents $
Scheduler.schedule $
handleInterrupts
onInt
et
where
onInt = lift . assertFailure . show . MkUnhandledProcessInterrupt
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 ->
ShutdownReason ->
Eff r ()
assertShutdown p r = do
unlinkProcess p
m <- monitor p
sendShutdown p r
logInfo (LABEL "awaitProcessDown" p) m
logCallStack debugSeverity
receiveSelectedMessage (selectProcessDown m)
>>= lift . assertEqual "bad exit reason" (MkUnhandledProcessExit r) . MkUnhandledProcessExit . downReason
awaitProcessDown ::
(Member Logs r, HasCallStack, HasProcesses r q) =>
ProcessId ->
Eff r ProcessDown
awaitProcessDown p = do
m <- monitor p
logInfo (LABEL "awaitProcessDown" p) m
logCallStack debugSeverity
receiveSelectedMessage (selectProcessDown m)
awaitProcessDownAny ::
(Member Logs r, HasCallStack, HasProcesses r q) =>
Eff r ProcessDown
awaitProcessDownAny = do
logInfo (MSG "awaitProcessDownAny")
logCallStack debugSeverity
receiveMessage