cleff-0.1.0.0: test/ConcurrencySpec.hs
module ConcurrencySpec where
import Cleff
import Cleff.Error (runError, throwError)
import Cleff.State
import Control.Monad (when)
import Data.Set (Set)
import qualified Data.Set as Set
import Test.Hspec
import UnliftIO (concurrently_)
import UnliftIO.Concurrent (threadDelay)
spec :: Spec
spec = do
sharedState
errorHandling
sharedState :: Spec
sharedState = it "should have shared state" do
(_, set) <- runIOE $ runState (Set.empty @Int) do
concurrently_ (addWhen even x) (addWhen odd x)
set `shouldBe` Set.fromList [1..x]
where
x :: Int = 100
addWhen :: State (Set Int) :> es => (Int -> Bool) -> Int -> Eff es ()
addWhen f = \case
0 -> pure ()
n -> do
when (f n) $ do
modify $ Set.insert n
addWhen f $ n - 1
errorHandling :: Spec
errorHandling = it "should handle errors properly" do
(r, s) <- runIOE $ runState (0 :: Int) $ runError @String $ concurrently_
(liftIO (threadDelay 10000) >> throwError err)
(modify (+x))
case r of
Left e -> e `shouldBe` err
Right _ -> expectationFailure "no error caught - or error escaped"
s `shouldBe` x
where
x :: Int = 67
err = "error"