From c03b392bcccf827835bb4d9188881619e5142889 Mon Sep 17 00:00:00 2001 From: hashlag Date: Sun, 2 Aug 2026 03:06:27 +0300 Subject: [PATCH] Improve negative assertions by checking the actual exceptions' content. --- ChaosTests/CMakeLists.txt | 1 + ChaosTests/Cipher/Arc4CryptTests.cpp | 14 ++- ChaosTests/Cipher/Arc4GenTests.cpp | 85 +++++++++++++++--- ChaosTests/Cipher/DesCryptTests.cpp | 17 +++- ChaosTests/Cipher/EcbModeTests.cpp | 109 ++++++++++++++++++----- ChaosTests/Mac/HmacTests.cpp | 14 ++- ChaosTests/Padding/PadderPkcs7Tests.cpp | 19 +++- ChaosTests/TestHelpers/AssertThrowEx.hpp | 34 +++++++ 8 files changed, 247 insertions(+), 46 deletions(-) create mode 100644 ChaosTests/TestHelpers/AssertThrowEx.hpp diff --git a/ChaosTests/CMakeLists.txt b/ChaosTests/CMakeLists.txt index b85d788..062ff50 100644 --- a/ChaosTests/CMakeLists.txt +++ b/ChaosTests/CMakeLists.txt @@ -28,6 +28,7 @@ add_executable(ChaosTests ${ChaosTests_SOURCE}) target_link_libraries(ChaosTests gtest gtest_main) target_include_directories(ChaosTests PRIVATE $ + $ ) target_compile_options(ChaosTests PRIVATE -Wunused -Werror=unused) diff --git a/ChaosTests/Cipher/Arc4CryptTests.cpp b/ChaosTests/Cipher/Arc4CryptTests.cpp index 8453504..4f3a32d 100644 --- a/ChaosTests/Cipher/Arc4CryptTests.cpp +++ b/ChaosTests/Cipher/Arc4CryptTests.cpp @@ -1,4 +1,5 @@ #include +#include "TestHelpers/AssertThrowEx.hpp" #include #include #include @@ -62,8 +63,17 @@ TEST(Arc4CryptTests, UninitializedArc4CryptTest) std::array in = {}; std::array out = {}; - ASSERT_THROW(arc4.Encrypt(out.begin(), in.begin(), in.size()), Chaos::Service::ChaosException); - ASSERT_THROW(arc4.Decrypt(out.begin(), in.begin(), in.size()), Chaos::Service::ChaosException); + ASSERT_THROW_EX(arc4.Encrypt(out.begin(), in.begin(), in.size()), + Chaos::Service::ChaosException, + { + ASSERT_EQ("Arc4Crypt: not initialized", ex.GetMessage()); + }); + + ASSERT_THROW_EX(arc4.Decrypt(out.begin(), in.begin(), in.size()), + Chaos::Service::ChaosException, + { + ASSERT_EQ("Arc4Crypt: not initialized", ex.GetMessage()); + }); } } diff --git a/ChaosTests/Cipher/Arc4GenTests.cpp b/ChaosTests/Cipher/Arc4GenTests.cpp index 81fe1b1..72ecc61 100644 --- a/ChaosTests/Cipher/Arc4GenTests.cpp +++ b/ChaosTests/Cipher/Arc4GenTests.cpp @@ -1,4 +1,5 @@ #include +#include "TestHelpers/AssertThrowEx.hpp" #include #include #include @@ -322,9 +323,17 @@ TEST(Arc4GenTests, TooSmallKeyTest) const char * key = "smal"; Arc4Gen gen; - ASSERT_THROW(gen.Rekey(key, key + strlen(key)), Chaos::Service::ChaosException); + ASSERT_THROW_EX(gen.Rekey(key, key + strlen(key)), + Chaos::Service::ChaosException, + { + ASSERT_EQ("Arc4Gen: key is too small", ex.GetMessage()); + }); - ASSERT_THROW(Arc4Gen(key, key + strlen(key)), Chaos::Service::ChaosException); + ASSERT_THROW_EX(Arc4Gen(key, key + strlen(key)), + Chaos::Service::ChaosException, + { + ASSERT_EQ("Arc4Gen: key is too small", ex.GetMessage()); + }); } } @@ -335,12 +344,35 @@ TEST(Arc4GenTests, UninitializedGenTest) { Arc4Gen gen; - ASSERT_THROW(gen.Generate(out.begin(), out.size()), Chaos::Service::ChaosException); + ASSERT_THROW_EX(gen.Generate(out.begin(), out.size()), + Chaos::Service::ChaosException, + { + ASSERT_EQ("Arc4Gen: not initialized", ex.GetMessage()); + }); - ASSERT_THROW(gen.Drop(0), Chaos::Service::ChaosException); - ASSERT_THROW(gen.Drop(1), Chaos::Service::ChaosException); - ASSERT_THROW(gen.Drop(20), Chaos::Service::ChaosException); - ASSERT_THROW(gen.Drop(256), Chaos::Service::ChaosException); + ASSERT_THROW_EX(gen.Drop(0), + Chaos::Service::ChaosException, + { + ASSERT_EQ("Arc4Gen: not initialized", ex.GetMessage()); + }); + + ASSERT_THROW_EX(gen.Drop(1), + Chaos::Service::ChaosException, + { + ASSERT_EQ("Arc4Gen: not initialized", ex.GetMessage()); + }); + + ASSERT_THROW_EX(gen.Drop(20), + Chaos::Service::ChaosException, + { + ASSERT_EQ("Arc4Gen: not initialized", ex.GetMessage()); + }); + + ASSERT_THROW_EX(gen.Drop(256), + Chaos::Service::ChaosException, + { + ASSERT_EQ("Arc4Gen: not initialized", ex.GetMessage()); + }); } { @@ -348,14 +380,41 @@ TEST(Arc4GenTests, UninitializedGenTest) Arc4Gen gen; - ASSERT_THROW(gen.Rekey(key, key + strlen(key)), Chaos::Service::ChaosException); + ASSERT_THROW_EX(gen.Rekey(key, key + strlen(key)), + Chaos::Service::ChaosException, + { + ASSERT_EQ("Arc4Gen: key is too small", ex.GetMessage()); + }); - ASSERT_THROW(gen.Generate(out.begin(), out.size()), Chaos::Service::ChaosException); + ASSERT_THROW_EX(gen.Generate(out.begin(), out.size()), + Chaos::Service::ChaosException, + { + ASSERT_EQ("Arc4Gen: not initialized", ex.GetMessage()); + }); - ASSERT_THROW(gen.Drop(0), Chaos::Service::ChaosException); - ASSERT_THROW(gen.Drop(1), Chaos::Service::ChaosException); - ASSERT_THROW(gen.Drop(20), Chaos::Service::ChaosException); - ASSERT_THROW(gen.Drop(256), Chaos::Service::ChaosException); + ASSERT_THROW_EX(gen.Drop(0), + Chaos::Service::ChaosException, + { + ASSERT_EQ("Arc4Gen: not initialized", ex.GetMessage()); + }); + + ASSERT_THROW_EX(gen.Drop(1), + Chaos::Service::ChaosException, + { + ASSERT_EQ("Arc4Gen: not initialized", ex.GetMessage()); + }); + + ASSERT_THROW_EX(gen.Drop(20), + Chaos::Service::ChaosException, + { + ASSERT_EQ("Arc4Gen: not initialized", ex.GetMessage()); + }); + + ASSERT_THROW_EX(gen.Drop(256), + Chaos::Service::ChaosException, + { + ASSERT_EQ("Arc4Gen: not initialized", ex.GetMessage()); + }); } } diff --git a/ChaosTests/Cipher/DesCryptTests.cpp b/ChaosTests/Cipher/DesCryptTests.cpp index 6d4e7f7..8a799e9 100644 --- a/ChaosTests/Cipher/DesCryptTests.cpp +++ b/ChaosTests/Cipher/DesCryptTests.cpp @@ -1,4 +1,5 @@ #include +#include "TestHelpers/AssertThrowEx.hpp" #include #include #include @@ -366,7 +367,13 @@ TEST(DesCryptTests, ShortKeyTest) { { std::array key = {}; - ASSERT_THROW(DesCrypt::Key(key.begin(), key.end()), Chaos::Service::ChaosException); + ASSERT_THROW_EX(DesCrypt::Key(key.begin(), key.end()), + Chaos::Service::ChaosException, + { + ASSERT_EQ("DesCrypt::Key: invalid key length " + "(8 bytes required)", + ex.GetMessage()); + }); } } @@ -374,7 +381,13 @@ TEST(DesCryptTests, LongKeyTest) { { std::array key = {}; - ASSERT_THROW(DesCrypt::Key(key.begin(), key.end()), Chaos::Service::ChaosException); + ASSERT_THROW_EX(DesCrypt::Key(key.begin(), key.end()), + Chaos::Service::ChaosException, + { + ASSERT_EQ("DesCrypt::Key: invalid key length " + "(8 bytes required)", + ex.GetMessage()); + }); } } diff --git a/ChaosTests/Cipher/EcbModeTests.cpp b/ChaosTests/Cipher/EcbModeTests.cpp index 9ee83e9..2b7fb8b 100644 --- a/ChaosTests/Cipher/EcbModeTests.cpp +++ b/ChaosTests/Cipher/EcbModeTests.cpp @@ -1,4 +1,5 @@ #include +#include "TestHelpers/AssertThrowEx.hpp" #include #include @@ -384,8 +385,12 @@ TEST(EcbModeTests, EncryptInsufficientBufferTest) EcbMode::Encryptor enc(desKey); - ASSERT_THROW(enc.Update(out.begin(), out.end(), data.begin(), data.end()), - Chaos::Service::ChaosException); + ASSERT_THROW_EX(enc.Update(out.begin(), out.end(), data.begin(), data.end()), + Chaos::Service::ChaosException, + { + ASSERT_EQ("EcbMode<>::Encryptor: insufficient output buffer size", + ex.GetMessage()); + }); } { @@ -394,8 +399,12 @@ TEST(EcbModeTests, EncryptInsufficientBufferTest) EcbMode::Encryptor enc(desKey); - ASSERT_THROW(enc.Update(out.begin(), out.end(), data.begin(), data.end()), - Chaos::Service::ChaosException); + ASSERT_THROW_EX(enc.Update(out.begin(), out.end(), data.begin(), data.end()), + Chaos::Service::ChaosException, + { + ASSERT_EQ("EcbMode<>::Encryptor: insufficient output buffer size", + ex.GetMessage()); + }); } { @@ -409,8 +418,12 @@ TEST(EcbModeTests, EncryptInsufficientBufferTest) enc.Update(out1.begin(), out1.end(), data1.begin(), data1.end()); - ASSERT_THROW(enc.Update(out2.begin(), out2.end(), data2.begin(), data2.end()), - Chaos::Service::ChaosException); + ASSERT_THROW_EX(enc.Update(out2.begin(), out2.end(), data2.begin(), data2.end()), + Chaos::Service::ChaosException, + { + ASSERT_EQ("EcbMode<>::Encryptor: insufficient output buffer size", + ex.GetMessage()); + }); } { @@ -421,8 +434,12 @@ TEST(EcbModeTests, EncryptInsufficientBufferTest) uint64_t written = enc.Update(out.begin(), out.end(), data.begin(), data.end()); - ASSERT_THROW(written += enc.Finish(out.begin() + written, out.end()), - Chaos::Service::ChaosException); + ASSERT_THROW_EX(written += enc.Finish(out.begin() + written, out.end()), + Chaos::Service::ChaosException, + { + ASSERT_EQ("EcbMode<>::Encryptor: insufficient output buffer size", + ex.GetMessage()); + }); } { @@ -433,8 +450,12 @@ TEST(EcbModeTests, EncryptInsufficientBufferTest) uint64_t written = enc.Update(out.begin(), out.end(), data.begin(), data.end()); - ASSERT_THROW(written += enc.Finish(out.begin() + written, out.end()), - Chaos::Service::ChaosException); + ASSERT_THROW_EX(written += enc.Finish(out.begin() + written, out.end()), + Chaos::Service::ChaosException, + { + ASSERT_EQ("EcbMode<>::Encryptor: insufficient output buffer size", + ex.GetMessage()); + }); } } @@ -826,8 +847,12 @@ TEST(EcbModeTests, DecryptInsufficientBufferTest) EcbMode::Decryptor dec(desKey); - ASSERT_THROW(dec.Update(out.begin(), out.end(), data.begin(), data.end()), - Chaos::Service::ChaosException); + ASSERT_THROW_EX(dec.Update(out.begin(), out.end(), data.begin(), data.end()), + Chaos::Service::ChaosException, + { + ASSERT_EQ("EcbMode<>::Decryptor: insufficient output buffer size", + ex.GetMessage()); + }); } { @@ -838,8 +863,12 @@ TEST(EcbModeTests, DecryptInsufficientBufferTest) EcbMode::Decryptor dec(desKey); - ASSERT_THROW(dec.Update(out.begin(), out.end(), data.begin(), data.end()), - Chaos::Service::ChaosException); + ASSERT_THROW_EX(dec.Update(out.begin(), out.end(), data.begin(), data.end()), + Chaos::Service::ChaosException, + { + ASSERT_EQ("EcbMode<>::Decryptor: insufficient output buffer size", + ex.GetMessage()); + }); } { @@ -855,8 +884,12 @@ TEST(EcbModeTests, DecryptInsufficientBufferTest) dec.Update(out1.begin(), out1.end(), data1.begin(), data1.end()); - ASSERT_THROW(dec.Update(out2.begin(), out2.end(), data2.begin(), data2.end()), - Chaos::Service::ChaosException); + ASSERT_THROW_EX(dec.Update(out2.begin(), out2.end(), data2.begin(), data2.end()), + Chaos::Service::ChaosException, + { + ASSERT_EQ("EcbMode<>::Decryptor: insufficient output buffer size", + ex.GetMessage()); + }); } { @@ -868,8 +901,12 @@ TEST(EcbModeTests, DecryptInsufficientBufferTest) uint64_t written = dec.Update(out.begin(), out.end(), data.begin(), data.end()); - ASSERT_THROW(written += dec.Finish(out.begin() + written, out.end()), - Chaos::Service::ChaosException); + ASSERT_THROW_EX(written += dec.Finish(out.begin() + written, out.end()), + Chaos::Service::ChaosException, + { + ASSERT_EQ("EcbMode<>::Decryptor: insufficient output buffer size", + ex.GetMessage()); + }); } { @@ -882,8 +919,12 @@ TEST(EcbModeTests, DecryptInsufficientBufferTest) uint64_t written = dec.Update(out.begin(), out.end(), data.begin(), data.end()); - ASSERT_THROW(written += dec.Finish(out.begin() + written, out.end()), - Chaos::Service::ChaosException); + ASSERT_THROW_EX(written += dec.Finish(out.begin() + written, out.end()), + Chaos::Service::ChaosException, + { + ASSERT_EQ("EcbMode<>::Decryptor: insufficient output buffer size", + ex.GetMessage()); + }); } } @@ -915,7 +956,13 @@ TEST(EcbModeTests, DecryptNotRoundSizeTest) std::vector data = { 0x64, 0x32, 0x13, 0xe7, 0x31, 0x06, 0xc6 }; std::vector key = { 0x28, 0x1c, 0xf3, 0x11, 0xce, 0xc6, 0xc2, 0x38 }; - ASSERT_THROW(ecbDec(data, key), Chaos::Service::ChaosException); + ASSERT_THROW_EX(ecbDec(data, key), Chaos::Service::ChaosException, + { + ASSERT_EQ("EcbMode<>::Decryptor: ciphertext size " + "is not a multiple of the algorithm's " + "block size", + ex.GetMessage()); + }); } { @@ -923,7 +970,13 @@ TEST(EcbModeTests, DecryptNotRoundSizeTest) 0xdc, 0x0d, 0x9f, 0x87 }; std::vector key = { 0x28, 0x1c, 0xf3, 0x11, 0xce, 0xc6, 0xc2, 0x38 }; - ASSERT_THROW(ecbDec(data, key), Chaos::Service::ChaosException); + ASSERT_THROW_EX(ecbDec(data, key), Chaos::Service::ChaosException, + { + ASSERT_EQ("EcbMode<>::Decryptor: ciphertext size " + "is not a multiple of the algorithm's " + "block size", + ex.GetMessage()); + }); } } @@ -955,7 +1008,11 @@ TEST(EcbModeTests, DecryptInvalidPaddingTest) std::vector data = { 0x60, 0xa7, 0x4b, 0x8c, 0x68, 0x03, 0x70, 0x0c }; std::vector key = { 0xaa, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf1, 0x12 }; - ASSERT_THROW(ecbDec(data, key), Chaos::Service::ChaosException); + ASSERT_THROW_EX(ecbDec(data, key), Chaos::Service::ChaosException, + { + ASSERT_EQ("EcbMode<>::Decryptor: invalid ciphertext", + ex.GetMessage()); + }); } { @@ -963,6 +1020,10 @@ TEST(EcbModeTests, DecryptInvalidPaddingTest) 0xbe, 0xd2, 0x51, 0x7e, 0x4f, 0x39, 0xfe, 0xa2 }; std::vector key = { 0xaa, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf1, 0x12 }; - ASSERT_THROW(ecbDec(data, key), Chaos::Service::ChaosException); + ASSERT_THROW_EX(ecbDec(data, key), Chaos::Service::ChaosException, + { + ASSERT_EQ("EcbMode<>::Decryptor: invalid ciphertext", + ex.GetMessage()); + }); } } diff --git a/ChaosTests/Mac/HmacTests.cpp b/ChaosTests/Mac/HmacTests.cpp index 7882697..0e53532 100644 --- a/ChaosTests/Mac/HmacTests.cpp +++ b/ChaosTests/Mac/HmacTests.cpp @@ -1,4 +1,5 @@ #include +#include "TestHelpers/AssertThrowEx.hpp" #include #include #include @@ -108,7 +109,16 @@ TEST(HmacTests, UninitializedHmacTest) { Hmac hmac; - ASSERT_THROW(hmac.Update(in.begin(), in.end()), Chaos::Service::ChaosException); - ASSERT_THROW(hmac.Finish(), Chaos::Service::ChaosException); + ASSERT_THROW_EX(hmac.Update(in.begin(), in.end()), + Chaos::Service::ChaosException, + { + ASSERT_EQ("Hmac: not initialized", ex.GetMessage()); + }); + + ASSERT_THROW_EX(hmac.Finish(), + Chaos::Service::ChaosException, + { + ASSERT_EQ("Hmac: not initialized", ex.GetMessage()); + }); } } diff --git a/ChaosTests/Padding/PadderPkcs7Tests.cpp b/ChaosTests/Padding/PadderPkcs7Tests.cpp index 0e656e7..3eaa731 100644 --- a/ChaosTests/Padding/PadderPkcs7Tests.cpp +++ b/ChaosTests/Padding/PadderPkcs7Tests.cpp @@ -1,4 +1,5 @@ #include +#include "TestHelpers/AssertThrowEx.hpp" #include #include #include @@ -57,19 +58,31 @@ TEST(PadPkcs7Tests, PadInvalidRangeTest) { std::array out = {}; - ASSERT_THROW(PadderPkcs7::Pad(out.begin(), out.end()), Chaos::Service::ChaosException); + ASSERT_THROW_EX(PadderPkcs7::Pad(out.begin(), out.end()), + Chaos::Service::ChaosException, + { + ASSERT_EQ("PadderPkcs7::Pad(): invalid range", ex.GetMessage()); + }); } { std::array out = {}; - ASSERT_THROW(PadderPkcs7::Pad(out.begin(), out.end()), Chaos::Service::ChaosException); + ASSERT_THROW_EX(PadderPkcs7::Pad(out.begin(), out.end()), + Chaos::Service::ChaosException, + { + ASSERT_EQ("PadderPkcs7::Pad(): invalid range", ex.GetMessage()); + }); } { std::array out = {}; - ASSERT_THROW(PadderPkcs7::Pad(out.end(), out.begin()), Chaos::Service::ChaosException); + ASSERT_THROW_EX(PadderPkcs7::Pad(out.end(), out.begin()), + Chaos::Service::ChaosException, + { + ASSERT_EQ("PadderPkcs7::Pad(): invalid range", ex.GetMessage()); + }); } } diff --git a/ChaosTests/TestHelpers/AssertThrowEx.hpp b/ChaosTests/TestHelpers/AssertThrowEx.hpp new file mode 100644 index 0000000..169510b --- /dev/null +++ b/ChaosTests/TestHelpers/AssertThrowEx.hpp @@ -0,0 +1,34 @@ +#ifndef CHAOSTESTS_TESTHELPERS_ASSERTTHROWEX_HPP +#define CHAOSTESTS_TESTHELPERS_ASSERTTHROWEX_HPP + +#include + +#define ASSERT_THROW_EX(statement, expected_exception_type, assertions) \ + do \ + { \ + bool ASSERT_THROW_EX_expectedExceptionThrown = false; \ + \ + try \ + { \ + statement; \ + } \ + catch (const expected_exception_type & ex) \ + { \ + ASSERT_THROW_EX_expectedExceptionThrown = true; \ + assertions; \ + } \ + catch (...) \ + { \ + FAIL() << "Expected: " << #statement << " throws an exception of type " \ + << #expected_exception_type << ".\n Actual: it throws a different type."; \ + } \ + \ + if (!ASSERT_THROW_EX_expectedExceptionThrown) \ + { \ + FAIL() << "Expected: " << #statement << " throws an exception of type " \ + << #expected_exception_type << ".\n Actual: it throws nothing."; \ + } \ + } \ + while (false) + +#endif // CHAOSTESTS_TESTHELPERS_ASSERTTHROWEX_HPP