Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show full stacktrace in assertion failures #351

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion hunit/Test/Tasty/HUnit.hs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,6 @@ instance IsTest TestCase where
return $
case hunitResult of
Right info -> testPassed info
Left (HUnitFailure mbloc message) -> testFailed $ prependLocation mbloc message
Left (HUnitFailure cs message) -> testFailed $ prependCallStack cs message

testOptions = return []
42 changes: 28 additions & 14 deletions hunit/Test/Tasty/HUnit/Orig.hs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, TypeSynonymInstances #-}
{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, TypeSynonymInstances, RecordWildCards #-}

-- required for HasCallStack by different versions of GHC
{-# LANGUAGE ConstraintKinds, FlexibleContexts #-}
Expand All @@ -11,6 +11,7 @@ import qualified Control.Exception as E
import Control.Monad
import Data.Typeable (Typeable)
import Data.CallStack
import Data.List

-- Interfaces
-- ----------
Expand Down Expand Up @@ -38,12 +39,7 @@ assertFailure
:: HasCallStack
=> String -- ^ A message that is displayed with the assertion failure
-> IO a
assertFailure msg = E.throwIO (HUnitFailure location msg)
where
location :: Maybe SrcLoc
location = case reverse callStack of
(_, loc) : _ -> Just loc
[] -> Nothing
assertFailure msg = E.throwIO (HUnitFailure callStack msg)

-- Conditional Assertion Functions
-- -------------------------------
Expand Down Expand Up @@ -133,16 +129,34 @@ instance (AssertionPredicable t) => AssertionPredicable (IO t)


-- | Exception thrown by 'assertFailure' etc.
data HUnitFailure = HUnitFailure (Maybe SrcLoc) String
data HUnitFailure = HUnitFailure CallStack String
deriving (Eq, Show, Typeable)
instance E.Exception HUnitFailure where
displayException (HUnitFailure mbloc s) = prependLocation mbloc s
displayException (HUnitFailure mbloc s) = prependCallStack mbloc s

prependCallStack :: CallStack -> String -> String
prependCallStack cs s =
"Error message: " <> s <> "\n\n" <> prettyCallStack cs

prependLocation :: Maybe SrcLoc -> String -> String
prependLocation mbloc s =
case mbloc of
Nothing -> s
Just loc -> srcLocFile loc ++ ":" ++ show (srcLocStartLine loc) ++ ":\n" ++ s
prettyCallStack :: CallStack -> String
prettyCallStack = intercalate "\n" . prettyCallStackLines

prettyCallStackLines :: CallStack -> [String]
prettyCallStackLines cs = case cs of
[] -> []
stk -> "CallStack (from HasCallStack):"
: map ((" " ++) . prettyCallSite) stk
where
prettyCallSite (f, loc) = f ++ ", called at " ++ prettySrcLoc loc

Comment on lines +144 to +150
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

base re-exports prettyCallStackLines, so we should be able to use that. I'm assuming you made a local definition because you didn't want to rely on the ghc package?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this actually has a different reason, namely that the CallStack here is not the same that is used in GHC.Exception.

prettySrcLoc :: SrcLoc -> String
prettySrcLoc SrcLoc {..}
= foldr (++) ""
[ srcLocFile, ":"
, show srcLocStartLine, ":"
, show srcLocStartCol, " in "
, srcLocPackage, ":", srcLocModule
]

----------------------------------------------------------------------
-- DEPRECATED CODE
Expand Down
2 changes: 1 addition & 1 deletion hunit/Test/Tasty/HUnit/Steps.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ instance IsTest TestCaseSteps where
atomicModifyIORef ref (\l -> ((tme,msg):l, ()))

hunitResult <- (Right <$> assertionFn stepFn) `catch`
\(SomeException ex) -> return $ Left (displayException ex)
\(SomeException ex) -> return $ Left (displayException ex)

endTime <- getTime

Expand Down
Loading