module BracketSpec where import Test.Hspec import Control.Concurrent.MVar import Control.Effect import Control.Effect.Mask import Control.Effect.Bracket import Control.Effect.Error import Control.Effect.Conc import Control.Effect.Trace test1 :: IO ([String], Either () ()) test1 = runM $ runTraceListIO $ errorToIO @() $ bracketToIO $ do throw () `onError` trace "protected" test2 :: IO [String] test2 = runM $ fmap fst $ runTraceListIO $ maskToIO $ concToIO $ bracketToIO $ do a <- mask $ \restore -> async $ do restore (embed (newEmptyMVar @()) >>= embed . takeMVar) `onError` trace "protected" cancel a test3 :: IO ([String], Either () ()) test3 = runM $ runTraceListIO $ bracketToIO $ runError $ do throw () `onError` trace "protected" test4 :: IO (Either () [String]) test4 = runM $ runError $ fmap fst $ runTraceListIO $ bracketToIO $ do (throw () `onError` trace "protected") `catch` \() -> return () test5 :: ([String], Either () ()) test5 = run $ runTraceList $ runBracketLocally $ runError $ do throw () `onError` trace "protected" test6 :: IO ([String], Either () ()) test6 = runM $ runTraceList $ runBracketLocally $ errorToIO $ do throw () `onError` trace "protected" test7 :: Either () [String] test7 = run $ runError $ fmap fst $ runTraceList $ runBracketLocally $ do (throw () `onError` trace "protected") `catch` \() -> return () spec :: Spec spec = do describe "bracketToIO" $ do it "should protect against IO exceptions" $ do res <- test1 res `shouldBe` (["protected"], Left ()) it "should protect against asynchronous exceptions" $ do res <- test2 res `shouldBe` ["protected"] it "should protect against pure exceptions" $ do res3 <- test3 res3 `shouldBe` (["protected"], Left ()) res4 <- test4 res4 `shouldBe` Right ["protected"] describe "runBracketLocally" $ do it "should protect against pure exceptions of local effects" $ do test5 `shouldBe` (["protected"], Left ()) it "should not protect against global effects" $ do res6 <- test6 res6 `shouldBe` ([], Left ()) test7 `shouldBe` Right []