Skip to content

Commit 2e4e9b9

Browse files
committed
tests: refactor versionbits unit test
Base the unit test directly on `VersionBitsConditionChecker`, slightly improving coverage, in particular adding coverage for the the logic regarding setting the TOP_BITS.
1 parent 525c00f commit 2e4e9b9

File tree

2 files changed

+52
-42
lines changed

2 files changed

+52
-42
lines changed

src/test/versionbits_tests.cpp

Lines changed: 50 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -16,39 +16,41 @@
1616
/* Define a virtual block time, one block per 10 minutes after Nov 14 2014, 0:55:36am */
1717
static int32_t TestTime(int nHeight) { return 1415926536 + 600 * nHeight; }
1818

19-
class TestConditionChecker : public AbstractThresholdConditionChecker
19+
class TestConditionChecker final : public VersionBitsConditionChecker
2020
{
2121
private:
2222
mutable ThresholdConditionCache cache;
2323

2424
public:
25-
int64_t BeginTime() const override { return TestTime(10000); }
26-
int64_t EndTime() const override { return TestTime(20000); }
27-
int Period() const override { return 1000; }
28-
int Threshold() const override { return 900; }
29-
bool Condition(const CBlockIndex* pindex) const override { return (pindex->nVersion & 0x100); }
30-
31-
ThresholdState GetStateFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateFor(pindexPrev, cache); }
32-
int GetStateSinceHeightFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor(pindexPrev, cache); }
33-
};
25+
// constructor is implicit to allow for easier initialization of vector<TestConditionChecker>
26+
explicit(false) TestConditionChecker(const Consensus::BIP9Deployment& dep) : VersionBitsConditionChecker{dep} { }
27+
~TestConditionChecker() override = default;
3428

35-
class TestDelayedActivationConditionChecker : public TestConditionChecker
36-
{
37-
public:
38-
int MinActivationHeight() const override { return 15000; }
39-
};
40-
41-
class TestAlwaysActiveConditionChecker : public TestConditionChecker
42-
{
43-
public:
44-
int64_t BeginTime() const override { return Consensus::BIP9Deployment::ALWAYS_ACTIVE; }
29+
ThresholdState StateFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateFor(pindexPrev, cache); }
30+
int StateSinceHeightFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor(pindexPrev, cache); }
31+
void clear() { cache.clear(); }
4532
};
4633

47-
class TestNeverActiveConditionChecker : public TestConditionChecker
34+
namespace {
35+
struct Deployments
4836
{
49-
public:
50-
int64_t BeginTime() const override { return Consensus::BIP9Deployment::NEVER_ACTIVE; }
37+
const Consensus::BIP9Deployment normal{
38+
.bit = 8,
39+
.nStartTime = TestTime(10000),
40+
.nTimeout = TestTime(20000),
41+
.min_activation_height = 0,
42+
.period = 1000,
43+
.threshold = 900,
44+
};
45+
Consensus::BIP9Deployment always, never, delayed;
46+
Deployments()
47+
{
48+
delayed = normal; delayed.min_activation_height = 15000;
49+
always = normal; always.nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
50+
never = normal; never.nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE;
51+
}
5152
};
53+
}
5254

5355
#define CHECKERS 6
5456

@@ -58,22 +60,28 @@ class VersionBitsTester
5860
// A fake blockchain
5961
std::vector<CBlockIndex*> vpblock;
6062

63+
// Used to automatically set the top bits for manual calls to Mine()
64+
const int32_t nVersionBase{0};
65+
66+
// Setup BIP9Deployment structs for the checkers
67+
const Deployments test_deployments;
68+
6169
// 6 independent checkers for the same bit.
6270
// The first one performs all checks, the second only 50%, the third only 25%, etc...
6371
// This is to test whether lack of cached information leads to the same results.
64-
TestConditionChecker checker[CHECKERS];
72+
std::vector<TestConditionChecker> checker{CHECKERS, {test_deployments.normal}};
6573
// Another 6 that assume delayed activation
66-
TestDelayedActivationConditionChecker checker_delayed[CHECKERS];
74+
std::vector<TestConditionChecker> checker_delayed{CHECKERS, {test_deployments.delayed}};
6775
// Another 6 that assume always active activation
68-
TestAlwaysActiveConditionChecker checker_always[CHECKERS];
76+
std::vector<TestConditionChecker> checker_always{CHECKERS, {test_deployments.always}};
6977
// Another 6 that assume never active activation
70-
TestNeverActiveConditionChecker checker_never[CHECKERS];
78+
std::vector<TestConditionChecker> checker_never{CHECKERS, {test_deployments.never}};
7179

7280
// Test counter (to identify failures)
7381
int num{1000};
7482

7583
public:
76-
VersionBitsTester(FastRandomContext& rng) : m_rng{rng} {}
84+
explicit VersionBitsTester(FastRandomContext& rng, int32_t nVersionBase=0) : m_rng{rng}, nVersionBase{nVersionBase} { }
7785

