Bitcoin Core 22.99.0
P2P Digital Currency
validationinterface_tests.cpp
Go to the documentation of this file.
1// Copyright (c) 2020 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <boost/test/unit_test.hpp>
7#include <primitives/block.h>
8#include <scheduler.h>
10#include <util/check.h>
11#include <validationinterface.h>
12
13BOOST_FIXTURE_TEST_SUITE(validationinterface_tests, TestingSetup)
14
16 void BlockChecked(const CBlock&, const BlockValidationState&) override {}
17};
18
19BOOST_AUTO_TEST_CASE(unregister_validation_interface_race)
20{
21 std::atomic<bool> generate{true};
22
23 // Start thread to generate notifications
24 std::thread gen{[&] {
25 const CBlock block_dummy;
26 BlockValidationState state_dummy;
27 while (generate) {
28 GetMainSignals().BlockChecked(block_dummy, state_dummy);
29 }
30 }};
31
32 // Start thread to consume notifications
33 std::thread sub{[&] {
34 // keep going for about 1 sec, which is 250k iterations
35 for (int i = 0; i < 250000; i++) {
36 auto sub = std::make_shared<TestSubscriberNoop>();
39 }
40 // tell the other thread we are done
41 generate = false;
42 }};
43
44 gen.join();
45 sub.join();
47}
48
50{
51public:
52 TestInterface(std::function<void()> on_call = nullptr, std::function<void()> on_destroy = nullptr)
53 : m_on_call(std::move(on_call)), m_on_destroy(std::move(on_destroy))
54 {
55 }
57 {
59 }
60 void BlockChecked(const CBlock& block, const BlockValidationState& state) override
61 {
62 if (m_on_call) m_on_call();
63 }
64 static void Call()
65 {
66 CBlock block;
68 GetMainSignals().BlockChecked(block, state);
69 }
70 std::function<void()> m_on_call;
71 std::function<void()> m_on_destroy;
72};
73
74// Regression test to ensure UnregisterAllValidationInterfaces calls don't
75// destroy a validation interface while it is being called. Bug:
76// https://github.com/bitcoin/bitcoin/pull/18551
77BOOST_AUTO_TEST_CASE(unregister_all_during_call)
78{
79 bool destroyed = false;
80 RegisterSharedValidationInterface(std::make_shared<TestInterface>(
81 [&] {
82 // First call should decrements reference count 2 -> 1
84 BOOST_CHECK(!destroyed);
85 // Second call should not decrement reference count 1 -> 0
87 BOOST_CHECK(!destroyed);
88 },
89 [&] { destroyed = true; }));
91 BOOST_CHECK(destroyed);
92}
93
Definition: block.h:63
void BlockChecked(const CBlock &, const BlockValidationState &)
Implement this to subscribe to events generated in validation.
TestInterface(std::function< void()> on_call=nullptr, std::function< void()> on_destroy=nullptr)
std::function< void()> m_on_call
void BlockChecked(const CBlock &block, const BlockValidationState &state) override
Notifies listeners of a block validation result.
std::function< void()> m_on_destroy
BOOST_AUTO_TEST_SUITE_END()
#define BOOST_FIXTURE_TEST_SUITE(a, b)
Definition: object.cpp:14
#define BOOST_CHECK(expr)
Definition: object.cpp:17
static RPCHelpMan generate()
Definition: mining.cpp:247
void BlockChecked(const CBlock &, const BlockValidationState &) override
Notifies listeners of a block validation result.
Testing setup that configures a complete environment.
Definition: setup_common.h:99
CMainSignals & GetMainSignals()
void UnregisterSharedValidationInterface(std::shared_ptr< CValidationInterface > callbacks)
Unregister subscriber.
void UnregisterAllValidationInterfaces()
Unregister all subscribers.
void RegisterSharedValidationInterface(std::shared_ptr< CValidationInterface > callbacks)
Register subscriber.
BOOST_AUTO_TEST_CASE(unregister_validation_interface_race)