From 743ac30e349e181c26a2d2af0bcb93b0835ce521 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C5=91rinc?= Date: Sun, 1 Sep 2024 15:09:42 +0200 Subject: [PATCH 1/3] Add std::optional support to Boost's equality check Also moved the operators to the bottom of the file since they're less important and to group them together. Co-authored-by: Hodlinator <172445034+hodlinator@users.noreply.github.com> Co-authored-by: stickies-v --- src/test/util/setup_common.cpp | 33 +++++++++++++++------------------ src/test/util/setup_common.h | 31 +++++++++++++++++++++---------- 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 10363f22473..fa89ceb332a 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -78,24 +78,6 @@ constexpr inline auto TEST_DIR_PATH_ELEMENT{"test_common bitcoin"}; // Includes /** Random context to get unique temp data dirs. Separate from m_rng, which can be seeded from a const env var */ static FastRandomContext g_rng_temp_path; -std::ostream& operator<<(std::ostream& os, const arith_uint256& num) -{ - os << num.ToString(); - return os; -} - -std::ostream& operator<<(std::ostream& os, const uint160& num) -{ - os << num.ToString(); - return os; -} - -std::ostream& operator<<(std::ostream& os, const uint256& num) -{ - os << num.ToString(); - return os; -} - struct NetworkSetup { NetworkSetup() @@ -606,3 +588,18 @@ CBlock getBlock13b8a() stream >> TX_WITH_WITNESS(block); return block; } + +std::ostream& operator<<(std::ostream& os, const arith_uint256& num) +{ + return os << num.ToString(); +} + +std::ostream& operator<<(std::ostream& os, const uint160& num) +{ + return os << num.ToString(); +} + +std::ostream& operator<<(std::ostream& os, const uint256& num) +{ + return os << num.ToString(); +} diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h index a9a890b1a56..30d4280fa53 100644 --- a/src/test/util/setup_common.h +++ b/src/test/util/setup_common.h @@ -10,6 +10,8 @@ #include #include #include // IWYU pragma: export +#include +#include #include #include #include @@ -29,6 +31,8 @@ class arith_uint256; class CFeeRate; class Chainstate; class FastRandomContext; +class uint160; +class uint256; /** This is connected to the logger. Can be used to redirect logs to any other log */ extern const std::function G_TEST_LOG_FUN; @@ -39,15 +43,6 @@ extern const std::function()> G_TEST_COMMAND_LINE_ARGUM /** Retrieve the unit test name. */ extern const std::function G_TEST_GET_FULL_NAME; -// Enable BOOST_CHECK_EQUAL for enum class types -namespace std { -template -std::ostream& operator<<(typename std::enable_if::value, std::ostream>::type& stream, const T& e) -{ - return stream << static_cast::type>(e); -} -} // namespace std - static constexpr CAmount CENT{1000000}; struct TestOpts { @@ -250,10 +245,26 @@ std::unique_ptr MakeNoLogFileContext(const ChainType chain_type = ChainType:: CBlock getBlock13b8a(); -// Make types usable in BOOST_CHECK_* +// Make types usable in BOOST_CHECK_* @{ +namespace std { +template requires std::is_enum_v +inline std::ostream& operator<<(std::ostream& os, const T& e) +{ + return os << static_cast>(e); +} + +template +inline std::ostream& operator<<(std::ostream& os, const std::optional& v) +{ + return v ? os << *v + : os << "std::nullopt"; +} +} // namespace std + std::ostream& operator<<(std::ostream& os, const arith_uint256& num); std::ostream& operator<<(std::ostream& os, const uint160& num); std::ostream& operator<<(std::ostream& os, const uint256& num); +// @} /** * BOOST_CHECK_EXCEPTION predicates to check the specific validation error. From 19947863e16425e6a119e7a4819867292b1235ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C5=91rinc?= Date: Sun, 1 Sep 2024 15:09:48 +0200 Subject: [PATCH 2/3] Use BOOST_CHECK_EQUAL for optional, arith_uint256, uint256, uint160 Example error before: > unknown location:0: fatal error: in "validation_chainstatemanager_tests/chainstatemanager_args": std::bad_optional_access: bad_optional_access test/validation_chainstatemanager_tests.cpp:781: last checkpoint after: > test/validation_chainstatemanager_tests.cpp:801: error: in "validation_chainstatemanager_tests/chainstatemanager_args": check set_opts({"-assumevalid=0"}).assumed_valid_block == uint256::ZERO has failed [std::nullopt != 0000000000000000000000000000000000000000000000000000000000000000] Also added extra minimum_chainwork test to make it symmetric with assumevalid Co-authored-by: Ryan Ofsky Co-authored-by: Hodlinator <172445034+hodlinator@users.noreply.github.com> --- src/test/uint256_tests.cpp | 20 +++++++------- .../validation_chainstatemanager_tests.cpp | 26 +++++++++++-------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp index 8b76e0865a1..ef534b1b78f 100644 --- a/src/test/uint256_tests.cpp +++ b/src/test/uint256_tests.cpp @@ -395,15 +395,15 @@ BOOST_AUTO_TEST_CASE(from_hex) BOOST_AUTO_TEST_CASE(from_user_hex) { - BOOST_CHECK_EQUAL(uint256::FromUserHex("").value(), uint256::ZERO); - BOOST_CHECK_EQUAL(uint256::FromUserHex("0x").value(), uint256::ZERO); - BOOST_CHECK_EQUAL(uint256::FromUserHex("0").value(), uint256::ZERO); - BOOST_CHECK_EQUAL(uint256::FromUserHex("00").value(), uint256::ZERO); - BOOST_CHECK_EQUAL(uint256::FromUserHex("1").value(), uint256::ONE); - BOOST_CHECK_EQUAL(uint256::FromUserHex("0x10").value(), uint256{0x10}); - BOOST_CHECK_EQUAL(uint256::FromUserHex("10").value(), uint256{0x10}); - BOOST_CHECK_EQUAL(uint256::FromUserHex("0xFf").value(), uint256{0xff}); - BOOST_CHECK_EQUAL(uint256::FromUserHex("Ff").value(), uint256{0xff}); + BOOST_CHECK_EQUAL(uint256::FromUserHex(""), uint256::ZERO); + BOOST_CHECK_EQUAL(uint256::FromUserHex("0x"), uint256::ZERO); + BOOST_CHECK_EQUAL(uint256::FromUserHex("0"), uint256::ZERO); + BOOST_CHECK_EQUAL(uint256::FromUserHex("00"), uint256::ZERO); + BOOST_CHECK_EQUAL(uint256::FromUserHex("1"), uint256::ONE); + BOOST_CHECK_EQUAL(uint256::FromUserHex("0x10"), uint256{0x10}); + BOOST_CHECK_EQUAL(uint256::FromUserHex("10"), uint256{0x10}); + BOOST_CHECK_EQUAL(uint256::FromUserHex("0xFf"), uint256{0xff}); + BOOST_CHECK_EQUAL(uint256::FromUserHex("Ff"), uint256{0xff}); const std::string valid_hex_64{"0x0123456789abcdef0123456789abcdef0123456789ABDCEF0123456789ABCDEF"}; BOOST_REQUIRE_EQUAL(valid_hex_64.size(), 2 + 64); // 0x prefix and 64 hex digits BOOST_CHECK_EQUAL(uint256::FromUserHex(valid_hex_64.substr(2)).value().ToString(), ToLower(valid_hex_64.substr(2))); @@ -430,7 +430,7 @@ BOOST_AUTO_TEST_CASE( check_ONE ) BOOST_AUTO_TEST_CASE(FromHex_vs_uint256) { - auto runtime_uint{uint256::FromHex("4A5E1E4BAAB89F3A32518A88C31BC87F618f76673e2cc77ab2127b7afdeda33b").value()}; + auto runtime_uint{uint256::FromHex("4A5E1E4BAAB89F3A32518A88C31BC87F618f76673e2cc77ab2127b7afdeda33b")}; constexpr uint256 consteval_uint{ "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"}; BOOST_CHECK_EQUAL(consteval_uint, runtime_uint); } diff --git a/src/test/validation_chainstatemanager_tests.cpp b/src/test/validation_chainstatemanager_tests.cpp index b07c70e1070..b4fcfbd8537 100644 --- a/src/test/validation_chainstatemanager_tests.cpp +++ b/src/test/validation_chainstatemanager_tests.cpp @@ -806,22 +806,26 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_args, BasicTestingSetup) }; // test -assumevalid - BOOST_CHECK(!get_valid_opts({}).assumed_valid_block.has_value()); - BOOST_CHECK(get_valid_opts({"-assumevalid="}).assumed_valid_block.value().IsNull()); - BOOST_CHECK(get_valid_opts({"-assumevalid=0"}).assumed_valid_block.value().IsNull()); - BOOST_CHECK(get_valid_opts({"-noassumevalid"}).assumed_valid_block.value().IsNull()); - BOOST_CHECK_EQUAL(get_valid_opts({"-assumevalid=0x1234"}).assumed_valid_block.value().ToString(), std::string(60, '0') + "1234"); - const std::string cmd{"-assumevalid=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}; - BOOST_CHECK_EQUAL(get_valid_opts({cmd.c_str()}).assumed_valid_block.value().ToString(), cmd.substr(13, cmd.size())); + BOOST_CHECK(!get_valid_opts({}).assumed_valid_block); + BOOST_CHECK_EQUAL(get_valid_opts({"-assumevalid="}).assumed_valid_block, uint256::ZERO); + BOOST_CHECK_EQUAL(get_valid_opts({"-assumevalid=0"}).assumed_valid_block, uint256::ZERO); + BOOST_CHECK_EQUAL(get_valid_opts({"-noassumevalid"}).assumed_valid_block, uint256::ZERO); + BOOST_CHECK_EQUAL(get_valid_opts({"-assumevalid=0x12"}).assumed_valid_block, uint256{0x12}); + + std::string assume_valid{"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}; + BOOST_CHECK_EQUAL(get_valid_opts({("-assumevalid=" + assume_valid).c_str()}).assumed_valid_block, uint256::FromHex(assume_valid)); BOOST_CHECK(!get_opts({"-assumevalid=xyz"})); // invalid hex characters BOOST_CHECK(!get_opts({"-assumevalid=01234567890123456789012345678901234567890123456789012345678901234"})); // > 64 hex chars // test -minimumchainwork - BOOST_CHECK(!get_valid_opts({}).minimum_chain_work.has_value()); - BOOST_CHECK_EQUAL(get_valid_opts({"-minimumchainwork=0"}).minimum_chain_work.value().GetCompact(), 0U); - BOOST_CHECK_EQUAL(get_valid_opts({"-nominimumchainwork"}).minimum_chain_work.value().GetCompact(), 0U); - BOOST_CHECK_EQUAL(get_valid_opts({"-minimumchainwork=0x1234"}).minimum_chain_work.value().GetCompact(), 0x02123400U); + BOOST_CHECK(!get_valid_opts({}).minimum_chain_work); + BOOST_CHECK_EQUAL(get_valid_opts({"-minimumchainwork=0"}).minimum_chain_work, arith_uint256()); + BOOST_CHECK_EQUAL(get_valid_opts({"-nominimumchainwork"}).minimum_chain_work, arith_uint256()); + BOOST_CHECK_EQUAL(get_valid_opts({"-minimumchainwork=0x1234"}).minimum_chain_work, arith_uint256{0x1234}); + + std::string minimum_chainwork{"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}; + BOOST_CHECK_EQUAL(get_valid_opts({("-minimumchainwork=" + minimum_chainwork).c_str()}).minimum_chain_work, UintToArith256(uint256::FromHex(minimum_chainwork).value())); BOOST_CHECK(!get_opts({"-minimumchainwork=xyz"})); // invalid hex characters BOOST_CHECK(!get_opts({"-minimumchainwork=01234567890123456789012345678901234567890123456789012345678901234"})); // > 64 hex chars From 1eac96a503b6bac3eaf5d0eb3d23ffde3bfbf9aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C5=91rinc?= Date: Wed, 28 Aug 2024 23:19:21 +0200 Subject: [PATCH 3/3] Compare FromUserHex result against other hex validators and parsers --- src/test/fuzz/hex.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/test/fuzz/hex.cpp b/src/test/fuzz/hex.cpp index 964e30cc7e8..70c5690d8e4 100644 --- a/src/test/fuzz/hex.cpp +++ b/src/test/fuzz/hex.cpp @@ -35,7 +35,13 @@ FUZZ_TARGET(hex) assert(uint256::FromUserHex(random_hex_string)); } if (const auto result{uint256::FromUserHex(random_hex_string)}) { - assert(uint256::FromHex(result->ToString())); + const auto result_string{result->ToString()}; // ToString() returns a fixed-length string without "0x" prefix + assert(result_string.length() == 64); + assert(IsHex(result_string)); + assert(TryParseHex(result_string)); + assert(Txid::FromHex(result_string)); + assert(Wtxid::FromHex(result_string)); + assert(uint256::FromHex(result_string)); } (void)uint256S(random_hex_string); try {