rippled
Loading...
Searching...
No Matches
cluster_test.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright 2015 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <test/jtx/TestSuite.h>
21#include <test/unit_test/SuiteJournal.h>
22
23#include <xrpld/overlay/Cluster.h>
24
25#include <xrpl/basics/BasicConfig.h>
26#include <xrpl/protocol/SecretKey.h>
27
28namespace ripple {
29namespace tests {
30
32{
34
35public:
36 cluster_test() : journal_("cluster_test", *this)
37 {
38 }
39
42 {
43 auto cluster = std::make_unique<Cluster>(journal_);
44
45 for (auto const& n : nodes)
46 cluster->update(n, "Test");
47
48 return cluster;
49 }
50
56
57 void
59 {
60 // The servers on the network
62
63 while (network.size() != 128)
64 network.push_back(randomNode());
65
66 {
67 testcase("Membership: Empty cluster");
68
69 auto c = create({});
70
71 for (auto const& n : network)
72 BEAST_EXPECT(!c->member(n));
73 }
74
75 {
76 testcase("Membership: Non-empty cluster and none present");
77
79 while (cluster.size() != 32)
80 cluster.push_back(randomNode());
81
82 auto c = create(cluster);
83
84 for (auto const& n : network)
85 BEAST_EXPECT(!c->member(n));
86 }
87
88 {
89 testcase("Membership: Non-empty cluster and some present");
90
92 network.begin(), network.begin() + 16);
93
94 while (cluster.size() != 32)
95 cluster.push_back(randomNode());
96
97 auto c = create(cluster);
98
99 for (auto const& n : cluster)
100 BEAST_EXPECT(c->member(n));
101
102 for (auto const& n : network)
103 {
104 auto found = std::find(cluster.begin(), cluster.end(), n);
105 BEAST_EXPECT(
106 static_cast<bool>(c->member(n)) ==
107 (found != cluster.end()));
108 }
109 }
110
111 {
112 testcase("Membership: Non-empty cluster and all present");
113
115 network.begin(), network.begin() + 32);
116
117 auto c = create(cluster);
118
119 for (auto const& n : cluster)
120 BEAST_EXPECT(c->member(n));
121
122 for (auto const& n : network)
123 {
124 auto found = std::find(cluster.begin(), cluster.end(), n);
125 BEAST_EXPECT(
126 static_cast<bool>(c->member(n)) ==
127 (found != cluster.end()));
128 }
129 }
130 }
131
132 void
134 {
135 testcase("Updating");
136
137 auto c = create({});
138
139 auto const node = randomNode();
140 auto const name = toBase58(TokenType::NodePublic, node);
141 std::uint32_t load = 0;
142 NetClock::time_point tick = {};
143
144 // Initial update
145 BEAST_EXPECT(c->update(node, "", load, tick));
146 {
147 auto member = c->member(node);
148 BEAST_EXPECT(static_cast<bool>(member));
149 BEAST_EXPECT(member->empty());
150 }
151
152 // Updating too quickly: should fail
153 BEAST_EXPECT(!c->update(node, name, load, tick));
154 {
155 auto member = c->member(node);
156 BEAST_EXPECT(static_cast<bool>(member));
157 BEAST_EXPECT(member->empty());
158 }
159
160 using namespace std::chrono_literals;
161
162 // Updating the name (empty updates to non-empty)
163 tick += 1s;
164 BEAST_EXPECT(c->update(node, name, load, tick));
165 {
166 auto member = c->member(node);
167 BEAST_EXPECT(static_cast<bool>(member));
168 BEAST_EXPECT(member->compare(name) == 0);
169 }
170
171 // Updating the name (non-empty doesn't go to empty)
172 tick += 1s;
173 BEAST_EXPECT(c->update(node, "", load, tick));
174 {
175 auto member = c->member(node);
176 BEAST_EXPECT(static_cast<bool>(member));
177 BEAST_EXPECT(member->compare(name) == 0);
178 }
179
180 // Updating the name (non-empty updates to new non-empty)
181 tick += 1s;
182 BEAST_EXPECT(c->update(node, "test", load, tick));
183 {
184 auto member = c->member(node);
185 BEAST_EXPECT(static_cast<bool>(member));
186 BEAST_EXPECT(member->compare("test") == 0);
187 }
188 }
189
190 void
192 {
193 testcase("Config Load");
194
196
197 // The servers on the network
199
200 while (network.size() != 8)
201 network.push_back(randomNode());
202
203 auto format = [](PublicKey const& publicKey,
204 char const* comment = nullptr) {
205 auto ret = toBase58(TokenType::NodePublic, publicKey);
206
207 if (comment)
208 ret += comment;
209
210 return ret;
211 };
212
213 Section s1;
214
215 // Correct (empty) configuration
216 BEAST_EXPECT(c->load(s1));
217 BEAST_EXPECT(c->size() == 0);
218
219 // Correct configuration
220 s1.append(format(network[0]));
221 s1.append(format(network[1], " "));
222 s1.append(format(network[2], " Comment"));
223 s1.append(format(network[3], " Multi Word Comment"));
224 s1.append(format(network[4], " Leading Whitespace"));
225 s1.append(format(network[5], " Trailing Whitespace "));
226 s1.append(format(network[6], " Leading & Trailing Whitespace "));
227 s1.append(format(
228 network[7], " Leading, Trailing & Internal Whitespace "));
229
230 BEAST_EXPECT(c->load(s1));
231
232 for (auto const& n : network)
233 BEAST_EXPECT(c->member(n));
234
235 // Incorrect configurations
236 Section s2;
237 s2.append("NotAPublicKey");
238 BEAST_EXPECT(!c->load(s2));
239
240 Section s3;
241 s3.append(format(network[0], "!"));
242 BEAST_EXPECT(!c->load(s3));
243
244 Section s4;
245 s4.append(format(network[0], "! Comment"));
246 BEAST_EXPECT(!c->load(s4));
247
248 // Check if we properly terminate when we encounter
249 // a malformed or unparseable entry:
250 auto const node1 = randomNode();
251 auto const node2 = randomNode();
252
253 Section s5;
254 s5.append(format(node1, "XXX"));
255 s5.append(format(node2));
256 BEAST_EXPECT(!c->load(s5));
257 BEAST_EXPECT(!c->member(node1));
258 BEAST_EXPECT(!c->member(node2));
259 }
260
261 void
262 run() override
263 {
265 testUpdating();
267 }
268};
269
270BEAST_DEFINE_TESTSUITE(cluster, overlay, ripple);
271
272} // namespace tests
273} // namespace ripple
T begin(T... args)
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:155
A public key.
Definition PublicKey.h:61
Holds a collection of configuration values.
Definition BasicConfig.h:45
void append(std::vector< std::string > const &lines)
Append a set of lines to this section.
void run() override
Runs the suite.
test::SuiteJournal journal_
std::unique_ptr< Cluster > create(std::vector< PublicKey > const &nodes)
T end(T... args)
T find(T... args)
T is_same_v
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
PublicKey derivePublicKey(KeyType type, SecretKey const &sk)
Derive the public key from a secret key.
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
T push_back(T... args)
T size(T... args)