Bitcoin Core  26.1.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>
6 #include <consensus/validation.h>
7 #include <primitives/block.h>
8 #include <scheduler.h>
10 #include <util/check.h>
11 #include <kernel/chain.h>
12 #include <validationinterface.h>
13 
14 #include <atomic>
15 
16 BOOST_FIXTURE_TEST_SUITE(validationinterface_tests, ChainTestingSetup)
17 
19  void BlockChecked(const CBlock&, const BlockValidationState&) override {}
20 };
21 
22 BOOST_AUTO_TEST_CASE(unregister_validation_interface_race)
23 {
24  std::atomic<bool> generate{true};
25 
26  // Start thread to generate notifications
27  std::thread gen{[&] {
28  const CBlock block_dummy;
29  BlockValidationState state_dummy;
30  while (generate) {
31  GetMainSignals().BlockChecked(block_dummy, state_dummy);
32  }
33  }};
34 
35  // Start thread to consume notifications
36  std::thread sub{[&] {
37  // keep going for about 1 sec, which is 250k iterations
38  for (int i = 0; i < 250000; i++) {
39  auto sub = std::make_shared<TestSubscriberNoop>();
42  }
43  // tell the other thread we are done
44  generate = false;
45  }};
46 
47  gen.join();
48  sub.join();
50 }
51 
53 {
54 public:
55  TestInterface(std::function<void()> on_call = nullptr, std::function<void()> on_destroy = nullptr)
56  : m_on_call(std::move(on_call)), m_on_destroy(std::move(on_destroy))
57  {
58  }
59  virtual ~TestInterface()
60  {
62  }
63  void BlockChecked(const CBlock& block, const BlockValidationState& state) override
64  {
65  if (m_on_call) m_on_call();
66  }
67  static void Call()
68  {
69  CBlock block;
71  GetMainSignals().BlockChecked(block, state);
72  }
73  std::function<void()> m_on_call;
74  std::function<void()> m_on_destroy;
75 };
76 
77 // Regression test to ensure UnregisterAllValidationInterfaces calls don't
78 // destroy a validation interface while it is being called. Bug:
79 // https://github.com/bitcoin/bitcoin/pull/18551
80 BOOST_AUTO_TEST_CASE(unregister_all_during_call)
81 {
82  bool destroyed = false;
83  RegisterSharedValidationInterface(std::make_shared<TestInterface>(
84  [&] {
85  // First call should decrements reference count 2 -> 1
87  BOOST_CHECK(!destroyed);
88  // Second call should not decrement reference count 1 -> 0
90  BOOST_CHECK(!destroyed);
91  },
92  [&] { destroyed = true; }));
94  BOOST_CHECK(destroyed);
95 }
96 
Testing setup that performs all steps up until right before ChainstateManager gets initialized...
Definition: setup_common.h:63
std::function< void()> m_on_destroy
Definition: block.h:68
BOOST_AUTO_TEST_CASE(unregister_validation_interface_race)
void UnregisterAllValidationInterfaces()
Unregister all subscribers.
void RegisterSharedValidationInterface(std::shared_ptr< CValidationInterface > callbacks)
Register subscriber.
void UnregisterSharedValidationInterface(std::shared_ptr< CValidationInterface > callbacks)
Unregister subscriber.
Implement this to subscribe to events generated in validation.
TestInterface(std::function< void()> on_call=nullptr, std::function< void()> on_destroy=nullptr)
BOOST_AUTO_TEST_SUITE_END()
void BlockChecked(const CBlock &block, const BlockValidationState &state) override
Notifies listeners of a block validation result.
CMainSignals & GetMainSignals()
void BlockChecked(const CBlock &, const BlockValidationState &) override
Notifies listeners of a block validation result.
std::function< void()> m_on_call
static RPCHelpMan generate()
Definition: mining.cpp:238
void BlockChecked(const CBlock &, const BlockValidationState &)
#define BOOST_CHECK(expr)
Definition: object.cpp:17