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