xrpld
Toggle main menu visibility
Loading...
Searching...
No Matches
test
app
HashRouter_test.cpp
1
#include <xrpld/app/misc/setup_HashRouter.h>
2
#include <xrpld/core/Config.h>
3
4
#include <xrpl/basics/chrono.h>
5
#include <xrpl/beast/unit_test/suite.h>
6
#include <xrpl/config/Constants.h>
7
#include <xrpl/core/HashRouter.h>
8
9
#include <
chrono
>
10
#include <
cstdint
>
11
#include <
exception
>
12
#include <
optional
>
13
#include <
set
>
14
#include <
type_traits
>
15
16
namespace
xrpl::test
{
17
18
class
HashRouter_test
:
public
beast::unit_test::Suite
19
{
20
static
HashRouter::Setup
21
getSetup
(
std::chrono::seconds
hold,
std::chrono::seconds
relay)
22
{
23
HashRouter::Setup
setup;
24
setup.
holdTime
= hold;
25
setup.
relayTime
= relay;
26
return
setup;
27
}
28
29
void
30
testNonExpiration
()
31
{
32
testcase
(
"Non-expiration"
);
33
using namespace
std::chrono_literals;
34
TestStopwatch
stopwatch
;
35
HashRouter
router(
getSetup
(2s, 1s),
stopwatch
);
36
37
HashRouterFlags
const
key1(
HashRouterFlags::PRIVATE1
);
38
HashRouterFlags
const
key2(
HashRouterFlags::PRIVATE2
);
39
HashRouterFlags
const
key3(
HashRouterFlags::PRIVATE3
);
40
41
auto
const
ukey1 =
UInt256
{
static_cast<
std::uint64_t
>
(key1)};
42
auto
const
ukey2 =
UInt256
{
static_cast<
std::uint64_t
>
(key2)};
43
auto
const
ukey3 =
UInt256
{
static_cast<
std::uint64_t
>
(key3)};
44
45
// t=0
46
router.
setFlags
(ukey1,
HashRouterFlags::PRIVATE1
);
47
BEAST_EXPECT(router.
getFlags
(ukey1) ==
HashRouterFlags::PRIVATE1
);
48
router.
setFlags
(ukey2,
HashRouterFlags::PRIVATE2
);
49
BEAST_EXPECT(router.
getFlags
(ukey2) ==
HashRouterFlags::PRIVATE2
);
50
// key1 : 0
51
// key2 : 0
52
// key3: null
53
54
++
stopwatch
;
55
56
// Because we are accessing key1 here, it
57
// will NOT be expired for another two ticks
58
BEAST_EXPECT(router.
getFlags
(ukey1) ==
HashRouterFlags::PRIVATE1
);
59
// key1 : 1
60
// key2 : 0
61
// key3 null
62
63
++
stopwatch
;
64
65
// t=3
66
router.
setFlags
(ukey3,
HashRouterFlags::PRIVATE3
);
// force expiration
67
BEAST_EXPECT(router.
getFlags
(ukey1) ==
HashRouterFlags::PRIVATE1
);
68
BEAST_EXPECT(router.
getFlags
(ukey2) ==
HashRouterFlags::UNDEFINED
);
69
}
70
71
void
72
testExpiration
()
73
{
74
testcase
(
"Expiration"
);
75
using namespace
std::chrono_literals;
76
TestStopwatch
stopwatch
;
77
HashRouter
router(
getSetup
(2s, 1s),
stopwatch
);
78
79
HashRouterFlags
const
key1(
HashRouterFlags::PRIVATE1
);
80
HashRouterFlags
const
key2(
HashRouterFlags::PRIVATE2
);
81
HashRouterFlags
const
key3(
HashRouterFlags::PRIVATE3
);
82
HashRouterFlags
const
key4(
HashRouterFlags::PRIVATE4
);
83
84
auto
const
ukey1 =
UInt256
{
static_cast<
std::uint64_t
>
(key1)};
85
auto
const
ukey2 =
UInt256
{
static_cast<
std::uint64_t
>
(key2)};
86
auto
const
ukey3 =
UInt256
{
static_cast<
std::uint64_t
>
(key3)};
87
auto
const
ukey4 =
UInt256
{
static_cast<
std::uint64_t
>
(key4)};
88
89
BEAST_EXPECT(key1 != key2 && key2 != key3 && key3 != key4);
90
91
// t=0
92
router.
setFlags
(ukey1,
HashRouterFlags::BAD
);
93
BEAST_EXPECT(router.
getFlags
(ukey1) ==
HashRouterFlags::BAD
);
94
// key1 : 0
95
// key2 : null
96
// key3 : null
97
98
++
stopwatch
;
99
100
// Expiration is triggered by insertion,
101
// and timestamps are updated on access,
102
// so key1 will be expired after the second
103
// call to setFlags.
104
// t=1
105
106
router.
setFlags
(ukey2,
HashRouterFlags::PRIVATE5
);
107
BEAST_EXPECT(router.
getFlags
(ukey1) ==
HashRouterFlags::BAD
);
108
BEAST_EXPECT(router.
getFlags
(ukey2) ==
HashRouterFlags::PRIVATE5
);
109
// key1 : 1
110
// key2 : 1
111
// key3 : null
112
113
++
stopwatch
;
114
// t=2
115
BEAST_EXPECT(router.
getFlags
(ukey2) ==
HashRouterFlags::PRIVATE5
);
116
// key1 : 1
117
// key2 : 2
118
// key3 : null
119
120
++
stopwatch
;
121
// t=3
122
router.
setFlags
(ukey3,
HashRouterFlags::BAD
);
123
BEAST_EXPECT(router.
getFlags
(ukey1) ==
HashRouterFlags::UNDEFINED
);
124
BEAST_EXPECT(router.
getFlags
(ukey2) ==
HashRouterFlags::PRIVATE5
);
125
BEAST_EXPECT(router.
getFlags
(ukey3) ==
HashRouterFlags::BAD
);
126
// key1 : 3
127
// key2 : 3
128
// key3 : 3
129
130
++
stopwatch
;
131
// t=4
132
// No insertion, no expiration
133
router.
setFlags
(ukey1,
HashRouterFlags::SAVED
);
134
BEAST_EXPECT(router.
getFlags
(ukey1) ==
HashRouterFlags::SAVED
);
135
BEAST_EXPECT(router.
getFlags
(ukey2) ==
HashRouterFlags::PRIVATE5
);
136
BEAST_EXPECT(router.
getFlags
(ukey3) ==
HashRouterFlags::BAD
);
137
// key1 : 4
138
// key2 : 4
139
// key3 : 4
140
141
++
stopwatch
;
142
++
stopwatch
;
143
144
// t=6
145
router.
setFlags
(ukey4,
HashRouterFlags::TRUSTED
);
146
BEAST_EXPECT(router.
getFlags
(ukey1) ==
HashRouterFlags::UNDEFINED
);
147
BEAST_EXPECT(router.
getFlags
(ukey2) ==
HashRouterFlags::UNDEFINED
);
148
BEAST_EXPECT(router.
getFlags
(ukey3) ==
HashRouterFlags::UNDEFINED
);
149
BEAST_EXPECT(router.
getFlags
(ukey4) ==
HashRouterFlags::TRUSTED
);
150
// key1 : 6
151
// key2 : 6
152
// key3 : 6
153
// key4 : 6
154
}
155
156
void
157
testSuppression
()
158
{
159
testcase
(
"Suppression"
);
160
// Normal HashRouter
161
using namespace
std::chrono_literals;
162
TestStopwatch
stopwatch
;
163
HashRouter
router(
getSetup
(2s, 1s),
stopwatch
);
164
165
UInt256
const
key1(1);
166
UInt256
const
key2(2);
167
UInt256
const
key3(3);
168
UInt256
const
key4(4);
169
BEAST_EXPECT(key1 != key2 && key2 != key3 && key3 != key4);
170
171
HashRouterFlags
flags(
HashRouterFlags::BAD
);
// This value is ignored
172
router.
addSuppression
(key1);
173
BEAST_EXPECT(router.
addSuppressionPeer
(key2, 15));
174
BEAST_EXPECT(router.
addSuppressionPeer
(key3, 20, flags));
175
BEAST_EXPECT(flags ==
HashRouterFlags::UNDEFINED
);
176
177
++
stopwatch
;
178
179
BEAST_EXPECT(!router.
addSuppressionPeer
(key1, 2));
180
BEAST_EXPECT(!router.
addSuppressionPeer
(key2, 3));
181
BEAST_EXPECT(!router.
addSuppressionPeer
(key3, 4, flags));
182
BEAST_EXPECT(flags ==
HashRouterFlags::UNDEFINED
);
183
BEAST_EXPECT(router.
addSuppressionPeer
(key4, 5));
184
}
185
186
void
187
testSetFlags
()
188
{
189
testcase
(
"Set Flags"
);
190
using namespace
std::chrono_literals;
191
TestStopwatch
stopwatch
;
192
HashRouter
router(
getSetup
(2s, 1s),
stopwatch
);
193
194
UInt256
const
key1(1);
195
BEAST_EXPECT(router.
setFlags
(key1,
HashRouterFlags::PRIVATE1
));
196
BEAST_EXPECT(!router.
setFlags
(key1,
HashRouterFlags::PRIVATE1
));
197
BEAST_EXPECT(router.
setFlags
(key1,
HashRouterFlags::PRIVATE2
));
198
}
199
200
void
201
testRelay
()
202
{
203
testcase
(
"Relay"
);
204
using namespace
std::chrono_literals;
205
TestStopwatch
stopwatch
;
206
HashRouter
router(
getSetup
(50s, 1s),
stopwatch
);
207
208
UInt256
const
key1(1);
209
210
std::optional<std::set<HashRouter::PeerShortID>
> peers;
211
212
peers = router.
shouldRelay
(key1);
213
BEAST_EXPECT(peers && peers->empty());
214
router.
addSuppressionPeer
(key1, 1);
215
router.
addSuppressionPeer
(key1, 3);
216
router.
addSuppressionPeer
(key1, 5);
217
// No action, because relayed
218
BEAST_EXPECT(!router.
shouldRelay
(key1));
219
// Expire, but since the next search will
220
// be for this entry, it will get refreshed
221
// instead. However, the relay won't.
222
++
stopwatch
;
223
// Get those peers we added earlier
224
peers = router.
shouldRelay
(key1);
225
BEAST_EXPECT(peers && peers->size() == 3);
226
router.
addSuppressionPeer
(key1, 2);
227
router.
addSuppressionPeer
(key1, 4);
228
// No action, because relayed
229
BEAST_EXPECT(!router.
shouldRelay
(key1));
230
// Expire, but since the next search will
231
// be for this entry, it will get refreshed
232
// instead. However, the relay won't.
233
++
stopwatch
;
234
// Relay again
235
peers = router.
shouldRelay
(key1);
236
BEAST_EXPECT(peers && peers->size() == 2);
237
// Expire again
238
++
stopwatch
;
239
// Confirm that peers list is empty.
240
peers = router.
shouldRelay
(key1);
241
BEAST_EXPECT(peers && peers->empty());
242
}
243
244
void
245
testProcess
()
246
{
247
testcase
(
"Process"
);
248
using namespace
std::chrono_literals;
249
TestStopwatch
stopwatch
;
250
HashRouter
router(
getSetup
(5s, 1s),
stopwatch
);
251
UInt256
const
key(1);
252
HashRouter::PeerShortID
const
peer = 1;
253
HashRouterFlags
flags =
HashRouterFlags::UNDEFINED
;
254
255
BEAST_EXPECT(router.
shouldProcess
(key, peer, flags, 1s));
256
BEAST_EXPECT(!router.
shouldProcess
(key, peer, flags, 1s));
257
++
stopwatch
;
258
++
stopwatch
;
259
BEAST_EXPECT(router.
shouldProcess
(key, peer, flags, 1s));
260
}
261
262
void
263
testSetup
()
264
{
265
testcase
(
"setup_HashRouter"
);
266
267
using namespace
std::chrono_literals;
268
{
269
Config
const
cfg;
270
// default
271
auto
const
setup =
setupHashRouter
(cfg);
272
BEAST_EXPECT(setup.holdTime == 300s);
273
BEAST_EXPECT(setup.relayTime == 30s);
274
}
275
{
276
Config
cfg;
277
// non-default
278
auto
& h = cfg.
section
(
Sections::kHashrouter
);
279
h.
set
(
Keys::kHoldTime
,
"600"
);
280
h.set(
Keys::kRelayTime
,
"15"
);
281
auto
const
setup =
setupHashRouter
(cfg);
282
BEAST_EXPECT(setup.holdTime == 600s);
283
BEAST_EXPECT(setup.relayTime == 15s);
284
}
285
{
286
Config
cfg;
287
// equal
288
auto
& h = cfg.
section
(
Sections::kHashrouter
);
289
h.
set
(
Keys::kHoldTime
,
"400"
);
290
h.set(
Keys::kRelayTime
,
"400"
);
291
auto
const
setup =
setupHashRouter
(cfg);
292
BEAST_EXPECT(setup.holdTime == 400s);
293
BEAST_EXPECT(setup.relayTime == 400s);
294
}
295
{
296
Config
cfg;
297
// wrong order
298
auto
& h = cfg.
section
(
Sections::kHashrouter
);
299
h.
set
(
Keys::kHoldTime
,
"60"
);
300
h.set(
Keys::kRelayTime
,
"120"
);
301
try
302
{
303
setupHashRouter
(cfg);
304
fail
();
305
}
306
catch
(
std::exception
const
& e)
307
{
308
std::string
const
expected =
309
"HashRouter relay time must be less than or equal to hold "
310
"time"
;
311
BEAST_EXPECT(e.
what
() == expected);
312
}
313
}
314
{
315
Config
cfg;
316
// too small hold
317
auto
& h = cfg.
section
(
Sections::kHashrouter
);
318
h.
set
(
Keys::kHoldTime
,
"10"
);
319
h.set(
Keys::kRelayTime
,
"120"
);
320
try
321
{
322
setupHashRouter
(cfg);
323
fail
();
324
}
325
catch
(
std::exception
const
& e)
326
{
327
std::string
const
expected =
328
"HashRouter hold time must be at least 12 seconds (the "
329
"approximate validation time for three "
330
"ledgers)."
;
331
BEAST_EXPECT(e.
what
() == expected);
332
}
333
}
334
{
335
Config
cfg;
336
// too small relay
337
auto
& h = cfg.
section
(
Sections::kHashrouter
);
338
h.
set
(
Keys::kHoldTime
,
"500"
);
339
h.set(
Keys::kRelayTime
,
"6"
);
340
try
341
{
342
setupHashRouter
(cfg);
343
fail
();
344
}
345
catch
(
std::exception
const
& e)
346
{
347
std::string
const
expected =
348
"HashRouter relay time must be at least 8 seconds (the "
349
"approximate validation time for two ledgers)."
;
350
BEAST_EXPECT(e.
what
() == expected);
351
}
352
}
353
{
354
Config
cfg;
355
// garbage
356
auto
& h = cfg.
section
(
Sections::kHashrouter
);
357
h.
set
(
Keys::kHoldTime
,
"alice"
);
358
h.set(
Keys::kRelayTime
,
"bob"
);
359
auto
const
setup =
setupHashRouter
(cfg);
360
// The set function ignores values that don't convert, so the
361
// defaults are left unchanged
362
BEAST_EXPECT(setup.holdTime == 300s);
363
BEAST_EXPECT(setup.relayTime == 30s);
364
}
365
}
366
367
void
368
testFlagsOps
()
369
{
370
testcase
(
"Bitwise Operations"
);
371
372
using
HF =
HashRouterFlags
;
373
using
UHF =
std::underlying_type_t<HF>
;
374
375
HF
const
f1 = HF::BAD;
376
HF
const
f2 = HF::SAVED;
377
HF
const
combined = f1 | f2;
378
379
BEAST_EXPECT(
static_cast<
UHF
>
(combined) == (
static_cast<
UHF
>
(f1) |
static_cast<
UHF
>
(f2)));
380
381
HF temp = f1;
382
temp |= f2;
383
BEAST_EXPECT(temp == combined);
384
385
HF
const
intersect = combined & f1;
386
BEAST_EXPECT(intersect == f1);
387
388
HF temp2 = combined;
389
temp2 &= f1;
390
BEAST_EXPECT(temp2 == f1);
391
392
BEAST_EXPECT(
any
(f1));
393
BEAST_EXPECT(
any
(f2));
394
BEAST_EXPECT(
any
(combined));
395
BEAST_EXPECT(!
any
(HF::UNDEFINED));
396
}
397
398
public
:
399
void
400
run
()
override
401
{
402
testNonExpiration
();
403
testExpiration
();
404
testSuppression
();
405
testSetFlags
();
406
testRelay
();
407
testProcess
();
408
testSetup
();
409
testFlagsOps
();
410
}
411
};
412
413
BEAST_DEFINE_TESTSUITE
(
HashRouter
, app,
xrpl
);
414
415
}
// namespace xrpl::test
std::string
chrono
beast::unit_test::Suite
A testsuite class.
Definition
suite.h:52
beast::unit_test::Suite::fail
void fail(String const &reason, char const *file, int line)
Record a failure.
Definition
suite.h:554
beast::unit_test::Suite::testcase
TestcaseT testcase
Memberspace for declaring test cases.
Definition
suite.h:155
xrpl::BasicConfig::section
Section & section(std::string const &name)
Returns the section with the given name.
Definition
BasicConfig.cpp:121
xrpl::Config
Definition
src/xrpld/core/Config.h:89
xrpl::HashRouter
Routing table for objects identified by hash.
Definition
HashRouter.h:89
xrpl::HashRouter::addSuppression
void addSuppression(UInt256 const &key)
Definition
HashRouter.cpp:35
xrpl::HashRouter::setFlags
bool setFlags(UInt256 const &key, HashRouterFlags flags)
Set the flags on a hash.
Definition
HashRouter.cpp:94
xrpl::HashRouter::addSuppressionPeer
bool addSuppressionPeer(UInt256 const &key, PeerShortID peer)
Definition
HashRouter.cpp:43
xrpl::HashRouter::shouldRelay
std::optional< std::set< PeerShortID > > shouldRelay(UInt256 const &key)
Determines whether the hashed item should be relayed.
Definition
HashRouter.cpp:110
xrpl::HashRouter::PeerShortID
std::uint32_t PeerShortID
Definition
HashRouter.h:92
xrpl::HashRouter::getFlags
HashRouterFlags getFlags(UInt256 const &key)
Definition
HashRouter.cpp:86
xrpl::HashRouter::shouldProcess
bool shouldProcess(UInt256 const &key, PeerShortID peer, HashRouterFlags &flags, std::chrono::seconds txInterval)
Definition
HashRouter.cpp:70
xrpl::Section::set
void set(std::string const &key, std::string const &value)
Set a key/value pair.
Definition
BasicConfig.cpp:22
xrpl::test::HashRouter_test
Definition
HashRouter_test.cpp:19
xrpl::test::HashRouter_test::getSetup
static HashRouter::Setup getSetup(std::chrono::seconds hold, std::chrono::seconds relay)
Definition
HashRouter_test.cpp:21
xrpl::test::HashRouter_test::testProcess
void testProcess()
Definition
HashRouter_test.cpp:245
xrpl::test::HashRouter_test::testExpiration
void testExpiration()
Definition
HashRouter_test.cpp:72
xrpl::test::HashRouter_test::testSetFlags
void testSetFlags()
Definition
HashRouter_test.cpp:187
xrpl::test::HashRouter_test::run
void run() override
Runs the suite.
Definition
HashRouter_test.cpp:400
xrpl::test::HashRouter_test::testNonExpiration
void testNonExpiration()
Definition
HashRouter_test.cpp:30
xrpl::test::HashRouter_test::testSuppression
void testSuppression()
Definition
HashRouter_test.cpp:157
xrpl::test::HashRouter_test::testSetup
void testSetup()
Definition
HashRouter_test.cpp:263
xrpl::test::HashRouter_test::testRelay
void testRelay()
Definition
HashRouter_test.cpp:201
xrpl::test::HashRouter_test::testFlagsOps
void testFlagsOps()
Definition
HashRouter_test.cpp:368
cstdint
std::chrono::seconds
exception
std::uint64_t
xrpl::test
Definition
STLedgerEntry.h:21
xrpl::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AMMClawback, app, xrpl)
xrpl
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition
algorithm.h:5
xrpl::stopwatch
Stopwatch & stopwatch()
Returns an instance of a wall clock.
Definition
chrono.h:101
xrpl::UInt256
BaseUInt< 256 > UInt256
Definition
base_uint.h:580
xrpl::HashRouterFlags
HashRouterFlags
Definition
HashRouter.h:20
xrpl::HashRouterFlags::UNDEFINED
@ UNDEFINED
Definition
HashRouter.h:22
xrpl::HashRouterFlags::PRIVATE3
@ PRIVATE3
Definition
HashRouter.h:33
xrpl::HashRouterFlags::PRIVATE2
@ PRIVATE2
Definition
HashRouter.h:32
xrpl::HashRouterFlags::PRIVATE4
@ PRIVATE4
Definition
HashRouter.h:34
xrpl::HashRouterFlags::PRIVATE1
@ PRIVATE1
Definition
HashRouter.h:31
xrpl::HashRouterFlags::TRUSTED
@ TRUSTED
Definition
HashRouter.h:26
xrpl::HashRouterFlags::SAVED
@ SAVED
Definition
HashRouter.h:24
xrpl::HashRouterFlags::BAD
@ BAD
Definition
HashRouter.h:23
xrpl::HashRouterFlags::PRIVATE5
@ PRIVATE5
Definition
HashRouter.h:36
xrpl::setupHashRouter
HashRouter::Setup setupHashRouter(Config const &config)
Create HashRouter setup from configuration.
Definition
setup_HashRouter.cpp:17
xrpl::TestStopwatch
beast::ManualClock< std::chrono::steady_clock > TestStopwatch
A manual Stopwatch for unit tests.
Definition
chrono.h:95
xrpl::any
constexpr bool any(HashRouterFlags flags)
Definition
HashRouter.h:74
optional
set
xrpl::HashRouter::Setup
Structure used to customize HashRouter behavior.
Definition
HashRouter.h:104
xrpl::HashRouter::Setup::relayTime
Seconds relayTime
Amount of time required before a relayed item will be relayed again.
Definition
HashRouter.h:120
xrpl::HashRouter::Setup::holdTime
Seconds holdTime
Expiration time for a hash entry.
Definition
HashRouter.h:115
xrpl::Keys::kRelayTime
static constexpr auto kRelayTime
Definition
Constants.h:151
xrpl::Keys::kHoldTime
static constexpr auto kHoldTime
Definition
Constants.h:113
xrpl::Sections::kHashrouter
static constexpr auto kHashrouter
Definition
Constants.h:19
type_traits
std::underlying_type_t
std::exception::what
T what(T... args)
Generated by
1.17.0