content: 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 []
  