{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeFamilies #-} {-# OPTIONS_GHC -Wno-orphans #-} {- | This modules provides concurrency abstractions for hedgehog tests. Using "lifted-base" one can execute expensive test actions concurrently. For example, the actions invoked inside 'mapConcurrently_' are invoked in the same 'MonadTest' as the outer monad of 'mapConcurrently_'. @ import qualified Hedgehog.Extras.Test.Concurrent as H setUpEnvironment = H.mapConcurrently_ id [ H.threadDelay 100 >> pure 1 , H.threadDelay 200 >> pure 2 , H.threadDelay 300 >> pure 3 ] @ __Warning: Do not use this module for running concurrent checks!__ The 'MonadBaseControl' instance does not aggregate effects for 'PropertyT'. Consider the following code: @ LA.mapConcurrently_ id [ do H.note_ \"FAIL1\" success , do IO.threadDelay 1_000_000 H.note_ \"FAIL2\" failure , do H.note_ \"FAIL3\" failure ] @ Executing this code will give you the following output in the test report: @ 66 ┃ LA.mapConcurrently_ id 67 ┃ [ do 68 ┃ H.note_ \"FAIL1\" ┃ │ FAIL1 69 ┃ success 70 ┃ , do 71 ┃ IO.threadDelay 1_000_000 72 ┃ H.note_ \"FAIL2\" ┃ │ FAIL2 73 ┃ failure ┃ ^^^^^^^ 74 ┃ , do 75 ┃ H.note_ \"FAIL3\" 76 ┃ failure 77 ┃ ] @ Please note that only @FAIL1@ and @FAIL2@ annotations were reported - @FAIL3@ annotation and the failure below was swallowed without any information. __Don't use concurrency abstractions from this module, when you need to aggregate and report failures!__ -} module Hedgehog.Extras.Test.Concurrent ( threadDelay -- * Re-exports of concurrency abstractions from @lifted-base@ , module Control.Concurrent.Async.Lifted , module System.Timeout.Lifted ) where import Control.Applicative import Control.Concurrent.Async.Lifted import qualified Control.Concurrent.Lifted as IO import Control.Monad.Base import Control.Monad.IO.Class import Control.Monad.Trans.Control import Control.Monad.Trans.Resource import Data.Function import Data.Int import qualified GHC.Stack as GHC import System.IO (IO) import System.Timeout.Lifted import qualified UnliftIO import Hedgehog import qualified Hedgehog as H -- | Delay the thread by 'n' milliseconds. threadDelay :: (MonadTest m, MonadIO m) => Int -> m () threadDelay n = GHC.withFrozenCallStack . H.evalIO $ IO.threadDelay n instance MonadBase IO (ResourceT IO) where liftBase = liftIO instance MonadBaseControl IO (ResourceT IO) where type StM (ResourceT IO) a = a liftBaseWith = UnliftIO.withRunInIO restoreM = pure