Currently, the unit tests use different boost check macros. However, this is problematic:
- The check macros are tied to the boost test framework and can not be used in other tests, such as the fuzz tests.
- The check macros are not overflow-safe. For example
BOOST_CHECK_GT(-10, 10U);compiles and passes fine, even though it is obviously wrong. - The check macros are not thread-safe. Using them in a thread will compile fine, but then fail tsan later on. Usually it is trivial to replace them by a plain
assert, but it would be better if the macros just worked under tsan. - The check macros are not fast-failing. This is confusing, as the test continues to run and will print more logs, making it harder to spot the first failure. Also, it is contrary to the internal check macros
assertandAssert, and evenCHECK_NONFATALunder debug mode, which all lead to an immediate abort.
Fix all issues by adding new check macros: ASSERT, ASSERT_EQ (and friends), ASSERT_EQ_COLLECTIONS (C++20 range-based), as well as ASSERT_EXCEPTION. They can be used as a drop-in replacement for the corresponding boost macro.
The implementation for all macros is only ~150 LOC, so it should be preferable to any external dependency addressing the above issues (which I couldn't find anyway).
Note on naming (why ASSERT?)
The test macros follow the naming and semantics of the internal Bitcoin Core macros (assert, and Assert). While it may confusing to have three unary assert macros that do roughly the same, it should be harmless and any macro that compiles is fine to use. (There is a special edge case to Assert, which allows to be turned into an exception as part of g_detail_test_only_CheckFailuresAreExceptionsNotAborts, but this shouldn't matter much).
In theory, if devs didn't care about nice diagnostic messages on a failure (printing the left and right side), the macros could even be a direct alias of assert or Assert, reducing the LOC even more. Though, I think it is fine and preferable to have slightly better failure messages in tests.
Also, the naming and semantics follow the Bitcoin Core functional test macros, which also start with assert_.
Later optimizations
The macros are currently sitting in the header, but once they are applied to the whole codebase, the pretty-printing implementation can move to a cpp file, which reduces the weight of the header and makes it possible to change or add pretty-printing features without a whole re-compilation of all tests.