Skip to content

Commit be768db

Browse files
committed
Merge bitcoin/bitcoin#30618: test: support std::optional in BOOST_CHECK_* and increase FromUserHex fuzz feature coverage
1eac96a Compare FromUserHex result against other hex validators and parsers (Lőrinc) 1994786 Use BOOST_CHECK_EQUAL for optional, arith_uint256, uint256, uint160 (Lőrinc) 743ac30 Add std::optional support to Boost's equality check (Lőrinc) Pull request description: Enhanced `FromUserHex` coverage by: * Added `std::optional` support to `BOOST_CHECK_EQUAL`, allowing direct comparisons of `std::optional<T>` with other `T` expected values. * Increased fuzz testing for hex parsing to validate against other hex validators and parsers. ---- * Use BOOST_CHECK_EQUAL for bitcoin/bitcoin#30569 (comment) 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] ACKs for top commit: stickies-v: re-ACK 1eac96a ryanofsky: Code review ACK 1eac96a. Only changes since last review were auto type and fuzz test tweaks. hodlinator: ACK 1eac96a Tree-SHA512: f1d2c65f0ee4e97830700be5b330189207b11ed0c89a8cebf0f97d43308402a6b3732e10130c79a0c044f7d2eeabfb5359990825aadf02c4ec19428dcd982b00
2 parents 07c7c96 + 1eac96a commit be768db

File tree

5 files changed

+68
-50
lines changed

5 files changed

+68
-50
lines changed

