Bitcoin Core
32.99.0
P2P Digital Currency
Loading...
Searching...
No Matches
src
test
coinscachepair_tests.cpp
Go to the documentation of this file.
1
// Copyright (c) 2024-present 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 <coins.h>
6
7
#include <boost/test/unit_test.hpp>
8
9
#include <list>
10
11
BOOST_AUTO_TEST_SUITE
(
coinscachepair_tests
)
12
13
static
constexpr
auto
NUM_NODES
{4};
14
15
std::list<CoinsCachePair>
CreatePairs
(
CoinsCachePair
&
sentinel
)
16
{
17
std::list<CoinsCachePair>
nodes
;
18
for
(
auto
i{0}; i <
NUM_NODES
; ++i) {
19
nodes
.emplace_back();
20
21
auto
node
{std::prev(
nodes
.end())};
22
CCoinsCacheEntry::SetDirty
(*
node
,
sentinel
);
23
24
BOOST_CHECK
(
node
->second.IsDirty());
25
BOOST_CHECK
(!
node
->second.IsFresh());
26
BOOST_CHECK_EQUAL
(
node
->second.Next(), &
sentinel
);
27
BOOST_CHECK_EQUAL
(
sentinel
.second.Prev(), &(*
node
));
28
29
if
(i > 0) {
30
BOOST_CHECK_EQUAL
(std::prev(
node
)->
second
.Next(), &(*
node
));
31
BOOST_CHECK_EQUAL
(
node
->second.Prev(), &(*std::prev(
node
)));
32
}
33
}
34
return
nodes
;
35
}
36
37
BOOST_AUTO_TEST_CASE
(
linked_list_iteration
)
38
{
39
CoinsCachePair
sentinel
;
40
sentinel
.second.SelfRef(
sentinel
);
41
auto
nodes
{
CreatePairs
(
sentinel
)};
42
43
// Check iterating through pairs is identical to iterating through a list
44
auto
node
{
sentinel
.second.Next()};
45
for
(
const
auto
& expected :
nodes
) {
46
BOOST_CHECK_EQUAL
(&expected,
node
);
47
node
=
node
->second.Next();
48
}
49
BOOST_CHECK_EQUAL
(
node
, &
sentinel
);
50
51
// Check iterating through pairs is identical to iterating through a list
52
// Clear the state during iteration
53
node
=
sentinel
.second.Next();
54
for
(
const
auto
& expected :
nodes
) {
55
BOOST_CHECK_EQUAL
(&expected,
node
);
56
auto
next =
node
->second.Next();
57
node
->second.SetClean();
58
node
= next;
59
}
60
BOOST_CHECK_EQUAL
(
node
, &
sentinel
);
61
// Check that sentinel's next and prev are itself
62
BOOST_CHECK_EQUAL
(
sentinel
.second.Next(), &
sentinel
);
63
BOOST_CHECK_EQUAL
(
sentinel
.second.Prev(), &
sentinel
);
64
65
// Delete the nodes from the list to make sure there are no dangling pointers
66
for
(
auto
it{
nodes
.begin()}; it !=
nodes
.end(); it =
nodes
.erase(it)) {
67
BOOST_CHECK
(!it->second.IsDirty());
68
BOOST_CHECK
(!it->second.IsFresh());
69
}
70
}
71
72
BOOST_AUTO_TEST_CASE
(
linked_list_iterate_erase
)
73
{
74
CoinsCachePair
sentinel
;
75
sentinel
.second.SelfRef(
sentinel
);
76
auto
nodes
{
CreatePairs
(
sentinel
)};
77
78
// Check iterating through pairs is identical to iterating through a list
79
// Erase the nodes as we iterate through, but don't clear state
80
// The state will be cleared by the CCoinsCacheEntry's destructor
81
auto
node
{
sentinel
.second.Next()};
82
for
(
auto
expected{
nodes
.begin()}; expected !=
nodes
.end(); expected =
nodes
.erase(expected)) {
83
BOOST_CHECK_EQUAL
(&(*expected),
node
);
84
node
=
node
->second.Next();
85
}
86
BOOST_CHECK_EQUAL
(
node
, &
sentinel
);
87
88
// Check that sentinel's next and prev are itself
89
BOOST_CHECK_EQUAL
(
sentinel
.second.Next(), &
sentinel
);
90
BOOST_CHECK_EQUAL
(
sentinel
.second.Prev(), &
sentinel
);
91
}
92
93
BOOST_AUTO_TEST_CASE
(
linked_list_random_deletion
)
94
{
95
CoinsCachePair
sentinel
;
96
sentinel
.second.SelfRef(
sentinel
);
97
auto
nodes
{
CreatePairs
(
sentinel
)};
98
99
// Create linked list sentinel->n1->n2->n3->n4->sentinel
100
auto
n1
{
nodes
.begin()};
101
auto
n2
{std::next(
n1
)};
102
auto
n3
{std::next(
n2
)};
103
auto
n4
{std::next(
n3
)};
104
105
// Delete n2
106
// sentinel->n1->n3->n4->sentinel
107
nodes
.erase(
n2
);
108
// Check that n1 now points to n3, and n3 still points to n4
109
// Also check that state was not altered
110
BOOST_CHECK
(
n1
->second.IsDirty());
111
BOOST_CHECK
(!
n1
->second.IsFresh());
112
BOOST_CHECK_EQUAL
(
n1
->second.Next(), &(*
n3
));
113
BOOST_CHECK
(
n3
->second.IsDirty());
114
BOOST_CHECK
(!
n3
->second.IsFresh());
115
BOOST_CHECK_EQUAL
(
n3
->second.Next(), &(*
n4
));
116
BOOST_CHECK_EQUAL
(
n3
->second.Prev(), &(*
n1
));
117
118
// Delete n1
119
// sentinel->n3->n4->sentinel
120
nodes
.erase(
n1
);
121
// Check that sentinel now points to n3, and n3 still points to n4
122
// Also check that state was not altered
123
BOOST_CHECK
(
n3
->second.IsDirty());
124
BOOST_CHECK
(!
n3
->second.IsFresh());
125
BOOST_CHECK_EQUAL
(
sentinel
.second.Next(), &(*
n3
));
126
BOOST_CHECK_EQUAL
(
n3
->second.Next(), &(*
n4
));
127
BOOST_CHECK_EQUAL
(
n3
->second.Prev(), &
sentinel
);
128
129
// Delete n4
130
// sentinel->n3->sentinel
131
nodes
.erase(
n4
);
132
// Check that sentinel still points to n3, and n3 points to sentinel
133
// Also check that state was not altered
134
BOOST_CHECK
(
n3
->second.IsDirty());
135
BOOST_CHECK
(!
n3
->second.IsFresh());
136
BOOST_CHECK_EQUAL
(
sentinel
.second.Next(), &(*
n3
));
137
BOOST_CHECK_EQUAL
(
n3
->second.Next(), &
sentinel
);
138
BOOST_CHECK_EQUAL
(
sentinel
.second.Prev(), &(*
n3
));
139
140
// Delete n3
141
// sentinel->sentinel
142
nodes
.erase(
n3
);
143
// Check that sentinel's next and prev are itself
144
BOOST_CHECK_EQUAL
(
sentinel
.second.Next(), &
sentinel
);
145
BOOST_CHECK_EQUAL
(
sentinel
.second.Prev(), &
sentinel
);
146
}
147
148
BOOST_AUTO_TEST_CASE
(
linked_list_set_state
)
149
{
150
CoinsCachePair
sentinel
;
151
sentinel
.second.SelfRef(
sentinel
);
152
CoinsCachePair
n1
;
153
CoinsCachePair
n2
;
154
155
// Check that setting DIRTY inserts it into linked list and sets state
156
CCoinsCacheEntry::SetDirty
(
n1
,
sentinel
);
157
BOOST_CHECK
(
n1
.second.IsDirty());
158
BOOST_CHECK
(!
n1
.second.IsFresh());
159
BOOST_CHECK_EQUAL
(
n1
.second.Next(), &
sentinel
);
160
BOOST_CHECK_EQUAL
(
n1
.second.Prev(), &
sentinel
);
161
BOOST_CHECK_EQUAL
(
sentinel
.second.Next(), &
n1
);
162
BOOST_CHECK_EQUAL
(
sentinel
.second.Prev(), &
n1
);
163
164
// Check that setting FRESH on new node inserts it after n1
165
CCoinsCacheEntry::SetFresh
(
n2
,
sentinel
);
166
BOOST_CHECK
(
n2
.second.IsFresh());
167
BOOST_CHECK
(!
n2
.second.IsDirty());
168
BOOST_CHECK_EQUAL
(
n2
.second.Next(), &
sentinel
);
169
BOOST_CHECK_EQUAL
(
n2
.second.Prev(), &
n1
);
170
BOOST_CHECK_EQUAL
(
n1
.second.Next(), &
n2
);
171
BOOST_CHECK_EQUAL
(
sentinel
.second.Prev(), &
n2
);
172
173
// Check that we can set extra state, but they don't change our position
174
CCoinsCacheEntry::SetFresh
(
n1
,
sentinel
);
175
BOOST_CHECK
(
n1
.second.IsDirty());
176
BOOST_CHECK
(
n1
.second.IsFresh());
177
BOOST_CHECK_EQUAL
(
n1
.second.Next(), &
n2
);
178
BOOST_CHECK_EQUAL
(
n1
.second.Prev(), &
sentinel
);
179
BOOST_CHECK_EQUAL
(
sentinel
.second.Next(), &
n1
);
180
BOOST_CHECK_EQUAL
(
n2
.second.Prev(), &
n1
);
181
182
// Check that we can clear state then re-set it
183
n1
.second.SetClean();
184
BOOST_CHECK
(!
n1
.second.IsDirty());
185
BOOST_CHECK
(!
n1
.second.IsFresh());
186
BOOST_CHECK_EQUAL
(
sentinel
.second.Next(), &
n2
);
187
BOOST_CHECK_EQUAL
(
sentinel
.second.Prev(), &
n2
);
188
BOOST_CHECK_EQUAL
(
n2
.second.Next(), &
sentinel
);
189
BOOST_CHECK_EQUAL
(
n2
.second.Prev(), &
sentinel
);
190
191
// Calling `SetClean` a second time has no effect
192
n1
.second.SetClean();
193
BOOST_CHECK
(!
n1
.second.IsDirty());
194
BOOST_CHECK
(!
n1
.second.IsFresh());
195
BOOST_CHECK_EQUAL
(
sentinel
.second.Next(), &
n2
);
196
BOOST_CHECK_EQUAL
(
sentinel
.second.Prev(), &
n2
);
197
BOOST_CHECK_EQUAL
(
n2
.second.Next(), &
sentinel
);
198
BOOST_CHECK_EQUAL
(
n2
.second.Prev(), &
sentinel
);
199
200
// Adding DIRTY re-inserts it after n2
201
CCoinsCacheEntry::SetDirty
(
n1
,
sentinel
);
202
BOOST_CHECK
(
n1
.second.IsDirty());
203
BOOST_CHECK
(!
n1
.second.IsFresh());
204
BOOST_CHECK_EQUAL
(
n2
.second.Next(), &
n1
);
205
BOOST_CHECK_EQUAL
(
n1
.second.Prev(), &
n2
);
206
BOOST_CHECK_EQUAL
(
n1
.second.Next(), &
sentinel
);
207
BOOST_CHECK_EQUAL
(
sentinel
.second.Prev(), &
n1
);
208
}
209
210
BOOST_AUTO_TEST_SUITE_END
()
CoinsCachePair
std::pair< const COutPoint, CCoinsCacheEntry > CoinsCachePair
Definition
coins.h:104
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(linked_list_iteration)
Definition
coinscachepair_tests.cpp:37
NUM_NODES
static constexpr auto NUM_NODES
Definition
coinscachepair_tests.cpp:13
CreatePairs
std::list< CoinsCachePair > CreatePairs(CoinsCachePair &sentinel)
Definition
coinscachepair_tests.cpp:15
BOOST_AUTO_TEST_SUITE_END
BOOST_AUTO_TEST_SUITE_END()
node
Definition
messages.h:21
BOOST_CHECK_EQUAL
#define BOOST_CHECK_EQUAL(v1, v2)
Definition
object.cpp:17
BOOST_CHECK
#define BOOST_CHECK(expr)
Definition
object.cpp:16
CCoinsCacheEntry::SetFresh
static void SetFresh(CoinsCachePair &pair, CoinsCachePair &sentinel) noexcept
Definition
coins.h:184
CCoinsCacheEntry::SetDirty
static void SetDirty(CoinsCachePair &pair, CoinsCachePair &sentinel) noexcept
Definition
coins.h:183
Ticks
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.
Definition
time.h:82
Generated on Thu Oct 22 2026 20:00:33 for Bitcoin Core by
1.9.8