aeson-gadt-th-0.2.1.2: test/Expectations.hs
-- | Some useful helper expectations for use with Hspec.
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Expectations where
import Control.Exception (PatternMatchFail, evaluate, throwIO, try)
import Data.Maybe
import GHC.Stack (HasCallStack, callStack, getCallStack, SrcLoc)
import Test.Hspec
import qualified Test.HUnit.Lang as HUnit
-- | Assert that a pattern match succeeds; may require -fno-warn-incomplete-patterns
expectPattern :: (HasCallStack, Show a) => (a -> b) -> a -> IO b
expectPattern f a =
try (evaluate $ f a) >>= \case
Right b -> pure b
Left (e :: PatternMatchFail) ->
throwHUnit $ "Pattern match failed, value was: " ++ show a
-- | Same as 'expectPattern' but with its arguments flipped.
shouldMatchPattern :: (HasCallStack, Show a) => a -> (a -> b) -> IO b
shouldMatchPattern = flip expectPattern
-- | Same as 'shouldMatchPattern' but with the return type specialized as unit.
-- Useful for pattern matching on GADTs.
shouldMatchPattern_ :: (HasCallStack, Show a) => a -> (a -> ()) -> IO ()
shouldMatchPattern_ = shouldMatchPattern
-- | Obtain the source location given a reverse call stack index.
callStackLoc :: (HasCallStack) => Int -> Maybe SrcLoc
callStackLoc index = fmap snd $ listToMaybe $ drop index $ reverse $ getCallStack callStack
-- | Throw an test failed exception, defaulting the source location to the caller's caller.
throwHUnit :: (HasCallStack) => String -> IO a
throwHUnit = throwHUnitWithLoc 0
-- | Throw a test failure exception with source location determined by the supplied reverse call stack index.
throwHUnitWithLoc :: (HasCallStack) => Int -> String -> IO a
throwHUnitWithLoc index msg = throwIO $ HUnit.HUnitFailure (callStackLoc index) $ HUnit.Reason msg