packages feed

fb-util-0.1.0.1: tests/ExceptionTest.hs

{-
  Copyright (c) Meta Platforms, Inc. and affiliates.
  All rights reserved.

  This source code is licensed under the BSD-style license found in the
  LICENSE file in the root directory of this source tree.
-}

{-# OPTIONS_GHC -fno-warn-name-shadowing -Wno-incomplete-uni-patterns #-}
{-# LANGUAGE OverloadedStrings #-}

module ExceptionTest (main) where

import Control.Exception
import Util.Control.Exception
import Test.HUnit
import TestRunner

catchAllTest :: Test
catchAllTest = TestLabel "catchAll" . TestCase $ do
  r <- (throwIO ThreadKilled `catchAll` \_ -> return 1)
      `catch` \SomeException{} -> return (2::Int)
  assertEqual "catchAll1" 2 r
  r <- (throwIO (ErrorCall "x") `catchAll` \_ -> return 1)
      `catch` \SomeException{} -> return (2::Int)
  assertEqual "catchAll2" 1 r

tryAllTest :: Test
tryAllTest = TestLabel "tryAll" . TestCase $ do
  r <- try (tryAll (throwIO ThreadKilled))
  assertBool "tryAll1" $ case r of
    Left x | Just ThreadKilled{} <- fromException x -> True
    _ -> False
  r <- try (tryAll (throwIO (ErrorCall "x")))
   :: IO (Either SomeException (Either SomeException Int))
  assertBool "tryAll2" $ case r of
    Right (Left x) | Just ErrorCall{} <- fromException x -> True
    _ -> False

tryBracketTest :: Test
tryBracketTest = TestLabel "tryBracket" . TestCase $ do
  r <- tryAll $ tryBracket
     (throwIO (ErrorCall "a"))
     (\_ _ -> throwIO (ErrorCall "b"))
     (\_ -> throwIO (ErrorCall "c"))
  assertBool "tryBracket1" $ case r of
    Left e | Just (ErrorCall "a") <- fromException e -> True
    _other -> False
  r <- tryAll $ tryBracket
     (return 'a')
     (\'a' _ -> throwIO (ErrorCall "b")) -- release throws; this is what we get
     (\'a' -> throwIO (ErrorCall "c"))
  assertBool "tryBracket2" $ case r of
    Left e | Just (ErrorCall "b") <- fromException e -> True
    _other -> False
  r <- tryAll $ tryBracket
     (return 'a')
     (\'a' Left{} -> return ())
     (\'a' -> throwIO (ErrorCall "c"))
  assertBool "tryBracket3" $ case r of
    Left e | Just (ErrorCall "c") <- fromException e -> True
    _other -> False
  r <- tryAll $ tryBracket
     (return 'a')
     (\'a' Right{} -> return ())
     (\'a' -> return 'c')
  assertBool "tryBracket4" $ case r of
    Right 'c' -> True
    _other -> False

tryFinallyTest :: Test
tryFinallyTest = TestLabel "tryFinally" . TestCase $ do
  r <- tryAll $ tryFinally
     (throwIO (ErrorCall "a"))
     (\Left{} -> throwIO (ErrorCall "b"))
  assertBool "tryFinally1" $ case r of
    Left e | Just (ErrorCall "b") <- fromException e -> True
    _other -> False
  r <- tryAll $ tryFinally
     (return 'a')
     (\Right{} -> throwIO (ErrorCall "b"))
        -- release throws; this is what we get
  assertBool "tryFinally2" $ case r of
    Left e | Just (ErrorCall "b") <- fromException e -> True
    _other -> False

main :: IO ()
main = testRunner $ TestList
  [ catchAllTest
  , tryAllTest
  , tryBracketTest
  , tryFinallyTest
  ]