xrpld
Toggle main menu visibility
Loading...
Searching...
No Matches
test
overlay
cluster_test.cpp
1
#include <test/jtx/TestSuite.h>
2
#include <test/unit_test/SuiteJournal.h>
3
4
#include <xrpld/overlay/Cluster.h>
5
6
#include <xrpl/basics/chrono.h>
7
#include <xrpl/beast/unit_test/suite.h>
8
#include <xrpl/config/BasicConfig.h>
9
#include <xrpl/protocol/KeyType.h>
10
#include <xrpl/protocol/PublicKey.h>
11
#include <xrpl/protocol/SecretKey.h>
12
#include <xrpl/protocol/tokens.h>
13
14
#include <
algorithm
>
15
#include <
chrono
>
16
#include <
cstddef
>
17
#include <
cstdint
>
18
#include <
memory
>
19
#include <
vector
>
20
21
namespace
xrpl::tests
{
22
23
class
cluster_test
:
public
xrpl::TestSuite
24
{
25
test::SuiteJournal
journal_
;
26
27
public
:
28
cluster_test
() :
journal_
(
"cluster_test"
, *this)
29
{
30
}
31
32
std::unique_ptr<Cluster>
33
create
(
std::vector<PublicKey>
const
& nodes)
34
{
35
auto
cluster =
std::make_unique<Cluster>
(
journal_
);
36
37
for
(
auto
const
& n : nodes)
38
cluster->update(n,
"Test"
);
39
40
return
cluster;
41
}
42
43
static
PublicKey
44
randomNode
()
45
{
46
return
derivePublicKey
(
KeyType::Secp256k1
,
randomSecretKey
());
47
}
48
49
void
50
testMembership
()
51
{
52
// The servers on the network
53
std::vector<PublicKey>
network;
54
55
while
(network.
size
() != 128)
56
network.
push_back
(
randomNode
());
57
58
{
59
testcase
(
"Membership: Empty cluster"
);
60
61
auto
c =
create
({});
62
63
for
(
auto
const
& n : network)
64
BEAST_EXPECT(!c->member(n));
65
}
66
67
{
68
testcase
(
"Membership: Non-empty cluster and none present"
);
69
70
std::vector<PublicKey>
cluster;
71
while
(cluster.
size
() != 32)
72
cluster.
push_back
(
randomNode
());
73
74
auto
c =
create
(cluster);
75
76
for
(
auto
const
& n : network)
77
BEAST_EXPECT(!c->member(n));
78
}
79
80
{
81
testcase
(
"Membership: Non-empty cluster and some present"
);
82
83
std::vector<PublicKey>
cluster(network.
begin
(), network.
begin
() + 16);
84
85
while
(cluster.
size
() != 32)
86
cluster.
push_back
(
randomNode
());
87
88
auto
c =
create
(cluster);
89
90
for
(
auto
const
& n : cluster)
91
BEAST_EXPECT(c->member(n));
92
93
for
(
auto
const
& n : network)
94
{
95
auto
found =
std::ranges::find
(cluster, n);
96
BEAST_EXPECT(
static_cast<
bool
>
(c->member(n)) == (found != cluster.
end
()));
97
}
98
}
99
100
{
101
testcase
(
"Membership: isMember agrees with member"
);
102
103
// Number of network nodes that also belong to the cluster.
104
std::size_t
const
overlapCount = 16;
105
106
// Total size of the cluster once padded with non-network nodes.
107
std::size_t
const
clusterSize = 32;
108
109
std::vector<PublicKey>
cluster(network.
begin
(), network.
begin
() + overlapCount);
110
111
while
(cluster.
size
() != clusterSize)
112
cluster.
push_back
(
randomNode
());
113
114
auto
c =
create
(cluster);
115
116
for
(
auto
const
& n : cluster)
117
BEAST_EXPECT(c->isMember(n));
118
119
for
(
auto
const
& n : network)
120
BEAST_EXPECT(c->isMember(n) ==
static_cast<
bool
>
(c->member(n)));
121
}
122
123
{
124
testcase
(
"Membership: Non-empty cluster and all present"
);
125
126
std::vector<PublicKey>
cluster(network.
begin
(), network.
begin
() + 32);
127
128
auto
c =
create
(cluster);
129
130
for
(
auto
const
& n : cluster)
131
BEAST_EXPECT(c->member(n));
132
133
for
(
auto
const
& n : network)
134
{
135
auto
found =
std::ranges::find
(cluster, n);
136
BEAST_EXPECT(
static_cast<
bool
>
(c->member(n)) == (found != cluster.
end
()));
137
}
138
}
139
}
140
141
void
142
testUpdating
()
143
{
144
testcase
(
"Updating"
);
145
146
auto
c =
create
({});
147
148
auto
const
node =
randomNode
();
149
auto
const
name =
toBase58
(
TokenType::NodePublic
, node);
150
std::uint32_t
const
load = 0;
151
NetClock::time_point
tick = {};
152
153
// Initial update
154
BEAST_EXPECT(c->update(node,
""
, load, tick));
155
{
156
auto
member = c->member(node);
157
BEAST_EXPECT(
static_cast<
bool
>
(member));
158
BEAST_EXPECT(member->empty());
// NOLINT(bugprone-unchecked-optional-access)
159
}
160
161
// Updating too quickly: should fail
162
BEAST_EXPECT(!c->update(node, name, load, tick));
163
{
164
auto
member = c->member(node);
165
BEAST_EXPECT(
static_cast<
bool
>
(member));
166
BEAST_EXPECT(member->empty());
// NOLINT(bugprone-unchecked-optional-access)
167
}
168
169
using namespace
std::chrono_literals;
170
171
// Updating the name (empty updates to non-empty)
172
tick += 1s;
173
BEAST_EXPECT(c->update(node, name, load, tick));
174
{
175
auto
member = c->member(node);
176
BEAST_EXPECT(
static_cast<
bool
>
(member));
177
BEAST_EXPECT(*member == name);
// NOLINT(bugprone-unchecked-optional-access)
178
}
179
180
// Updating the name (non-empty doesn't go to empty)
181
tick += 1s;
182
BEAST_EXPECT(c->update(node,
""
, load, tick));
183
{
184
auto
member = c->member(node);
185
BEAST_EXPECT(
static_cast<
bool
>
(member));
186
BEAST_EXPECT(*member == name);
// NOLINT(bugprone-unchecked-optional-access)
187
}
188
189
// Updating the name (non-empty updates to new non-empty)
190
tick += 1s;
191
BEAST_EXPECT(c->update(node,
"test"
, load, tick));
192
{
193
auto
member = c->member(node);
194
BEAST_EXPECT(
static_cast<
bool
>
(member));
195
BEAST_EXPECT(*member ==
"test"
);
// NOLINT(bugprone-unchecked-optional-access)
196
}
197
}
198
199
void
200
testConfigLoad
()
201
{
202
testcase
(
"Config Load"
);
203
204
auto
c =
std::make_unique<Cluster>
(
journal_
);
205
206
// The servers on the network
207
std::vector<PublicKey>
network;
208
209
while
(network.
size
() != 8)
210
network.
push_back
(
randomNode
());
211
212
auto
format = [](
PublicKey
const
& publicKey,
char
const
* comment =
nullptr
) {
213
auto
ret =
toBase58
(
TokenType::NodePublic
, publicKey);
214
215
if
(comment)
216
ret += comment;
217
218
return
ret;
219
};
220
221
Section
s1;
222
223
// Correct (empty) configuration
224
BEAST_EXPECT(c->load(s1));
225
BEAST_EXPECT(c->size() == 0);
226
227
// Correct configuration
228
s1.
append
(format(network[0]));
229
s1.
append
(format(network[1],
" "
));
230
s1.
append
(format(network[2],
" Comment"
));
231
s1.
append
(format(network[3],
" Multi Word Comment"
));
232
s1.
append
(format(network[4],
" Leading Whitespace"
));
233
s1.
append
(format(network[5],
" Trailing Whitespace "
));
234
s1.
append
(format(network[6],
" Leading & Trailing Whitespace "
));
235
s1.
append
(format(network[7],
" Leading, Trailing & Internal Whitespace "
));
236
237
BEAST_EXPECT(c->load(s1));
238
239
for
(
auto
const
& n : network)
240
BEAST_EXPECT(c->member(n));
241
242
// Incorrect configurations
243
Section
s2;
244
s2.
append
(
"NotAPublicKey"
);
245
BEAST_EXPECT(!c->load(s2));
246
247
Section
s3;
248
s3.
append
(format(network[0],
"!"
));
249
BEAST_EXPECT(!c->load(s3));
250
251
Section
s4;
252
s4.
append
(format(network[0],
"! Comment"
));
253
BEAST_EXPECT(!c->load(s4));
254
255
// Check if we properly terminate when we encounter
256
// a malformed or unparsable entry:
257
auto
const
node1 =
randomNode
();
258
auto
const
node2 =
randomNode
();
259
260
Section
s5;
261
s5.
append
(format(node1,
"XXX"
));
262
s5.
append
(format(node2));
263
BEAST_EXPECT(!c->load(s5));
264
BEAST_EXPECT(!c->member(node1));
265
BEAST_EXPECT(!c->member(node2));
266
}
267
268
void
269
run
()
override
270
{
271
testMembership
();
272
testUpdating
();
273
testConfigLoad
();
274
}
275
};
276
277
BEAST_DEFINE_TESTSUITE
(cluster, overlay,
xrpl
);
278
279
}
// namespace xrpl::tests
algorithm
std::vector::begin
T begin(T... args)
chrono
beast::unit_test::Suite::testcase
TestcaseT testcase
Memberspace for declaring test cases.
Definition
suite.h:155
xrpl::NetClock::time_point
std::chrono::time_point< NetClock > time_point
Definition
chrono.h:48
xrpl::PublicKey
A public key.
Definition
PublicKey.h:53
xrpl::Section
Holds a collection of configuration values.
Definition
BasicConfig.h:28
xrpl::Section::append
void append(std::vector< std::string > const &lines)
Append a set of lines to this section.
Definition
BasicConfig.cpp:28
xrpl::TestSuite
Definition
TestSuite.h:12
xrpl::test::SuiteJournal
Definition
SuiteJournal.h:81
xrpl::tests::cluster_test::randomNode
static PublicKey randomNode()
Definition
cluster_test.cpp:44
xrpl::tests::cluster_test::journal_
test::SuiteJournal journal_
Definition
cluster_test.cpp:25
xrpl::tests::cluster_test::run
void run() override
Runs the suite.
Definition
cluster_test.cpp:269
xrpl::tests::cluster_test::testMembership
void testMembership()
Definition
cluster_test.cpp:50
xrpl::tests::cluster_test::cluster_test
cluster_test()
Definition
cluster_test.cpp:28
xrpl::tests::cluster_test::testConfigLoad
void testConfigLoad()
Definition
cluster_test.cpp:200
xrpl::tests::cluster_test::testUpdating
void testUpdating()
Definition
cluster_test.cpp:142
xrpl::tests::cluster_test::create
std::unique_ptr< Cluster > create(std::vector< PublicKey > const &nodes)
Definition
cluster_test.cpp:33
cstddef
cstdint
std::vector::end
T end(T... args)
std::ranges::find
T find(T... args)
std::uint32_t
std::make_unique
T make_unique(T... args)
memory
xrpl::tests
Definition
LedgerNodeHelpers_test.cpp:21
xrpl::tests::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(LedgerNodeHelpers, app, xrpl)
xrpl
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition
algorithm.h:5
xrpl::KeyType::Secp256k1
@ Secp256k1
Definition
KeyType.h:9
xrpl::derivePublicKey
PublicKey derivePublicKey(KeyType type, SecretKey const &sk)
Derive the public key from a secret key.
Definition
SecretKey.cpp:306
xrpl::toBase58
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition
AccountID.cpp:95
xrpl::randomSecretKey
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
Definition
SecretKey.cpp:274
xrpl::TokenType::NodePublic
@ NodePublic
Definition
tokens.h:21
std::vector::push_back
T push_back(T... args)
std::vector::size
T size(T... args)
std::size_t
std::unique_ptr
vector
Generated by
1.17.0