LCOV - code coverage report
Current view: top level - src/test - validationinterface_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 53 53 100.0 %
Date: 2020-09-26 01:30:44 Functions: 29 30 96.7 %

          Line data    Source code
       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>
       9             : #include <test/util/setup_common.h>
      10             : #include <util/check.h>
      11             : #include <validationinterface.h>
      12             : 
      13          89 : BOOST_FIXTURE_TEST_SUITE(validationinterface_tests, TestingSetup)
      14             : 
      15      500000 : struct TestSubscriberNoop final : public CValidationInterface {
      16        2768 :     void BlockChecked(const CBlock&, const BlockValidationState&) override {}
      17             : };
      18             : 
      19          95 : BOOST_AUTO_TEST_CASE(unregister_validation_interface_race)
      20             : {
      21           1 :     std::atomic<bool> generate{true};
      22             : 
      23             :     // Start thread to generate notifications
      24           2 :     std::thread gen{[&] {
      25           1 :         const CBlock block_dummy;
      26           1 :         BlockValidationState state_dummy;
      27       12908 :         while (generate) {
      28       12907 :             GetMainSignals().BlockChecked(block_dummy, state_dummy);
      29             :         }
      30           1 :     }};
      31             : 
      32             :     // Start thread to consume notifications
      33           2 :     std::thread sub{[&] {
      34             :         // keep going for about 1 sec, which is 250k iterations
      35      250001 :         for (int i = 0; i < 250000; i++) {
      36      250000 :             auto sub = std::make_shared<TestSubscriberNoop>();
      37      250000 :             RegisterSharedValidationInterface(sub);
      38      250000 :             UnregisterSharedValidationInterface(sub);
      39      250000 :         }
      40             :         // tell the other thread we are done
      41           1 :         generate = false;
      42           1 :     }};
      43             : 
      44           1 :     gen.join();
      45           1 :     sub.join();
      46           1 :     BOOST_CHECK(!generate);
      47           1 : }
      48             : 
      49             : class TestInterface : public CValidationInterface
      50             : {
      51             : public:
      52           2 :     TestInterface(std::function<void()> on_call = nullptr, std::function<void()> on_destroy = nullptr)
      53           1 :         : m_on_call(std::move(on_call)), m_on_destroy(std::move(on_destroy))
      54           2 :     {
      55           2 :     }
      56           2 :     virtual ~TestInterface()
      57           2 :     {
      58           1 :         if (m_on_destroy) m_on_destroy();
      59           2 :     }
      60           1 :     void BlockChecked(const CBlock& block, const BlockValidationState& state) override
      61             :     {
      62           1 :         if (m_on_call) m_on_call();
      63           1 :     }
      64           1 :     static void Call()
      65             :     {
      66           1 :         CBlock block;
      67           1 :         BlockValidationState state;
      68           1 :         GetMainSignals().BlockChecked(block, state);
      69           1 :     }
      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
      77          95 : BOOST_AUTO_TEST_CASE(unregister_all_during_call)
      78             : {
      79           1 :     bool destroyed = false;
      80           2 :     RegisterSharedValidationInterface(std::make_shared<TestInterface>(
      81           2 :         [&] {
      82             :             // First call should decrements reference count 2 -> 1
      83           1 :             UnregisterAllValidationInterfaces();
      84           1 :             BOOST_CHECK(!destroyed);
      85             :             // Second call should not decrement reference count 1 -> 0
      86           1 :             UnregisterAllValidationInterfaces();
      87           1 :             BOOST_CHECK(!destroyed);
      88           1 :         },
      89           2 :         [&] { destroyed = true; }));
      90           1 :     TestInterface::Call();
      91           1 :     BOOST_CHECK(destroyed);
      92           1 : }
      93             : 
      94          89 : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.15