From 0260b663be15c7e65495ecb7e982c4bb8574a909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Hamb=C3=BCchen?= Date: Thu, 5 Dec 2024 22:35:56 +0100 Subject: [PATCH 1/2] Fix missing space in exception showing. Before: CppStdException e "my message"(Just "std::runtime_error") After: CppStdException e "my message" (Just "std::runtime_error") --- inline-c-cpp/src/Language/C/Inline/Cpp/Exception.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inline-c-cpp/src/Language/C/Inline/Cpp/Exception.hs b/inline-c-cpp/src/Language/C/Inline/Cpp/Exception.hs index e8878bc..c94df51 100644 --- a/inline-c-cpp/src/Language/C/Inline/Cpp/Exception.hs +++ b/inline-c-cpp/src/Language/C/Inline/Cpp/Exception.hs @@ -41,7 +41,7 @@ data CppException | CppNonStdException CppExceptionPtr (Maybe ByteString) instance Show CppException where - showsPrec p (CppStdException _ msg typ) = showParen (p >= 11) (showString "CppStdException e " . showsPrec 11 msg . showsPrec 11 typ) + showsPrec p (CppStdException _ msg typ) = showParen (p >= 11) (showString "CppStdException e " . showsPrec 11 msg . showChar ' ' . showsPrec 11 typ) showsPrec p (CppHaskellException e) = showParen (p >= 11) (showString "CppHaskellException " . showsPrec 11 e) showsPrec p (CppNonStdException _ typ) = showParen (p >= 11) (showString "CppOtherException e " . showsPrec 11 typ) From dee5eefe3ce0254cb01b6950108bad258c6666b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Hamb=C3=BCchen?= Date: Thu, 5 Dec 2024 23:48:06 +0100 Subject: [PATCH 2/2] tests: Test both legacy and new Exception(s) module API. Until now, only the legacy one was tested. --- inline-c-cpp/test/tests.hs | 60 ++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/inline-c-cpp/test/tests.hs b/inline-c-cpp/test/tests.hs index ab8ce1d..9008858 100644 --- a/inline-c-cpp/test/tests.hs +++ b/inline-c-cpp/test/tests.hs @@ -121,21 +121,26 @@ main = Hspec.hspec $ do throw std::runtime_error("C++ error message"); |] - result `shouldBeCppStdException` "Exception: C++ error message; type: std::runtime_error" + result `shouldBeCppStdException` ("C++ error message", Just "std::runtime_error") + result `shouldBeLegacyCppStdException` "Exception: C++ error message; type: std::runtime_error" + -- Test that we don't accidentally mess up formatting: + result `shouldBeShownException` "CppStdException e \"C++ error message\" (Just \"std::runtime_error\")" Hspec.it "non-exceptions are caught (unsigned int)" $ do result <- try [C.catchBlock| throw 0xDEADBEEF; |] - result `shouldBeCppOtherException` (Just "unsigned int") + result `shouldBeCppNonStdException` (Just "unsigned int") + result `shouldBeLegacyCppOtherException` (Just "unsigned int") Hspec.it "non-exceptions are caught (void *)" $ do result <- try [C.catchBlock| throw (void *)0xDEADBEEF; |] - result `shouldBeCppOtherException` (Just "void*") + result `shouldBeCppNonStdException` (Just "void*") + result `shouldBeLegacyCppOtherException` (Just "void*") Hspec.it "non-exceptions are caught (std::string)" $ do result <- try [C.catchBlock| @@ -169,7 +174,8 @@ main = Hspec.hspec $ do } |] - result `shouldBeCppStdException` "Exception: C++ error message; type: std::runtime_error" + result `shouldBeCppStdException` ("C++ error message", Just "std::runtime_error") + result `shouldBeLegacyCppStdException` "Exception: C++ error message; type: std::runtime_error" Hspec.it "try and return without throwing (pure)" $ do result <- [C.tryBlock| int { @@ -195,7 +201,8 @@ main = Hspec.hspec $ do } |] - result `shouldBeCppStdException` "Exception: C++ error message; type: std::runtime_error" + result `shouldBeCppStdException` ("C++ error message", Just "std::runtime_error") + result `shouldBeLegacyCppStdException` "Exception: C++ error message; type: std::runtime_error" Hspec.it "catch without return (pure)" $ do result <- [C.tryBlock| void { @@ -203,7 +210,8 @@ main = Hspec.hspec $ do } |] - result `shouldBeCppStdException` "Exception: C++ error message; type: std::runtime_error" + result `shouldBeCppStdException` ("C++ error message", Just "std::runtime_error") + result `shouldBeLegacyCppStdException` "Exception: C++ error message; type: std::runtime_error" Hspec.it "try and return without throwing (throw)" $ do result :: Either C.CppException C.CInt <- try [C.throwBlock| int { @@ -229,7 +237,8 @@ main = Hspec.hspec $ do } |] - result `shouldBeCppStdException` "Exception: C++ error message; type: std::runtime_error" + result `shouldBeCppStdException` ("C++ error message", Just "std::runtime_error") + result `shouldBeLegacyCppStdException` "Exception: C++ error message; type: std::runtime_error" Hspec.it "return throwing Haskell" $ do let exc = toException $ userError "This is from Haskell" @@ -275,7 +284,8 @@ main = Hspec.hspec $ do } |] - result `shouldBeCppStdException` "Exception: C++ error message; type: std::runtime_error" + result `shouldBeCppStdException` ("C++ error message", Just "std::runtime_error") + result `shouldBeLegacyCppStdException` "Exception: C++ error message; type: std::runtime_error" Hspec.it "code without exceptions works normally" $ do result :: Either C.CppException C.CInt <- try $ C.withPtr_ $ \resPtr -> [C.catchBlock| @@ -368,19 +378,37 @@ main = Hspec.hspec $ do tag :: C.CppException -> String tag (C.CppStdException {}) = "CppStdException" tag (C.CppHaskellException {}) = "CppHaskellException" -tag (Legacy.CppOtherException {}) = "CppStdException" +tag (C.CppNonStdException {}) = "CppNonStdException" -shouldBeCppStdException :: Either C.CppException a -> String -> IO () -shouldBeCppStdException (Left (Legacy.CppStdException actualMsg)) expectedMsg = do - actualMsg `Hspec.shouldBe` expectedMsg +shouldBeShownException :: Either C.CppException a -> String -> IO () +shouldBeShownException (Left e) expectedStr = show e `shouldBe` expectedStr +shouldBeShownException (Right _) _expectedStr = "Right _" `Hspec.shouldBe` "Left _" + +shouldBeCppStdException :: Either C.CppException a -> (ByteString, Maybe ByteString) -> IO () +shouldBeCppStdException (Left (C.CppStdException _ actualMsg actualType)) (expectedMsg, expectedType) = do + (actualMsg, actualType) `shouldBe` (expectedMsg, expectedType) shouldBeCppStdException (Left x) expectedMsg = tag x `Hspec.shouldBe` ("CppStdException " <> show expectedMsg) shouldBeCppStdException (Right _) expectedMsg = "Right _" `Hspec.shouldBe` ("Left (CppStdException " <> show expectedMsg <> ")") -shouldBeCppOtherException :: Either C.CppException a -> Maybe String -> IO () -shouldBeCppOtherException (Left (Legacy.CppOtherException actualType)) expectedType = do +-- | Tests that the old, deprecated exception's module and error messages still work. +shouldBeLegacyCppStdException :: Either Legacy.CppException a -> String -> IO () +shouldBeLegacyCppStdException (Left (Legacy.CppStdException actualMsg)) expectedMsg = do + actualMsg `Hspec.shouldBe` expectedMsg +shouldBeLegacyCppStdException (Left x) expectedMsg = tag x `Hspec.shouldBe` ("CppStdException " <> show expectedMsg) +shouldBeLegacyCppStdException (Right _) expectedMsg = "Right _" `Hspec.shouldBe` ("Left (CppStdException " <> show expectedMsg <> ")") + +shouldBeCppNonStdException :: Either C.CppException a -> Maybe ByteString -> IO () +shouldBeCppNonStdException (Left (C.CppNonStdException _ actualType)) expectedType = do + actualType `Hspec.shouldBe` expectedType +shouldBeCppNonStdException (Left x) expectedType = tag x `Hspec.shouldBe` ("CppOtherException " <> show expectedType) +shouldBeCppNonStdException (Right _) expectedType = "Right _" `Hspec.shouldBe` ("Left (CppOtherException " <> show expectedType <> ")") + +-- | Tests that the old, deprecated exception's module and error messages still work. +shouldBeLegacyCppOtherException :: Either Legacy.CppException a -> Maybe String -> IO () +shouldBeLegacyCppOtherException (Left (Legacy.CppOtherException actualType)) expectedType = do actualType `Hspec.shouldBe` expectedType -shouldBeCppOtherException (Left x) expectedType = tag x `Hspec.shouldBe` ("CppOtherException " <> show expectedType) -shouldBeCppOtherException (Right _) expectedType = "Right _" `Hspec.shouldBe` ("Left (CppOtherException " <> show expectedType <> ")") +shouldBeLegacyCppOtherException (Left x) expectedType = tag x `Hspec.shouldBe` ("CppOtherException " <> show expectedType) +shouldBeLegacyCppOtherException (Right _) expectedType = "Right _" `Hspec.shouldBe` ("Left (CppOtherException " <> show expectedType <> ")") shouldBeRight :: (Eq a, Show a) => Either C.CppException a -> a -> IO () shouldBeRight (Right actual) expected = actual `Hspec.shouldBe` expected