Repository: bitcoin/bitcoin
File: src/test/uint256_tests.cpp (C++)

Code before:

    ss << R1S;
    BOOST_CHECK_EQUAL(ss.str(), std::string(R1Array,R1Array+20));
    ss >> TmpS;
    BOOST_CHECK_EQUAL(R1S, TmpS);
    ss.clear();
    ss << ZeroS;
    BOOST_CHECK_EQUAL(ss.str(), std::string(ZeroArray,ZeroArray+20));
    ss >> TmpS;
    BOOST_CHECK_EQUAL(ZeroS, TmpS);
    ss.clear();
    ss << MaxS;
    BOOST_CHECK_EQUAL(ss.str(), std::string(MaxArray,MaxArray+20));
    ss >> TmpS;
    BOOST_CHECK_EQUAL(MaxS, TmpS);
    ss.clear();
}

BOOST_AUTO_TEST_CASE( conversion )
{
    BOOST_CHECK_EQUAL(ArithToUint256(UintToArith256(ZeroL)), ZeroL);
    BOOST_CHECK_EQUAL(ArithToUint256(UintToArith256(OneL)), OneL);
    BOOST_CHECK_EQUAL(ArithToUint256(UintToArith256(R1L)), R1L);
    BOOST_CHECK_EQUAL(ArithToUint256(UintToArith256(R2L)), R2L);
    BOOST_CHECK_EQUAL(UintToArith256(ZeroL), 0);
    BOOST_CHECK_EQUAL(UintToArith256(OneL), 1);
    BOOST_CHECK_EQUAL(ArithToUint256(0), ZeroL);
    BOOST_CHECK_EQUAL(ArithToUint256(1), OneL);
    BOOST_CHECK_EQUAL(arith_uint256(UintToArith256(uint256S(R1L.GetHex()))), UintToArith256(R1L));
    BOOST_CHECK_EQUAL(arith_uint256(UintToArith256(uint256S(R2L.GetHex()))), UintToArith256(R2L));
    BOOST_CHECK_EQUAL(R1L.GetHex(), UintToArith256(R1L).GetHex());
    BOOST_CHECK_EQUAL(R2L.GetHex(), UintToArith256(R2L).GetHex());
}

BOOST_AUTO_TEST_CASE( operator_with_self )
{

/* Clang 16 and earlier detects v -= v and v /= v as self-assignments
   to 0 and 1 respectively.
   See: https://github.com/llvm/llvm-project/issues/42469
   and the fix in commit c5302325b2a62d77cf13dd16cd5c19141862fed0 .

   This makes some sense for arithmetic classes, but could be considered a bug
   elsewhere. Disable the warning here so that the code can be tested, but the
   warning should remain on as there will likely always be a better way to
   express this.
*/

#if defined(__clang__)
#    pragma clang diagnostic push
#    pragma clang diagnostic ignored "-Wself-assign-overloaded"

Review comment (suggestion):
nit: The old `conversion` test compared against integer literals here. The `methods` test in *arith_uint256_tests.cpp* compares against `0`, so this is covered in part.

Still, what do you think about adding something like:
```diff
diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp
index f596951dac..d437b6a54b 100644
--- a/src/test/arith_uint256_tests.cpp
+++ b/src/test/arith_uint256_tests.cpp
@@ -565,6 +565,8 @@ BOOST_AUTO_TEST_CASE(conversion)
     for (uint8_t num : {0, 1, 0xff}) {
         BOOST_CHECK_EQUAL(UintToArith256(uint256{num}), arith_uint256{num});
         BOOST_CHECK_EQUAL(uint256{num}, ArithToUint256(arith_uint256{num}));
+        BOOST_CHECK_EQUAL(UintToArith256(uint256{num}), num);
+        BOOST_CHECK_EQUAL(arith_uint256{num}, num);
     }
 }
```

Code after:
 * method that wraps base_blob::FromHex(), such as transaction_identifier::FromHex().
 */
template <typename T>
void TestFromHex()
{
    constexpr unsigned int num_chars{T::size() * 2};
    static_assert(num_chars <= 64); // this test needs to be modified to allow for more than 64 hex chars
    const std::string valid_64char_input{"0123456789abcdef0123456789ABCDEF0123456789abcdef0123456789ABCDEF"};
    const auto valid_input{valid_64char_input.substr(0, num_chars)};
    {
        // check that lower and upper case hex characters are accepted
        auto valid_result{T::FromHex(valid_input)};
        BOOST_REQUIRE(valid_result);
        BOOST_CHECK_EQUAL(valid_result->ToString(), ToLower(valid_input));
    }
    {
        // check that only strings of size num_chars are accepted
        BOOST_CHECK(!T::FromHex(""));
        BOOST_CHECK(!T::FromHex("0"));
        BOOST_CHECK(!T::FromHex(valid_input.substr(0, num_chars / 2)));
        BOOST_CHECK(!T::FromHex(valid_input.substr(0, num_chars - 1)));
        BOOST_CHECK(!T::FromHex(valid_input + "0"));
    }
    {
        // check that non-hex characters are not accepted
        std::string invalid_chars{R"( !"#$%&'()*+,-./:;<=>?@GHIJKLMNOPQRSTUVWXYZ[\]^_`ghijklmnopqrstuvwxyz{|}~)"};
        for (auto c : invalid_chars) {
            BOOST_CHECK(!T::FromHex(valid_input.substr(0, num_chars - 1) + c));
        }
        // 0x prefixes are invalid
        std::string invalid_prefix{"0x" + valid_input};
        BOOST_CHECK(!T::FromHex(std::string_view(invalid_prefix.data(), num_chars)));
        BOOST_CHECK(!T::FromHex(invalid_prefix));
    }
    {
        // check that string_view length is respected
        std::string chars_68{valid_64char_input + "0123"};
        BOOST_CHECK_EQUAL(T::FromHex(std::string_view(chars_68.data(), num_chars)).value().ToString(), ToLower(valid_input));
        BOOST_CHECK(!T::FromHex(std::string_view(chars_68.data(), num_chars - 1))); // too short
        BOOST_CHECK(!T::FromHex(std::string_view(chars_68.data(), num_chars + 1))); // too long
    }
}

BOOST_AUTO_TEST_CASE(from_hex)
{
    TestFromHex<uint160>();
    TestFromHex<uint256>();
    TestFromHex<Txid>();
    TestFromHex<Wtxid>();
}