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