7886
VersionBitsTester& Reset() {
7987
// Have each group of tests be counted by the 1000s part, starting at 1000
@@ -83,10 +91,10 @@ class VersionBitsTester
8391
delete vpblock[i];
8492
}
8593
for (unsigned int i = 0; i < CHECKERS; i++) {
86-
checker[i] = TestConditionChecker();
87-
checker_delayed[i] = TestDelayedActivationConditionChecker();
88-
checker_always[i] = TestAlwaysActiveConditionChecker();
89-
checker_never[i] = TestNeverActiveConditionChecker();
94+
checker[i].clear();
95+
checker_delayed[i].clear();
96+
checker_always[i].clear();
97+
checker_never[i].clear();
9098
}
9199
vpblock.clear();
92100
return *this;
@@ -102,7 +110,7 @@ class VersionBitsTester
102110
pindex->nHeight = vpblock.size();
103111
pindex->pprev = Tip();
104112
pindex->nTime = nTime;
105-
pindex->nVersion = nVersion;
113+
pindex->nVersion = (nVersionBase | nVersion);
106114
pindex->BuildSkip();
107115
vpblock.push_back(pindex);
108116
}
@@ -119,10 +127,10 @@ class VersionBitsTester
119127
const CBlockIndex* tip = Tip();
120128
for (int i = 0; i < CHECKERS; i++) {
121129
if (m_rng.randbits(i) == 0) {
122-
BOOST_CHECK_MESSAGE(checker[i].GetStateSinceHeightFor(tip) == height, strprintf("Test %i for StateSinceHeight", num));
123-
BOOST_CHECK_MESSAGE(checker_delayed[i].GetStateSinceHeightFor(tip) == height_delayed, strprintf("Test %i for StateSinceHeight (delayed)", num));
124-
BOOST_CHECK_MESSAGE(checker_always[i].GetStateSinceHeightFor(tip) == 0, strprintf("Test %i for StateSinceHeight (always active)", num));
125-
BOOST_CHECK_MESSAGE(checker_never[i].GetStateSinceHeightFor(tip) == 0, strprintf("Test %i for StateSinceHeight (never active)", num));
130+
BOOST_CHECK_MESSAGE(checker[i].StateSinceHeightFor(tip) == height, strprintf("Test %i for StateSinceHeight", num));
131+
BOOST_CHECK_MESSAGE(checker_delayed[i].StateSinceHeightFor(tip) == height_delayed, strprintf("Test %i for StateSinceHeight (delayed)", num));
132+
BOOST_CHECK_MESSAGE(checker_always[i].StateSinceHeightFor(tip) == 0, strprintf("Test %i for StateSinceHeight (always active)", num));
133+
BOOST_CHECK_MESSAGE(checker_never[i].StateSinceHeightFor(tip) == 0, strprintf("Test %i for StateSinceHeight (never active)", num));
126134
}
127135
}
128136
num++;
@@ -145,10 +153,10 @@ class VersionBitsTester
145153
const CBlockIndex* pindex = Tip();
146154
for (int i = 0; i < CHECKERS; i++) {
147155
if (m_rng.randbits(i) == 0) {
148-
ThresholdState got = checker[i].GetStateFor(pindex);
149-
ThresholdState got_delayed = checker_delayed[i].GetStateFor(pindex);
150-
ThresholdState got_always = checker_always[i].GetStateFor(pindex);
151-
ThresholdState got_never = checker_never[i].GetStateFor(pindex);
156+
ThresholdState got = checker[i].StateFor(pindex);
157+
ThresholdState got_delayed = checker_delayed[i].StateFor(pindex);
158+
ThresholdState got_always = checker_always[i].StateFor(pindex);
159+
ThresholdState got_never = checker_never[i].StateFor(pindex);
152160
// nHeight of the next block. If vpblock is empty, the next (ie first)
153161
// block should be the genesis block with nHeight == 0.
154162
int height = pindex == nullptr ? 0 : pindex->nHeight + 1;
@@ -180,7 +188,7 @@ BOOST_AUTO_TEST_CASE(versionbits_test)
180188
{
181189
for (int i = 0; i < 64; i++) {
182190
// DEFINED -> STARTED after timeout reached -> FAILED
183-
VersionBitsTester(m_rng).TestDefined().TestStateSinceHeight(0)
191+
VersionBitsTester(m_rng, VERSIONBITS_TOP_BITS).TestDefined().TestStateSinceHeight(0)
184192
.Mine(1, TestTime(1), 0x100).TestDefined().TestStateSinceHeight(0)
185193
.Mine(11, TestTime(11), 0x100).TestDefined().TestStateSinceHeight(0)
186194
.Mine(989, TestTime(989), 0x100).TestDefined().TestStateSinceHeight(0)

src/versionbits_impl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class AbstractThresholdConditionChecker {
3838
virtual int Threshold() const =0;
3939

4040
public:
41+
virtual ~AbstractThresholdConditionChecker() = default;
42+
4143
/** Returns the numerical statistics of an in-progress BIP9 softfork in the period including pindex
4244
* If provided, signalling_blocks is set to true/false based on whether each block in the period signalled
4345
*/

0 commit comments

Comments
 (0)