src/test/fuzz/hex.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,13 @@ FUZZ_TARGET(hex)
3535
assert(uint256::FromUserHex(random_hex_string));
3636
}
3737
if (const auto result{uint256::FromUserHex(random_hex_string)}) {
38-
assert(uint256::FromHex(result->ToString()));
38+
const auto result_string{result->ToString()}; // ToString() returns a fixed-length string without "0x" prefix
39+
assert(result_string.length() == 64);
40+
assert(IsHex(result_string));
41+
assert(TryParseHex(result_string));
42+
assert(Txid::FromHex(result_string));
43+
assert(Wtxid::FromHex(result_string));
44+
assert(uint256::FromHex(result_string));
3945
}
4046
try {
4147
(void)HexToPubKey(random_hex_string);

src/test/uint256_tests.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -299,15 +299,15 @@ BOOST_AUTO_TEST_CASE(from_hex)
299299

300300
BOOST_AUTO_TEST_CASE(from_user_hex)
301301
{
302-
BOOST_CHECK_EQUAL(uint256::FromUserHex("").value(), uint256::ZERO);
303-
BOOST_CHECK_EQUAL(uint256::FromUserHex("0x").value(), uint256::ZERO);
304-
BOOST_CHECK_EQUAL(uint256::FromUserHex("0").value(), uint256::ZERO);
305-
BOOST_CHECK_EQUAL(uint256::FromUserHex("00").value(), uint256::ZERO);
306-
BOOST_CHECK_EQUAL(uint256::FromUserHex("1").value(), uint256::ONE);
307-
BOOST_CHECK_EQUAL(uint256::FromUserHex("0x10").value(), uint256{0x10});
308-
BOOST_CHECK_EQUAL(uint256::FromUserHex("10").value(), uint256{0x10});
309-
BOOST_CHECK_EQUAL(uint256::FromUserHex("0xFf").value(), uint256{0xff});
310-
BOOST_CHECK_EQUAL(uint256::FromUserHex("Ff").value(), uint256{0xff});
302+
BOOST_CHECK_EQUAL(uint256::FromUserHex(""), uint256::ZERO);
303+
BOOST_CHECK_EQUAL(uint256::FromUserHex("0x"), uint256::ZERO);
304+
BOOST_CHECK_EQUAL(uint256::FromUserHex("0"), uint256::ZERO);
305+
BOOST_CHECK_EQUAL(uint256::FromUserHex("00"), uint256::ZERO);
306+
BOOST_CHECK_EQUAL(uint256::FromUserHex("1"), uint256::ONE);
307+
BOOST_CHECK_EQUAL(uint256::FromUserHex("0x10"), uint256{0x10});
308+
BOOST_CHECK_EQUAL(uint256::FromUserHex("10"), uint256{0x10});
309+
BOOST_CHECK_EQUAL(uint256::FromUserHex("0xFf"), uint256{0xff});
310+
BOOST_CHECK_EQUAL(uint256::FromUserHex("Ff"), uint256{0xff});
311311
const std::string valid_hex_64{"0x0123456789abcdef0123456789abcdef0123456789ABDCEF0123456789ABCDEF"};
312312
BOOST_REQUIRE_EQUAL(valid_hex_64.size(), 2 + 64); // 0x prefix and 64 hex digits
313313
BOOST_CHECK_EQUAL(uint256::FromUserHex(valid_hex_64.substr(2)).value().ToString(), ToLower(valid_hex_64.substr(2)));
@@ -334,7 +334,7 @@ BOOST_AUTO_TEST_CASE( check_ONE )
334334

335335
BOOST_AUTO_TEST_CASE(FromHex_vs_uint256)
336336
{
337-
auto runtime_uint{uint256::FromHex("4A5E1E4BAAB89F3A32518A88C31BC87F618f76673e2cc77ab2127b7afdeda33b").value()};
337+
auto runtime_uint{uint256::FromHex("4A5E1E4BAAB89F3A32518A88C31BC87F618f76673e2cc77ab2127b7afdeda33b")};
338338
constexpr uint256 consteval_uint{ "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"};
339339
BOOST_CHECK_EQUAL(consteval_uint, runtime_uint);
340340
}

src/test/util/setup_common.cpp

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -78,24 +78,6 @@ constexpr inline auto TEST_DIR_PATH_ELEMENT{"test_common bitcoin"}; // Includes
7878
/** Random context to get unique temp data dirs. Separate from m_rng, which can be seeded from a const env var */
7979
static FastRandomContext g_rng_temp_path;
8080

81-
std::ostream& operator<<(std::ostream& os, const arith_uint256& num)
82-
{
83-
os << num.ToString();
84-
return os;
85-
}
86-
87-
std::ostream& operator<<(std::ostream& os, const uint160& num)
88-
{
89-
os << num.ToString();
90-
return os;
91-
}
92-
93-
std::ostream& operator<<(std::ostream& os, const uint256& num)
94-
{
95-
os << num.ToString();
96-
return os;
97-
}
98-
9981
struct NetworkSetup
10082
{
10183
NetworkSetup()
@@ -606,3 +588,18 @@ CBlock getBlock13b8a()
606588
stream >> TX_WITH_WITNESS(block);
607589
return block;
608590
}
591+
592+
std::ostream& operator<<(std::ostream& os, const arith_uint256& num)
593+
{
594+
return os << num.ToString();
595+
}
596+
597+
std::ostream& operator<<(std::ostream& os, const uint160& num)
598+
{
599+
return os << num.ToString();
600+
}
601+
602+
std::ostream& operator<<(std::ostream& os, const uint256& num)
603+
{
604+
return os << num.ToString();
605+
}

src/test/util/setup_common.h

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include <key.h>
1111
#include <node/caches.h>
1212
#include <node/context.h> // IWYU pragma: export
13+
#include <optional>
14+
#include <ostream>
1315
#include <primitives/transaction.h>
1416
#include <pubkey.h>
1517
#include <stdexcept>
@@ -29,6 +31,8 @@ class arith_uint256;
2931
class CFeeRate;
3032
class Chainstate;
3133
class FastRandomContext;
34+
class uint160;
35+
class uint256;
3236

3337
/** This is connected to the logger. Can be used to redirect logs to any other log */
3438
extern const std::function<void(const std::string&)> G_TEST_LOG_FUN;
@@ -39,15 +43,6 @@ extern const std::function<std::vector<const char*>()> G_TEST_COMMAND_LINE_ARGUM
3943
/** Retrieve the unit test name. */
4044
extern const std::function<std::string()> G_TEST_GET_FULL_NAME;
4145

42-
// Enable BOOST_CHECK_EQUAL for enum class types
43-
namespace std {
44-
template <typename T>
45-
std::ostream& operator<<(typename std::enable_if<std::is_enum<T>::value, std::ostream>::type& stream, const T& e)
46-
{
47-
return stream << static_cast<typename std::underlying_type<T>::type>(e);
48-
}
49-
} // namespace std
50-
5146
static constexpr CAmount CENT{1000000};
5247

5348
struct TestOpts {
@@ -250,10 +245,26 @@ std::unique_ptr<T> MakeNoLogFileContext(const ChainType chain_type = ChainType::
250245

251246
CBlock getBlock13b8a();
252247

253-
// Make types usable in BOOST_CHECK_*
248+
// Make types usable in BOOST_CHECK_* @{
249+
namespace std {
250+
template <typename T> requires std::is_enum_v<T>
251+
inline std::ostream& operator<<(std::ostream& os, const T& e)
252+
{
253+
return os << static_cast<std::underlying_type_t<T>>(e);
254+
}
255+
256+
template <typename T>
257+
inline std::ostream& operator<<(std::ostream& os, const std::optional<T>& v)
258+
{
259+
return v ? os << *v
260+
: os << "std::nullopt";
261+
}
262+
} // namespace std
263+
254264
std::ostream& operator<<(std::ostream& os, const arith_uint256& num);
255265
std::ostream& operator<<(std::ostream& os, const uint160& num);
256266
std::ostream& operator<<(std::ostream& os, const uint256& num);
267+
// @}
257268

258269
/**
259270
* BOOST_CHECK_EXCEPTION predicates to check the specific validation error.

src/test/validation_chainstatemanager_tests.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -806,22 +806,26 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_args, BasicTestingSetup)
806806
};
807807

808808
// test -assumevalid
809-
BOOST_CHECK(!get_valid_opts({}).assumed_valid_block.has_value());
810-
BOOST_CHECK(get_valid_opts({"-assumevalid="}).assumed_valid_block.value().IsNull());
811-
BOOST_CHECK(get_valid_opts({"-assumevalid=0"}).assumed_valid_block.value().IsNull());
812-
BOOST_CHECK(get_valid_opts({"-noassumevalid"}).assumed_valid_block.value().IsNull());
813-
BOOST_CHECK_EQUAL(get_valid_opts({"-assumevalid=0x1234"}).assumed_valid_block.value().ToString(), std::string(60, '0') + "1234");
814-
const std::string cmd{"-assumevalid=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"};
815-
BOOST_CHECK_EQUAL(get_valid_opts({cmd.c_str()}).assumed_valid_block.value().ToString(), cmd.substr(13, cmd.size()));
809+
BOOST_CHECK(!get_valid_opts({}).assumed_valid_block);
810+
BOOST_CHECK_EQUAL(get_valid_opts({"-assumevalid="}).assumed_valid_block, uint256::ZERO);
811+
BOOST_CHECK_EQUAL(get_valid_opts({"-assumevalid=0"}).assumed_valid_block, uint256::ZERO);
812+
BOOST_CHECK_EQUAL(get_valid_opts({"-noassumevalid"}).assumed_valid_block, uint256::ZERO);
813+
BOOST_CHECK_EQUAL(get_valid_opts({"-assumevalid=0x12"}).assumed_valid_block, uint256{0x12});
814+
815+
std::string assume_valid{"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"};
816+
BOOST_CHECK_EQUAL(get_valid_opts({("-assumevalid=" + assume_valid).c_str()}).assumed_valid_block, uint256::FromHex(assume_valid));
816817

817818
BOOST_CHECK(!get_opts({"-assumevalid=xyz"})); // invalid hex characters
818819
BOOST_CHECK(!get_opts({"-assumevalid=01234567890123456789012345678901234567890123456789012345678901234"})); // > 64 hex chars
819820

820821
// test -minimumchainwork
821-
BOOST_CHECK(!get_valid_opts({}).minimum_chain_work.has_value());
822-
BOOST_CHECK_EQUAL(get_valid_opts({"-minimumchainwork=0"}).minimum_chain_work.value().GetCompact(), 0U);
823-
BOOST_CHECK_EQUAL(get_valid_opts({"-nominimumchainwork"}).minimum_chain_work.value().GetCompact(), 0U);
824-
BOOST_CHECK_EQUAL(get_valid_opts({"-minimumchainwork=0x1234"}).minimum_chain_work.value().GetCompact(), 0x02123400U);
822+
BOOST_CHECK(!get_valid_opts({}).minimum_chain_work);
823+
BOOST_CHECK_EQUAL(get_valid_opts({"-minimumchainwork=0"}).minimum_chain_work, arith_uint256());
824+
BOOST_CHECK_EQUAL(get_valid_opts({"-nominimumchainwork"}).minimum_chain_work, arith_uint256());
825+
BOOST_CHECK_EQUAL(get_valid_opts({"-minimumchainwork=0x1234"}).minimum_chain_work, arith_uint256{0x1234});
826+
827+
std::string minimum_chainwork{"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"};
828+
BOOST_CHECK_EQUAL(get_valid_opts({("-minimumchainwork=" + minimum_chainwork).c_str()}).minimum_chain_work, UintToArith256(uint256::FromHex(minimum_chainwork).value()));
825829

826830
BOOST_CHECK(!get_opts({"-minimumchainwork=xyz"})); // invalid hex characters
827831
BOOST_CHECK(!get_opts({"-minimumchainwork=01234567890123456789012345678901234567890123456789012345678901234"})); // > 64 hex chars

0 commit comments

Comments
 (0)