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

Code before:

    std::vector<value_type> collected;
    for (const auto& elem : range) {
        collected.push_back(elem);
    }
    BOOST_CHECK_EQUAL(collected.size(), expected_size);

    BOOST_CHECK_EQUAL(std::ranges::size(range), expected_size);

    it = range.begin();
    auto it2 = 1 + it;
    BOOST_CHECK(it2 == it + 1);
}

BOOST_AUTO_TEST_CASE(btck_transaction_tests)
{
    auto tx_data{hex_string_to_byte_vec("02000000013f7cebd65c27431a90bba7f796914fe8cc2ddfc3f2cbd6f7e5f2fc854534da95000000006b483045022100de1ac3bcdfb0332207c4a91f3832bd2c2915840165f876ab47c5f8996b971c3602201c6c053d750fadde599e6f5c4e1963df0f01fc0d97815e8157e3d59fe09ca30d012103699b464d1d8bc9e47d4fb1cdaa89a1c5783d68363c4dbc4b524ed3d857148617feffffff02836d3c01000000001976a914fc25d6d5c94003bf5b0c7b640a248e2c637fcfb088ac7ada8202000000001976a914fbed3d9b11183209a57999d54d59f67c019e756c88ac6acb0700")};
    auto tx{Transaction{tx_data}};
    auto tx_data_2{hex_string_to_byte_vec("02000000000101904f4ee5c87d20090b642f116e458cd6693292ad9ece23e72f15fb6c05b956210500000000fdffffff02e2010000000000002251200839a723933b56560487ec4d67dda58f09bae518ffa7e148313c5696ac837d9f10060000000000002251205826bcdae7abfb1c468204170eab00d887b61ab143464a4a09e1450bdc59a3340140f26e7af574e647355830772946356c27e7bbc773c5293688890f58983499581be84de40be7311a14e6d6422605df086620e75adae84ff06b75ce5894de5e994a00000000")};
    auto tx2{Transaction{tx_data_2}};
    CheckHandle(tx, tx2);

    BOOST_CHECK_EQUAL(tx.CountOutputs(), 2);
    BOOST_CHECK_EQUAL(tx.CountInputs(), 1);
    auto broken_tx_data{std::span<std::byte>{tx_data.begin(), tx_data.begin() + 10}};
    BOOST_CHECK_THROW(Transaction{broken_tx_data}, std::runtime_error);
    auto output{tx.GetOutput(tx.CountOutputs() - 1)};
    BOOST_CHECK_EQUAL(output.Amount(), 42130042);
    auto script_pubkey{output.GetScriptPubkey()};
    {
        auto tx_new{Transaction{tx_data}};
        // This is safe, because we now use copy assignment
        TransactionOutput output = tx_new.GetOutput(tx_new.CountOutputs() - 1);
        ScriptPubkey script = output.GetScriptPubkey();

        TransactionOutputView output2 = tx_new.GetOutput(tx_new.CountOutputs() - 1);
        BOOST_CHECK_NE(output.get(), output2.get());
        BOOST_CHECK_EQUAL(output.Amount(), output2.Amount());
        TransactionOutput output3 = output2;
        BOOST_CHECK_NE(output3.get(), output2.get());
        BOOST_CHECK_EQUAL(output3.Amount(), output2.Amount());

        // Non-owned view
        ScriptPubkeyView script2 = output.GetScriptPubkey();
        BOOST_CHECK_NE(script.get(), script2.get());
        check_equal(script.ToBytes(), script2.ToBytes());

        // Non-owned to owned
        ScriptPubkey script3 = script2;
        BOOST_CHECK_NE(script3.get(), script2.get());
        check_equal(script3.ToBytes(), script2.ToBytes());

Review comment (bug):
```suggestion
    BOOST_CHECK_THROW(Transaction{std::span{static_cast<std::byte*>(nullptr), 2}}, std::runtime_error);
```

style-nit in 5b89956eeb76cf8c9717152fbb0928e026fc0087 (no need to re-touch), also I haven't tried compiling, but I think the compiler can derive the type here and it can be omitted. Same below.

Code after:
    std::vector<value_type> collected;
    for (const auto& elem : range) {
        collected.push_back(elem);
    }
    BOOST_CHECK_EQUAL(collected.size(), expected_size);

    BOOST_CHECK_EQUAL(std::ranges::size(range), expected_size);

    it = range.begin();
    auto it2 = 1 + it;
    BOOST_CHECK(it2 == it + 1);
}

BOOST_AUTO_TEST_CASE(btck_transaction_tests)
{
    auto tx_data{hex_string_to_byte_vec("02000000013f7cebd65c27431a90bba7f796914fe8cc2ddfc3f2cbd6f7e5f2fc854534da95000000006b483045022100de1ac3bcdfb0332207c4a91f3832bd2c2915840165f876ab47c5f8996b971c3602201c6c053d750fadde599e6f5c4e1963df0f01fc0d97815e8157e3d59fe09ca30d012103699b464d1d8bc9e47d4fb1cdaa89a1c5783d68363c4dbc4b524ed3d857148617feffffff02836d3c01000000001976a914fc25d6d5c94003bf5b0c7b640a248e2c637fcfb088ac7ada8202000000001976a914fbed3d9b11183209a57999d54d59f67c019e756c88ac6acb0700")};
    auto tx{Transaction{tx_data}};
    auto tx_data_2{hex_string_to_byte_vec("02000000000101904f4ee5c87d20090b642f116e458cd6693292ad9ece23e72f15fb6c05b956210500000000fdffffff02e2010000000000002251200839a723933b56560487ec4d67dda58f09bae518ffa7e148313c5696ac837d9f10060000000000002251205826bcdae7abfb1c468204170eab00d887b61ab143464a4a09e1450bdc59a3340140f26e7af574e647355830772946356c27e7bbc773c5293688890f58983499581be84de40be7311a14e6d6422605df086620e75adae84ff06b75ce5894de5e994a00000000")};
    auto tx2{Transaction{tx_data_2}};
    CheckHandle(tx, tx2);

    auto invalid_data = hex_string_to_byte_vec("012300");
    BOOST_CHECK_THROW(Transaction{invalid_data}, std::runtime_error);
    auto empty_data = hex_string_to_byte_vec("");
    BOOST_CHECK_THROW(Transaction{empty_data}, std::runtime_error);
    BOOST_CHECK_THROW(Transaction{std::span<std::byte>(static_cast<std::byte*>(nullptr), 2)}, std::runtime_error);

    BOOST_CHECK_EQUAL(tx.CountOutputs(), 2);
    BOOST_CHECK_EQUAL(tx.CountInputs(), 1);
    auto broken_tx_data{std::span<std::byte>{tx_data.begin(), tx_data.begin() + 10}};
    BOOST_CHECK_THROW(Transaction{broken_tx_data}, std::runtime_error);
    auto output{tx.GetOutput(tx.CountOutputs() - 1)};
    BOOST_CHECK_EQUAL(output.Amount(), 42130042);
    auto script_pubkey{output.GetScriptPubkey()};
    {
        auto tx_new{Transaction{tx_data}};
        // This is safe, because we now use copy assignment
        TransactionOutput output = tx_new.GetOutput(tx_new.CountOutputs() - 1);
        ScriptPubkey script = output.GetScriptPubkey();

        TransactionOutputView output2 = tx_new.GetOutput(tx_new.CountOutputs() - 1);
        BOOST_CHECK_NE(output.get(), output2.get());
        BOOST_CHECK_EQUAL(output.Amount(), output2.Amount());
        TransactionOutput output3 = output2;
        BOOST_CHECK_NE(output3.get(), output2.get());
        BOOST_CHECK_EQUAL(output3.Amount(), output2.Amount());

        // Non-owned view
        ScriptPubkeyView script2 = output.GetScriptPubkey();
        BOOST_CHECK_NE(script.get(), script2.get());
        check_equal(script.ToBytes(), script2.ToBytes());