Remove boost as a unit test runner #35587

pull rustaceanrob wants to merge 24 commits into bitcoin:master from rustaceanrob:remove-boost-test changing 167 files +1396 −441
  1. rustaceanrob commented at 7:33 AM on June 23, 2026: member

    tl;dr: Make an equivalent test runner to boost with simpler macros and tighter coupling to bitcoin-specific code.

    Motivation

    There are a number of problems with using dependencies in general. Bugs must either be promptly upstreamed or patched, projects may be abandoned, and they are not tailored to a particular use case. This PR removes boost for writing and running unit tests. In the case of Boost.Test, there are a number of issues which are listed below.

    My problems with Boost.Test

    Macros

    When using boost, there are 3 ways of writing the same thing, each with different outcomes

    • BOOST_CHECK(expr1 == expr2): failures show the expression, but no values for expr1 and expr2
    • BOOST_CHECK_EQUAL(expr1, expr2): failures show the expression and values, but requires developers remember CHECK_EQUAL and does not use usual operands
    • BOOST_TEST(expr1 == expr2): failures show the expression and values, and developers may use familiar operands (==, !=)

    All three are preserved to maintain backwards compatibility - presumably, but this results in all 3 being used throughout the repository. As a bonus there is a 4th way, with added context

    • BOOST_CHECK_MESSAGE(expr1 == expr2, "the context"): failures show the expression and message, but no values for expr1 and expr2

    To make debugging and review easier, all of these should be unified to a single macro. Test sites use operands, print helpful messages - values are always included, and do not vary in approach (deciding between BOOST_TEST, CHECK, and BOOST_CHECK_EQUAL is unintuitive)

    <details> <summary>Example boost outputs</summary>

    BOOST_AUTO_TEST_CASE(mustfail)
    {
        auto a{1};
        auto b{2};
        BOOST_CHECK(a == b);
        BOOST_CHECK_EQUAL(a, b);
        BOOST_TEST(a == b);
        COutPoint outpoint_1{Txid{"0000000000000000000000000000000000000000000000000000000000000100"}, 0};
        COutPoint outpoint_2{Txid{"0000000000000000000000000000000000000000000000000000000000000100"}, 1};
        BOOST_CHECK(outpoint_1 == outpoint_2);
        // Doesn't even compile
        // BOOST_TEST(outpoint_1 == outpoint_2);
        // BOOST_CHECK_EQUAL(outpoint_1, outpoint_2);
    }
    
    Running 1 test case...
    test/argsman_tests.cpp(31): error: in "argsman_tests/mustfail": check a == b has failed
    test/argsman_tests.cpp(32): error: in "argsman_tests/mustfail": check a == b has failed [1 != 2]
    test/argsman_tests.cpp(33): error: in "argsman_tests/mustfail": check a == b has failed [1 != 2]
    test/argsman_tests.cpp(36): error: in "argsman_tests/mustfail": check outpoint_1 == outpoint_2 has failed
    

    </details>

    <details> <summary>New outputs</summary>

    TEST_CASE(mustfail)
    {
        auto a{1};
        auto b{2};
        CHECK(a == b);
        COutPoint outpoint_1{Txid{"0000000000000000000000000000000000000000000000000000000000000100"}, 0};
        COutPoint outpoint_2{Txid{"0000000000000000000000000000000000000000000000000000000000000100"}, 1};
        CHECK(outpoint_1 == outpoint_2);
    }
    
    Running 1 test cases...
    [FAIL]: test/argsman_tests.cpp:30: CHECK(a == b)
    1 == 2
    
    [FAIL]: test/argsman_tests.cpp:33: CHECK(outpoint_1 == outpoint_2)
    COutPoint(0000000000, 0) == COutPoint(0000000000, 1)
    
    [FAIL] mustfail (2/2 checks failed)
    

    </details>

    No repository context

    Many types implement ToString, but boost has no way of meaningfully using these representations (will change w/ future std::format). With a repository-specific test runner we can use these today. See example above.

    Not extensible

    With the test runner in this repository we can add things such as #35139, implement string representations for more types, and implement ideas from #8670.

    Other issues

    More issues with boost are raised in #34666, #8670. This PR does not resolve all of them, but one it does address immediately is banning comparisons of integers with different signs, previously allowed by boost. Using a test runner within the source also makes IWYU easier to work with.

    High level changes

    For those running tests, not a tremendous amount has changed in this PR. For instance, the doc page remains valid. Changes to the runner options include anything that is not help, run_test, log_level, list_content. This includes catch_system_errors which is always no. The log_levels have been reduced to 5 levels.

    Changes in writing tests

    • CHECK to compare two values with any ==, !=, >, etc
    • CHECK(a == b, "my message") to append a message
    • REQUIRE, same as CHECK, but will fail the test immediately
    • CHECK_EQUAL_RANGES(it1, it2) to compare two ranges
    • TEST_CASE(name) to add a test
    • FIXTURE_TEST_CASE(name, Fixture) to add a test with a fixture
    • TEST_SUITE_BEGIN/END to declare a suite, optionally with fixture for each test in the suite

    Migration

    Boost.Test is removed in this PR, but the macros are aliased by BOOST_* counterparts so there are no merge conflicts. The idea would be to migrate test files to the new macros when there are no/low number of conflicts on that file.

  2. DrahtBot commented at 7:33 AM on June 23, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/35587.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline and AI policy for information on the review process.

    Type Reviewers
    Concept ACK purpleKarrot, josibake, janb84, w0xlt, optout21

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #35569 (Encapsulation for CTransaction by purpleKarrot)
    • #35531 (txindex: hash keys and pack positions to reduce disk usage by andrewtoth)
    • #35195 (coins: cache UTXO outpoint hash codes by l0rinc)
    • #34872 (wallet: fix mixed-input transaction accounting in history RPCs by w0xlt)
    • #34864 (coins: tighten cache entry state invariants by l0rinc)
    • #34075 (fees: Introduce Mempool Based Fee Estimation to reduce overestimation by ismaelsadeeq)
    • #33540 (argsman, cli: GNU-style command-line option parsing (allows options after non-option arguments) by pablomartin4btc)
    • #31682 ([IBD] specialize CheckBlock's input & coinbase checks by l0rinc)
    • #29278 (Wallet: Add maxfeerate wallet startup option by ismaelsadeeq)
    • #17783 (common: Disallow calling IsArgSet() on ALLOW_LIST options by ryanofsky)
    • #17581 (refactor: Remove settings merge reverse precedence code by ryanofsky)
    • #17580 (refactor: Add ALLOW_LIST flags and enforce usage in CheckArgFlags by ryanofsky)
    • #17493 (util: Forbid ambiguous multiple assignments in config file by ryanofsky)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

    LLM Linter (✨ experimental)

    Possible typos and grammar issues:

    • evalution -> evaluation [misspelled in the comment “captures the expression before evalution”]

    Possible places where named args for integral literals may be used (e.g. func(x, /*named_arg=*/0) in C++, and func(x, named_arg=0) in Python):

    • GetSetting(settings, "section", "name", false, false, false) in src/test/settings_tests.cpp
    • GetSetting(settings, "section", "name", false, false, false) in src/test/settings_tests.cpp
    • Test(ms_stack_limit, "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 4 * count + 1, 1, {}, {}, 1 + count + 1) in src/test/miniscript_tests.cpp

    <sup>2026-07-08 17:54:02</sup>

  3. purpleKarrot commented at 8:43 AM on June 23, 2026: contributor

    Strong Concept ACK

    My problems with boost

    Boost may have multiple problems on its own, but the problems that you list are specific to Boost.Test. You should not conflate the two.

    CHECK_EQUAL_RANGES(it1, it2) to compare two iterators

    Iterators or Ranges?

    TEST_SUITE_BEGIN/END to declare a suite

    Boost.Test allows arbitrary deep nesting of test suites. When integrating Boost.Test into CTest, this causes headaches for little benefit. I hope we can follow-up on this and restrict the test hierarchy to exactly one test suite (no more and no less) using something along the TEST(TestSuiteName, TestName) macro from GoogleTest.

    Why no concurrency?

    In my opinion, concurrency does not belong in a testing framework. Many testing frameworks have a test driver built-in. But separating test framework and test driver into two orthogonal components allows much more powerful composition. I would even go so far and claim that a test framework should not provide a way to run more than one test; neither concurrently, nor sequentially.

    What a test framework needs to be able to provide, is a way to launch a single test and a way to tell the test driver about the list of tests that are available. The test driver can then orchestrate tests from different testing frameworks from potentially different programming languages and invoke tests individually, sequentially, concurrently, or even distributed across multiple hosts.

    This kind of integration is exactly the reason why I implemented discover_tests, which will be available in CMake 4.4.

    The Boost.Test framework is notoriously bad at this. When selecting a single test, it spams out information about all tests that are not selected. While it can provide information about what tests are available, that output is optimized for human readability and very hard to parse by a test driver. We can definitely do better with a custom test framework!

  4. fjahr commented at 9:06 AM on June 23, 2026: contributor

    There are a number of problems with using dependencies in general. Bugs must either be promptly upstreamed or patched, projects may be abandoned, and they are not tailored to a particular use case. bitcoind has a small number of dependencies and will have fewer very soon (https://github.com/bitcoin/bitcoin/pull/34411). One of the final remaining dependencies is boost, which is responsible for the unit tests and multi-index. This PR removes boost for writing and running unit tests.

    Boost.Test is not a dependency of bitcoind, only of test_bitcoin so this is not comparable to the libevent removal. Also boost::multi_index removal was rejected very recently: #34586.

  5. rustaceanrob commented at 9:21 AM on June 23, 2026: member

    only of test_bitcoin

    Correct me if I'm wrong but it appears the config here still builds test_bitcoin: https://github.com/bitcoin/bitcoin/blob/master/contrib/guix/libexec/build.sh#L125

    Also boost::multi_index removal was rejected very recently: #34586

    That approach used STL containers. An actual replacement would need to use something like this: https://www.mail-archive.com/digitalmars-d@puremagic.com/msg33920.html

  6. fjahr commented at 9:43 AM on June 23, 2026: contributor

    Correct me if I'm wrong but it appears the config here still builds test_bitcoin

    Yes, but what does that have to with my comment? I just said that it's a dependency of test_bitcoin not bitcoind. Reducing the dependencies of bitcoind is a lot more interesting than those of test_bitcoin for obvious security reasons. I don't think the fact that test_bitcoin is built in a release and installed changes much of that. Maybe it does for other people but I think your motivation should be more clear on this if this is what you are after. Particularly this part:

    bitcoind has a small number of dependencies and will have fewer very soon (https://github.com/bitcoin/bitcoin/pull/34411). One of the final remaining dependencies is boost, which is responsible for the unit tests and multi-index.

    I would read this very clearly as boost (including Boost.Test) is a dependency of bitcoind if I didn't know better.

    That approach used STL containers.

    The pull was rejected on conceptual basis, not approach, so I don't think this matters.

  7. rustaceanrob commented at 10:15 AM on June 23, 2026: member

    I would read this very clearly as boost (including Boost.Test) is a dependency of bitcoind if I didn't know better.

    Sure, PR description updated.

    Reducing the dependencies of bitcoind is a lot more interesting than those of test_bitcoin for obvious security reasons

    I find this less obvious then the comment implies. A repository going stale is far more likely than some backdoor or high severity CVE, so "a lot more interesting" feels subjective.

  8. josibake commented at 12:19 PM on June 23, 2026: member

    Yes, but what does that have to with my comment?

    A lot. @rustaceanrob correctly points out that even though Boost.Test is not strictly a dependency of bitcoind, it is included in the release flow that creates and packages bitcoind, along with test_bitcoin. It is correct to say that Boost.Test is a dependency of our release process.

  9. josibake commented at 12:20 PM on June 23, 2026: member

    A repository going stale is far more likely than some backdoor or high severity CVE, so "a lot more interesting" feels subjective.

    Precisely. It's also worth remembering the xzutils backdoor was introduced through test code.

  10. josibake commented at 12:27 PM on June 23, 2026: member

    Strong Concept ACK!

    Love to see it. While I broadly agree with the author's reasons stated in the PR, the ones I'll highlight specifically are:

    • No repository context
    • Not extensible

    Having our own simple, in house test framework gives us the ability to customise it for exactly our needs. I believe we should do everything in our power to make testing an easy, intuitive, and feature rich experience as this helps to remove barriers to people writing and interpreting tests.

    In particular, as a longer term project I am looking at ways to improve concurrency in our testing to help speed up CI. As @purpleKarrot points out:

    The Boost.Test framework is notoriously bad at this. When selecting a single test, it spams out information about all tests that are not selected. While it can provide information about what tests are available, that output is optimized for human readability and very hard to parse by a test driver. We can definitely do better with a custom test framework!

  11. hebasto commented at 1:30 PM on June 23, 2026: member

    996832947dd1053b2e31acd1ef3e2933804fd580 "test: Separate mock_process into a standalone binary"

    This approach seems incompatible with the release process.

    For example, I downloaded the bitcoin-e6e8d1f00a08-win64-unsigned.zip "release" binaries on a Windows machine, unpacked them, and ran:

    >.\bitcoin-e6e8d1f00a08\libexec\test_bitcoin.exe
    Running 770 test cases...
    EXCEPTION in run_command: CreateProcess failed: The system cannot find the file specified.
    [FAIL] run_command (0/1 checks failed)
    [WARN]: Variable DIR_UNIT_TEST_DATA unset, skipping script_assets_test
    
    770 tests: 769 passed, 1 failed, 0 skipped (26566129 checks)
    
    
  12. rustaceanrob force-pushed on Jun 23, 2026
  13. rustaceanrob commented at 5:12 PM on June 23, 2026: member

    This approach seems incompatible with the release process.

    a0d535a78b63df4d04411efb1b2c0f98ee87211e uses an environment variable to determine if the test should run as the mock process or the actual test runner. No added files and should not effect the release.

  14. DrahtBot added the label Needs rebase on Jun 23, 2026
  15. rustaceanrob force-pushed on Jun 23, 2026
  16. DrahtBot removed the label Needs rebase on Jun 23, 2026
  17. in src/test/util/framework.h:463 in 7974316a1a
     458 | +                return ExitStatus::UnknownArgs;
     459 | +            }
     460 | +            opts.log_level = log_level;
     461 | +            continue;
     462 | +        }
     463 | +        if (arg.starts_with("-l")) {
    


    janb84 commented at 9:56 AM on June 24, 2026:

    Is this what we want ? -t foo => correct -tfoo => silently mis-parses

    --run_test foo ==> reject with message (BOOST would accept this) --run_test=foo ==> correct

    (same for --log_level and -l)


    rustaceanrob commented at 12:01 PM on June 24, 2026:

    f90b9b97a85bb923e2ec2b48e7719381bd5c2a99

    -tfoo -> errors and prints usage

    --run_test foo -> runs the foo tests

  18. in src/test/util/framework.h:417 in 7974316a1a
     412 | +struct RuntimeOptions {
     413 | +    const char* prog;
     414 | +    std::string_view filter;
     415 | +    LogLevel log_level = LogLevel::Error;
     416 | +    bool show_list;
     417 | +    bool show_help;
    


    janb84 commented at 10:06 AM on June 24, 2026:
        const char* prog{nullptr};
        std::string_view filter;
        LogLevel log_level = LogLevel::Error;
        bool show_list{false};
        bool show_help{false};
    

    NIT, Core code has a Initializing members at the point of declaration style. This is not wrong (by means of used RuntimeOptions opts{} ) but not matching style.

  19. in src/test/util/framework.h:195 in 7974316a1a
     190 | +        if (!result.is_ok()) {
     191 | +            m_failed.fetch_add(1, std::memory_order_relaxed);
     192 | +        }
     193 | +    }
     194 | +
     195 | +    void exception_occured()
    


    janb84 commented at 10:08 AM on June 24, 2026:
        void exception_occurred()
    

    NIT: spelling

  20. janb84 commented at 10:13 AM on June 24, 2026: contributor

    Concept ACK 7974316a1a5e9e84be446f86fed52564ee954b4b

    This change has enough pro's for me to support it;

    • Unification of all the different BOOS_CHECK*
    • Better orchestrate-able, see #35587 (comment)
    • Removal of dependency.
  21. josibake commented at 11:33 AM on June 24, 2026: member

    The pull was rejected on conceptual basis, not approach, so I don't think this matters. @fjahr this is not an accurate framing of the discussion on #34586. It is acknowledged that fewer dependencies are desirable, if the replacements are an improvement. The critique that follows is specifically about the use of STL containers (which are indeed worse). The second push back from a different reviewer echos the sentiment: boost multi index is better than the alternatives (STL containers, in this case).

    I think this PR stands on its own merit as better than using Boost.Test, regardless of whether or not we end up fully removing boost. However, if a better alternative to boost multi index were to be proposed (e.g., @rustaceanrob 's link), this PR and that perhaps future PR only strengthen each other, not weaken.

  22. rustaceanrob force-pushed on Jun 24, 2026
  23. fanquake commented at 2:11 PM on June 24, 2026: member

    @rustaceanrob if you want, couple commits here to prune out the Boost Test dep: https://github.com/fanquake/bitcoin/commits/35587_drop_pkg/.

  24. rustaceanrob commented at 5:47 PM on June 24, 2026: member

    Nice, I picked those up, thanks

  25. DrahtBot added the label Needs rebase on Jun 24, 2026
  26. rustaceanrob force-pushed on Jun 25, 2026
  27. DrahtBot removed the label Needs rebase on Jun 25, 2026
  28. w0xlt commented at 8:36 PM on June 25, 2026: contributor

    Concept ACK

  29. in src/test/kernel/test_kernel.cpp:415 in fab3d3bf8e outdated
     411 | @@ -412,9 +412,9 @@ BOOST_AUTO_TEST_CASE(btck_transaction_tests)
     412 |      auto empty_data = hex_string_to_byte_vec("");
     413 |      BOOST_CHECK_THROW(Transaction{empty_data}, std::runtime_error);
     414 |  
     415 | -    BOOST_CHECK_EQUAL(tx.CountOutputs(), 2);
     416 | -    BOOST_CHECK_EQUAL(tx.CountInputs(), 1);
     417 | -    BOOST_CHECK_EQUAL(tx.GetLocktime(), 510826);
     418 | +    BOOST_CHECK_EQUAL(tx.CountOutputs(), 2U);
    


    maflcko commented at 3:59 PM on June 27, 2026:

    in fab3d3bf8e9557b92003d5719a6e9781e7cb1886: Not sure why this is needed.

    What are the steps to reproduce and what is the exact output? It would be good to explain this in the commit message.

    Recall that integers in C++ are not type safe (as opposed to e.g. Rust), and C++ has integer promotion rules. This means that literals, such as 0 or 2 can be converted by the compiler to fit in whatever type they should fit for this comparison operation. Specifying U here is harmless, but also useless.

    The correct fix would be to drop this commit, not only because it is large (500+ lines modified), but also because it is not needed.

    See also https://www.github.com/bitcoin/bitcoin/pull/35139/changes/fa0ca71f6964153650a8d5b5d410eceb56460a9c, which makes this work properly:

    template <typename L, typename R, typename OpFunc>
    void check_op(const L& lhs, const R& rhs, std::string_view expr, const char* inv_op, const OpFunc& op,
                  std::source_location loc = std::source_location::current()) noexcept
    {
        if constexpr (std::is_integral_v<L> && std::is_integral_v<R>) {
            // Reject mixed signs for integrals after integral promotion.
            if constexpr (std::is_signed_v<decltype(std::declval<L>() + 0)> != std::is_signed_v<decltype(std::declval<R>() + 0)>) {
                static_assert(std::is_signed_v<L> == std::is_signed_v<R>,
                              "ERROR: Mixed signed/unsigned comparison! Ensure both sides have the same type of signedness.");
            }
        }
        if (!op(lhs, rhs)) {
            std::string explanation{"[" + format_value(lhs) + " " + inv_op + " " + format_value(rhs) + "]"};
            fail_report(expr, explanation, loc);
        }
    }
    
  30. maflcko commented at 4:17 PM on June 27, 2026: member

    I like the changes, but I wonder if another approach could be done here, because replacing the check macros and replacing the framework are not tied together and can be done subsequently and independently.

    Given that this has ~100 direct merge conflicts and possibly a few more silent merge conflicts, I wonder if this should be made easier to review and rebase against.

    My preference would be to:

    • First add the new macros (and the required changes to use them), similar to #35139
    • Then, switch to them in a commit that is easier to review than a commit that also changes the framework in the same diff.
    • Then introduce the new framework.
    • Then switch to the new framework and remove boost.

    Just my preference, though. Not sure what other reviewers prefer.

    Edit: An alternative approach could be to keep this pull as-is, but drop the large "macro rewrite" and instead provide legacy aliases, which can be used temporarily (#define BOOST_CHECK_EQUAL(a, b) CHECK(a == b) // or CHECK_EQUAL(a, b) or whatever the name of the new macro is). This way, many conflicts/rebases during the review of this pull can be avoided, which should make re-review less tedious here. The "simple"/mechanical replacement can then be done later, hopefully at a pre-defined time to minimize the conflicts/rebases and thus minimize the re-review load again?

  31. rustaceanrob commented at 1:34 PM on June 29, 2026: member

    An alternative approach could be to keep this pull as-is, but drop the large "macro rewrite" and instead provide legacy aliases, which can be used temporarily (#define BOOST_CHECK_EQUAL(a, b) CHECK(a == b) // or CHECK_EQUAL(a, b) or whatever the name of the new macro is).

    Makes sense

  32. rustaceanrob force-pushed on Jun 30, 2026
  33. rustaceanrob commented at 2:50 PM on June 30, 2026: member

    Updated with legacy aliases

  34. DrahtBot added the label Needs rebase on Jun 30, 2026
  35. rustaceanrob force-pushed on Jun 30, 2026
  36. DrahtBot removed the label Needs rebase on Jun 30, 2026
  37. maflcko commented at 8:31 AM on July 1, 2026: member

    This only has 24 comments, but is already tedious to review on GitHub, because GitHub decides to hide even a 4 day old comment (https://github.com/bitcoin/bitcoin/pull/35587#discussion_r3486342364). This GitHub behavior was triggered by the (no longer relevant) long list of conflicts.

    Maybe open as a fresh pull request? This should be easy, given that there are no outstanding review comments. (Except maybe mine)

    <img width="1010" height="78" alt="Screenshot 2026-07-01 at 10-30-44 Remove boost as a unit test runner by rustaceanrob · Pull Request [#35587](/github-metadata-backup-bitcoin-bitcoin/35587/) · bitcoin_bitcoin" src="https://github.com/user-attachments/assets/b54ef02f-863f-4a42-9a38-17a513f36f10" />

  38. l0rinc commented at 5:24 PM on July 1, 2026: contributor

    This only has 24 comments, but is already tedious to review on GitHub

    Maybe open as a fresh pull request?

    We need to find a more sustainable/scalable way to do this; GitHub is basically unusable for non-trivial PRs.

    GitHub decides to hide even a 4 day old comment

    https://github.com/refined-github/refined-github has a browser extension to work around that (command+clicking these opens all hidden sections). I also added automatic open to my helper in https://github.com/l0rinc/ACKtopus.

  39. maflcko commented at 8:13 AM on July 2, 2026: member

    This only has 24 comments, but is already tedious to review on GitHub Maybe open as a fresh pull request?

    We need to find a more sustainable/scalable way to do this; GitHub is basically unusable for non-trivial PRs.

    I think here it is really only related to the long list of conflicting pulls. I guess each conflict was an "event" (like a comment). E.g., #35402 is another pull request with roughly 24 comments, and it works just fine.

    I think here opening a fresh pull is trivial and sufficient, but of course I won't object moving off of GitHub :sweat_smile:

    GitHub decides to hide even a 4 day old comment

    https://github.com/refined-github/refined-github has a browser extension to work around that (command+clicking these opens all hidden sections). I also added automatic open to my helper in https://github.com/l0rinc/ACKtopus.

    Thx. Browser extensions, in combination with javascript and LLM integration give me a bit of unease. I think I'll just click the mouse button thrice for now here :sweat_smile:

    A third alternative could be to not trigger GitHub events for each conflict, by using a click-jacking URL. Opened a brainstorming issue in https://github.com/maflcko/DrahtBot/issues/83

  40. optout21 commented at 11:01 AM on July 3, 2026: contributor

    Concept ACK

    A net benefit, both due to reducing Boost usage and improvements (current and future) to the unit test framework.

    Some minor/quick observations:

    • It's a large diff, as all test code is affected. Could be broken up as: introduce new framework, change testers (in chunks), remove boost framework leftovers. Testers that are touched in pending PRs could be left at the end.
    • Once this is over, the macros could be renamed to not have the BOOST prefix (scripted diff)
    • I've seen some seemingly unrelated change to non-test code (const -> constexpr)
  41. in src/test/dbwrapper_tests.cpp:359 in 613a43b5d0 outdated
     355 | @@ -356,18 +356,18 @@ BOOST_AUTO_TEST_CASE(iterator_ordering)
     356 |      for (const int seek_start : {0x00, 0x80}) {
     357 |          it->Seek((uint8_t)seek_start);
     358 |          for (unsigned int x=seek_start; x<255; ++x) {
     359 | -            uint8_t key;
     360 | -            uint32_t value;
     361 | +            uint8_t key{};
    


    l0rinc commented at 6:31 PM on July 3, 2026:

    The diff is already huge and there are a lot of seemingly unrelated changes here - can you please revert these to minimize the diff?

  42. in src/test/dbwrapper_tests.cpp:337 in 613a43b5d0


    l0rinc commented at 6:32 PM on July 3, 2026:

    Is there any way to keep the IDE supports somehow - since other tools already have test/debug/coverage/profile support for it, e.g. current behavior on CLion: <img width="445" height="150" alt="Image" src="https://github.com/user-attachments/assets/6da4f6ca-b6b0-4b54-bbe7-fcecd823b6fa" />

    PR behavior: <img width="465" height="80" alt="Image" src="https://github.com/user-attachments/assets/34f5249e-c89c-46e4-b34e-577e4e93d61d" />

  43. l0rinc changes_requested
  44. l0rinc commented at 6:53 PM on July 3, 2026: contributor

    Not yet sure about this, another huge change (that kills the GitHub UI) - I'd be interested in a gradual/minimal approach here that doesn't touch so many files.

  45. maflcko commented at 8:35 AM on July 4, 2026: member

    I think it is nice to have a self-contained and complete patchset that applies globally all at once. Of course, if there are specific unrelated changes that truly make sense on their own and where it makes sense to split them up, it can be done. However, some of the changes seem not needed and possibly even going in the wrong direction, as pointed out in review (https://github.com/bitcoin/bitcoin/pull/35587#discussion_r3486342364, or #35587 (review), or #35625 (comment)). So there is somewhat of a chance that some of those may be dropped and the result here will be slim enough to go in as mostly a single pull request.

  46. DrahtBot added the label Needs rebase on Jul 8, 2026
  47. crypto: Use `constexpr` to define output size
    This makes the output size of each hash known at compile time throughout
    TU
    
    Needed in `crypto_tests` without the presence of boost.
    5b7e26ecd6
  48. util: Use `constexpr` in `LockedPool` definitions
    Makes the size of the pool known at compile time for other TU
    
    Needed in `allocator_tests` without the presence of boost.
    9dfd945b7f
  49. net: Make `AddressPosition` comparitor `const`
    Needed to use `==` operator in tests.
    b8b2d5e6c1
  50. test: Remove `mock_process.cpp`
    The previous binary used a number of `Boost.Test` features:
    - `boost::unit_test::disable`
    - `BOOST_FAIL`
    - `boost::exit_test_failure`
    
    None of these are used elsewhere and are unnecessary to port to a new
    framework.
    
    This duplicates the previous mock process behavior with no boost features.
    8d88d51403
  51. test: Compare by string instead of char*
    Boost allows comparison of two char* within `CHECK_EQUAL` but
    comparing two char* with `==` is undefined as it compares two
    pointers.
    
    Cast c-style strings to `std::string` before comparison.
    9f5fc25cc7
  52. test: Include `memory` in `result_tests`
    This is being brought in transitively by boost
    f8849dd8a7
  53. test: Initialize variables in `dbwrapper_tests`
    This would otherwise trip the sanitizer, but the `BOOST_CHECK`
    obfuscates the use before initialization.
    1c47b91684
  54. test: Redeclare variable as signed in `util_tests`
    This is an underflow as `n` is declared unsigned.
    5c8a2258a1
  55. test: Remove use of `BOOST_FAIL`
    There is only a single case of this macro and the if conditional that
    triggers it may simply be used in a `BOOST_REQUIRE`
    39f27ba6f5
  56. test: Remove use of `BOOST_TEST_INFO_*`
    In the case of `descriptor_tests.cpp`, the info is only used to get the
    diagonsics of `BOOST_CHECK_EQUAL` along with the human readable form of
    the descriptor. This is irrelevant if the test framework implements
    expression decomposition, which will print the string representation on
    failure (e.g. `BOOST_TEST`).
    
    Removing `BOOST_TEST_INFO_SCOPE` requires a few duplications, but these are
    very little cost compared to a port of this macro, which does not appear
    very useful.
    f93f0f05c6
  57. test: Remove use of `BOOST_CHECK_CLOSE`
    This is only used in a single test and would be a low-motivation add to
    porting the test framework. A lambda is sufficient to enforce the check.
    26a1cd321e
  58. test: Constrain optional<T> operator<< by streamability
    Without this constraint, an operator<<(std::ostream&, const std::optional<T>&)
    overload is selectable for any T, even when T itself has no operator<<.
    dcb7ff5801
  59. test: Move test-only helper classes out of Boost suite namespaces
    BOOST_FIXTURE_TEST_SUITE opens an implicit namespace matching
    the suite name, so a class declared inside the suite body ends up at
    `<outer>::<suite>::Name`. This assumption does not hold for other
    frameworks.
    940f5a5c3b
  60. test: Use ListCoinsTestingSetup directly instead of the test-case class
    BOOST_FIXTURE_TEST_CASE(name, Fixture) generates a class named after the
    test case (deriving from Fixture). When switching frameworks this is not
    a guarentee, and it is also unnecessary.
    e1b107086c
  61. test: Use lambda for `CRecipient` to avoid gcc12 uninitialized warning
    gcc12 warns with uninitialized when boost is not used for this test.
    This side-steps the warning.
    1f0927f5ad
  62. rustaceanrob force-pushed on Jul 8, 2026
  63. DrahtBot removed the label Needs rebase on Jul 8, 2026
  64. rustaceanrob force-pushed on Jul 8, 2026
  65. DrahtBot added the label CI failed on Jul 8, 2026
  66. DrahtBot commented at 4:51 PM on July 8, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task previous releases: https://github.com/bitcoin/bitcoin/actions/runs/28954672394/job/85910327486</sub> <sub>LLM reason (✨ experimental): CI failed due to a C++ build error: a static_assert in /usr/include/c++/12/utility (from std::cmp_equal) when compiling src/test/util_tests.cpp.</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  67. test: Avoid unnecessary type conversions in check conditions
    `EraseTx` already returns a `bool`, so these implicit casts within the
    comparisons are not necessary.
    fea359ab46
  68. test: Unroll `&&` conditions in macros
    Using `&&` in `BOOST_CHECK` is problematic as failures will not indicate
    which condition failed. By unrolling these checks, the user knows
    exactly which expression is the failing case.
    
    This is also required when using test macros that support value
    decomposition, which requires `&&` and `||` are `delete`. Examples
    include `BOOST_TEST`, doctest, Catch2, etc.
    
    ref: https://fekir.info/post/decomposing-an-expression/
    fe7ad834d9
  69. test: Wrap `||` expressions in macros
    The `||` is not usable with `BOOST_TEST` and other modern test
    frameworks like Catch2. This is due to operator precedence used in such
    macros. Here is an additional opinion from Catch2:
    
    > There is no simple rewrite rule for ||, but I generally believe
    that if you have || in your test expression, you should rethink your tests.
    
    ref: https://catch2-temp.readthedocs.io/en/latest/assertions.html#other-limitations
    ref: https://fekir.info/post/decomposing-an-expression/
    e757b5ac8f
  70. test: Wrap bitwise `&` expressions in macros 3b03be7d8e
  71. test: Add header-only framework to util 8c65315ec1
  72. scripted-diff: Migrate tests to header-only framework
    -BEGIN VERIFY SCRIPT-
    mv src/test/new_main.cpp src/test/main.cpp
    git grep -l '<boost/test/unit_test.hpp>' | xargs sed -i 's|<boost/test/unit_test.hpp>|<test/util/framework.h>|'
    sed -i 's|BOOST_TEST_MODULE Bitcoin Kernel Test Suite|BITCOIN_TEST_MAIN|; s|<boost/test/included/unit_test.hpp>|<test/util/framework.h>|' src/test/kernel/test_kernel.cpp
    sed -i 's|boost::unit_test::framework::master_test_suite().argv\[0\]|framework::executable_path()|' src/test/system_tests.cpp
    sed -i '/boost\/test\/\(included\/\)\?unit_test.hpp/d' test/lint/lint-includes.py
    sed -i 's| --catch_system_error=no||' src/test/CMakeLists.txt
    -END VERIFY SCRIPT-
    cb2863c806
  73. depends: drop test from Boost libraries d85425241e
  74. cmake: drop vcpkg Boost Test check 30d1f3b086
  75. vcpkg: drop boost-test dependency 500ebaab42
  76. rustaceanrob force-pushed on Jul 8, 2026
  77. DrahtBot removed the label CI failed on Jul 8, 2026

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-07-09 06:47 UTC