From 533013cba20664e3581a8e4633cc188d5be3175a Mon Sep 17 00:00:00 2001 From: Hodlinator <172445034+hodlinator@users.noreply.github.com> Date: Fri, 6 Dec 2024 16:08:34 +0100 Subject: [PATCH] test: Prove+document ConstevalFormatString/tinyformat parity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lőrinc Co-Authored-By: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Co-Authored-By: Ryan Ofsky --- src/test/util_string_tests.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/test/util_string_tests.cpp b/src/test/util_string_tests.cpp index eaf179f6400..d90539af47a 100644 --- a/src/test/util_string_tests.cpp +++ b/src/test/util_string_tests.cpp @@ -12,6 +12,14 @@ using util::detail::CheckNumFormatSpecifiers; BOOST_AUTO_TEST_SUITE(util_string_tests) +template +void TfmFormatZeroes(const std::string& fmt) +{ + std::apply([&](auto... args) { + (void)tfm::format(fmt, args...); + }, std::array{}); +} + // Helper to allow compile-time sanity checks while providing the number of // args directly. Normally PassFmt would be used. template @@ -19,6 +27,12 @@ void PassFmt(ConstevalFormatString fmt) { // Execute compile-time check again at run-time to get code coverage stats BOOST_CHECK_NO_THROW(CheckNumFormatSpecifiers(fmt.fmt)); + + // If ConstevalFormatString didn't throw above, make sure tinyformat doesn't + // throw either for the same format string and parameter count combination. + // Proves that we have some extent of protection from runtime errors + // (tinyformat may still throw for some type mismatches). + BOOST_CHECK_NO_THROW(TfmFormatZeroes(fmt.fmt)); } template void FailFmtWithError(const char* wrong_fmt, std::string_view error) @@ -111,6 +125,15 @@ BOOST_AUTO_TEST_CASE(ConstevalFormatString_NumSpec) FailFmtWithError<2>("%1$*2$", err_term); FailFmtWithError<2>("%1$.*2$", err_term); FailFmtWithError<2>("%1$9.*2$", err_term); + + // Ensure that tinyformat throws if format string contains wrong number + // of specifiers. PassFmt relies on this to verify tinyformat successfully + // formats the strings, and will need to be updated if tinyformat is changed + // not to throw on failure. + BOOST_CHECK_EXCEPTION(TfmFormatZeroes<2>("%s"), tfm::format_error, + HasReason{"tinyformat: Not enough conversion specifiers in format string"}); + BOOST_CHECK_EXCEPTION(TfmFormatZeroes<1>("%s %s"), tfm::format_error, + HasReason{"tinyformat: Too many conversion specifiers in format string"}); } BOOST_AUTO_TEST_SUITE_END()