Bitcoin Core
31.1.0
P2P Digital Currency
Toggle main menu visibility
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() && !
node
->second.IsFresh());
25
BOOST_CHECK_EQUAL
(
node
->second.Next(), &sentinel);
26
BOOST_CHECK_EQUAL
(sentinel.second.Prev(), &(*
node
));
27
28
if
(i > 0) {
29
BOOST_CHECK_EQUAL
(std::prev(
node
)->second.Next(), &(*
node
));
30
BOOST_CHECK_EQUAL
(
node
->second.Prev(), &(*std::prev(
node
)));
31
}
32
}
33
return
nodes;
34
}
35
36
BOOST_AUTO_TEST_CASE
(linked_list_iteration)
37
{
38
CoinsCachePair
sentinel;
39
sentinel.second.SelfRef(sentinel);
40
auto
nodes{
CreatePairs
(sentinel)};
41
42
// Check iterating through pairs is identical to iterating through a list
43
auto
node
{sentinel.second.Next()};
44
for
(
const
auto
& expected : nodes) {
45
BOOST_CHECK_EQUAL
(&expected,
node
);
46
node
=
node
->second.Next();
47
}
48
BOOST_CHECK_EQUAL
(
node
, &sentinel);
49
50
// Check iterating through pairs is identical to iterating through a list
51
// Clear the state during iteration
52
node
= sentinel.second.Next();
53
for
(
const
auto
& expected : nodes) {
54
BOOST_CHECK_EQUAL
(&expected,
node
);
55
auto
next =
node
->second.Next();
56
node
->second.SetClean();
57
node
= next;
58
}
59
BOOST_CHECK_EQUAL
(
node
, &sentinel);
60
// Check that sentinel's next and prev are itself
61
BOOST_CHECK_EQUAL
(sentinel.second.Next(), &sentinel);
62
BOOST_CHECK_EQUAL
(sentinel.second.Prev(), &sentinel);
63
64
// Delete the nodes from the list to make sure there are no dangling pointers
65
for
(
auto
it{nodes.begin()}; it != nodes.end(); it = nodes.erase(it)) {
66
BOOST_CHECK
(!it->second.IsDirty() && !it->second.IsFresh());
67
}
68
}
69
70
BOOST_AUTO_TEST_CASE
(linked_list_iterate_erase)
71
{
72
CoinsCachePair
sentinel;
73
sentinel.second.SelfRef(sentinel);
74
auto
nodes{
CreatePairs
(sentinel)};
75
76
// Check iterating through pairs is identical to iterating through a list
77
// Erase the nodes as we iterate through, but don't clear state
78
// The state will be cleared by the CCoinsCacheEntry's destructor
79
auto
node
{sentinel.second.Next()};
80
for
(
auto
expected{nodes.begin()}; expected != nodes.end(); expected = nodes.erase(expected)) {
81
BOOST_CHECK_EQUAL
(&(*expected),
node
);
82
node
=
node
->second.Next();
83
}
84
BOOST_CHECK_EQUAL
(
node
, &sentinel);
85
86
// Check that sentinel's next and prev are itself
87
BOOST_CHECK_EQUAL
(sentinel.second.Next(), &sentinel);
88
BOOST_CHECK_EQUAL
(sentinel.second.Prev(), &sentinel);
89
}
90
91
BOOST_AUTO_TEST_CASE
(linked_list_random_deletion)
92
{
93
CoinsCachePair
sentinel;
94
sentinel.second.SelfRef(sentinel);
95
auto
nodes{
CreatePairs
(sentinel)};
96
97
// Create linked list sentinel->n1->n2->n3->n4->sentinel
98
auto
n1{nodes.begin()};
99
auto
n2{std::next(n1)};
100
auto
n3{std::next(n2)};
101
auto
n4{std::next(n3)};
102
103
// Delete n2
104
// sentinel->n1->n3->n4->sentinel
105
nodes.erase(n2);
106
// Check that n1 now points to n3, and n3 still points to n4
107
// Also check that state was not altered
108
BOOST_CHECK
(n1->second.IsDirty() && !n1->second.IsFresh());
109
BOOST_CHECK_EQUAL
(n1->second.Next(), &(*n3));
110
BOOST_CHECK
(n3->second.IsDirty() && !n3->second.IsFresh());
111
BOOST_CHECK_EQUAL
(n3->second.Next(), &(*n4));
112
BOOST_CHECK_EQUAL
(n3->second.Prev(), &(*n1));
113
114
// Delete n1
115
// sentinel->n3->n4->sentinel
116
nodes.erase(n1);
117
// Check that sentinel now points to n3, and n3 still points to n4
118
// Also check that state was not altered
119
BOOST_CHECK
(n3->second.IsDirty() && !n3->second.IsFresh());
120
BOOST_CHECK_EQUAL
(sentinel.second.Next(), &(*n3));
121
BOOST_CHECK_EQUAL
(n3->second.Next(), &(*n4));
122
BOOST_CHECK_EQUAL
(n3->second.Prev(), &sentinel);
123
124
// Delete n4
125
// sentinel->n3->sentinel
126
nodes.erase(n4);
127
// Check that sentinel still points to n3, and n3 points to sentinel
128
// Also check that state was not altered
129
BOOST_CHECK
(n3->second.IsDirty() && !n3->second.IsFresh());
130
BOOST_CHECK_EQUAL
(sentinel.second.Next(), &(*n3));
131
BOOST_CHECK_EQUAL
(n3->second.Next(), &sentinel);
132
BOOST_CHECK_EQUAL
(sentinel.second.Prev(), &(*n3));
133
134
// Delete n3
135
// sentinel->sentinel
136
nodes.erase(n3);
137
// Check that sentinel's next and prev are itself
138
BOOST_CHECK_EQUAL
(sentinel.second.Next(), &sentinel);
139
BOOST_CHECK_EQUAL
(sentinel.second.Prev(), &sentinel);
140
}
141
142
BOOST_AUTO_TEST_CASE
(linked_list_set_state)
143
{
144
CoinsCachePair
sentinel;
145
sentinel.second.SelfRef(sentinel);
146
CoinsCachePair
n1;
147
CoinsCachePair
n2;
148
149
// Check that setting DIRTY inserts it into linked list and sets state
150
CCoinsCacheEntry::SetDirty
(n1, sentinel);
151
BOOST_CHECK
(n1.second.IsDirty() && !n1.second.IsFresh());
152
BOOST_CHECK_EQUAL
(n1.second.Next(), &sentinel);
153
BOOST_CHECK_EQUAL
(n1.second.Prev(), &sentinel);
154
BOOST_CHECK_EQUAL
(sentinel.second.Next(), &n1);
155
BOOST_CHECK_EQUAL
(sentinel.second.Prev(), &n1);
156
157
// Check that setting FRESH on new node inserts it after n1
158
CCoinsCacheEntry::SetFresh
(n2, sentinel);
159
BOOST_CHECK
(n2.second.IsFresh() && !n2.second.IsDirty());
160
BOOST_CHECK_EQUAL
(n2.second.Next(), &sentinel);
161
BOOST_CHECK_EQUAL
(n2.second.Prev(), &n1);
162
BOOST_CHECK_EQUAL
(n1.second.Next(), &n2);
163
BOOST_CHECK_EQUAL
(sentinel.second.Prev(), &n2);
164
165
// Check that we can set extra state, but they don't change our position
166
CCoinsCacheEntry::SetFresh
(n1, sentinel);
167
BOOST_CHECK
(n1.second.IsDirty() && n1.second.IsFresh());
168
BOOST_CHECK_EQUAL
(n1.second.Next(), &n2);
169
BOOST_CHECK_EQUAL
(n1.second.Prev(), &sentinel);
170
BOOST_CHECK_EQUAL
(sentinel.second.Next(), &n1);
171
BOOST_CHECK_EQUAL
(n2.second.Prev(), &n1);
172
173
// Check that we can clear state then re-set it
174
n1.second.SetClean();
175
BOOST_CHECK
(!n1.second.IsDirty() && !n1.second.IsFresh());
176
BOOST_CHECK_EQUAL
(sentinel.second.Next(), &n2);
177
BOOST_CHECK_EQUAL
(sentinel.second.Prev(), &n2);
178
BOOST_CHECK_EQUAL
(n2.second.Next(), &sentinel);
179
BOOST_CHECK_EQUAL
(n2.second.Prev(), &sentinel);
180
181
// Calling `SetClean` a second time has no effect
182
n1.second.SetClean();
183
BOOST_CHECK
(!n1.second.IsDirty() && !n1.second.IsFresh());
184
BOOST_CHECK_EQUAL
(sentinel.second.Next(), &n2);
185
BOOST_CHECK_EQUAL
(sentinel.second.Prev(), &n2);
186
BOOST_CHECK_EQUAL
(n2.second.Next(), &sentinel);
187
BOOST_CHECK_EQUAL
(n2.second.Prev(), &sentinel);
188
189
// Adding DIRTY re-inserts it after n2
190
CCoinsCacheEntry::SetDirty
(n1, sentinel);
191
BOOST_CHECK
(n1.second.IsDirty() && !n1.second.IsFresh());
192
BOOST_CHECK_EQUAL
(n2.second.Next(), &n1);
193
BOOST_CHECK_EQUAL
(n1.second.Prev(), &n2);
194
BOOST_CHECK_EQUAL
(n1.second.Next(), &sentinel);
195
BOOST_CHECK_EQUAL
(sentinel.second.Prev(), &n1);
196
}
197
198
BOOST_AUTO_TEST_SUITE_END
()
CoinsCachePair
std::pair< const COutPoint, CCoinsCacheEntry > CoinsCachePair
Definition
coins.h:93
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(linked_list_iteration)
Definition
coinscachepair_tests.cpp:36
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:173
CCoinsCacheEntry::SetDirty
static void SetDirty(CoinsCachePair &pair, CoinsCachePair &sentinel) noexcept
Definition
coins.h:172
Generated on
for Bitcoin Core by
1.17.0