Bitcoin Core  27.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>
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  m_node.validation_signals->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>();
40  m_node.validation_signals->RegisterSharedValidationInterface(sub);
41  m_node.validation_signals->UnregisterSharedValidationInterface(sub);
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(ValidationSignals& signals, 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)), m_signals{signals}
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  void Call()
68  {
69  CBlock block;
71  m_signals.BlockChecked(block, state);
72  }
73  std::function<void()> m_on_call;
74  std::function<void()> m_on_destroy;
76 };
77 
78 // Regression test to ensure UnregisterAllValidationInterfaces calls don't
79 // destroy a validation interface while it is being called. Bug:
80 // https://github.com/bitcoin/bitcoin/pull/18551
81 BOOST_AUTO_TEST_CASE(unregister_all_during_call)
82 {
83  bool destroyed = false;
84  auto shared{std::make_shared<TestInterface>(
86  [&] {
87  // First call should decrements reference count 2 -> 1
88  m_node.validation_signals->UnregisterAllValidationInterfaces();
89  BOOST_CHECK(!destroyed);
90  // Second call should not decrement reference count 1 -> 0
91  m_node.validation_signals->UnregisterAllValidationInterfaces();
92  BOOST_CHECK(!destroyed);
93  },
94  [&] { destroyed = true; })};
95  m_node.validation_signals->RegisterSharedValidationInterface(shared);
96  BOOST_CHECK(shared.use_count() == 2);
97  shared->Call();
98  BOOST_CHECK(shared.use_count() == 1);
99  BOOST_CHECK(!destroyed);
100  shared.reset();
101  BOOST_CHECK(destroyed);
102 }
103 
node::NodeContext m_node
Definition: bitcoin-gui.cpp:37
Definition: block.h:69
Implement this to subscribe to events generated in validation and mempool.
ValidationSignals & m_signals
TestInterface(ValidationSignals &signals, 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
void BlockChecked(const CBlock &, const BlockValidationState &)
BOOST_AUTO_TEST_SUITE_END()
#define BOOST_CHECK(expr)
Definition: object.cpp:17
static RPCHelpMan generate()
Definition: mining.cpp:250
Testing setup that performs all steps up until right before ChainstateManager gets initialized.
Definition: setup_common.h:69
void BlockChecked(const CBlock &, const BlockValidationState &) override
Notifies listeners of a block validation result.
std::unique_ptr< ValidationSignals > validation_signals
Issues calls about blocks and transactions.
Definition: context.h:77
BOOST_AUTO_TEST_CASE(unregister_validation_interface_race)