xrpld
Loading...
Searching...
No Matches
Issue_test.cpp
1#include <xrpl/basics/UnorderedContainers.h>
2#include <xrpl/basics/base_uint.h>
3#include <xrpl/beast/unit_test/suite.h>
4#include <xrpl/json/json_value.h>
5#include <xrpl/protocol/AccountID.h>
6#include <xrpl/protocol/Book.h>
7#include <xrpl/protocol/Issue.h>
8#include <xrpl/protocol/UintTypes.h>
9#include <xrpl/protocol/jss.h>
10
11#include <functional>
12#include <map>
13#include <optional>
14#include <set>
15#include <utility>
16
17#if BEAST_MSVC
18#define STL_SET_HAS_EMPLACE 1
19#else
20#define STL_SET_HAS_EMPLACE 0
21#endif
22
23namespace xrpl {
24
26{
27public:
28 using Domain = uint256;
29
30 // Comparison, hash tests for uint60 (via base_uint)
31 template <typename Unsigned>
32 void
34 {
35 Unsigned const u1(1);
36 Unsigned const u2(2);
37 Unsigned const u3(3);
38
39 BEAST_EXPECT(u1 != u2);
40 BEAST_EXPECT(u1 < u2);
41 BEAST_EXPECT(u1 <= u2);
42 BEAST_EXPECT(u2 <= u2);
43 BEAST_EXPECT(u2 == u2);
44 BEAST_EXPECT(u2 >= u2);
45 BEAST_EXPECT(u3 >= u2);
46 BEAST_EXPECT(u3 > u2);
47
48 std::hash<Unsigned> const hash;
49
50 BEAST_EXPECT(hash(u1) == hash(u1));
51 BEAST_EXPECT(hash(u2) == hash(u2));
52 BEAST_EXPECT(hash(u3) == hash(u3));
53 BEAST_EXPECT(hash(u1) != hash(u2));
54 BEAST_EXPECT(hash(u1) != hash(u3));
55 BEAST_EXPECT(hash(u2) != hash(u3));
56 }
57
58 //--------------------------------------------------------------------------
59
60 // Comparison, hash tests for Issue
61 template <class Issue>
62 void
64 {
65 Currency const c1(1);
66 AccountID const i1(1);
67 Currency const c2(2);
68 AccountID const i2(2);
69 Currency const c3(3);
70 AccountID const i3(3);
71
72 BEAST_EXPECT(Issue(c1, i1) != Issue(c2, i1));
73 BEAST_EXPECT(Issue(c1, i1) < Issue(c2, i1));
74 BEAST_EXPECT(Issue(c1, i1) <= Issue(c2, i1));
75 BEAST_EXPECT(Issue(c2, i1) <= Issue(c2, i1));
76 BEAST_EXPECT(Issue(c2, i1) == Issue(c2, i1));
77 BEAST_EXPECT(Issue(c2, i1) >= Issue(c2, i1));
78 BEAST_EXPECT(Issue(c3, i1) >= Issue(c2, i1));
79 BEAST_EXPECT(Issue(c3, i1) > Issue(c2, i1));
80 BEAST_EXPECT(Issue(c1, i1) != Issue(c1, i2));
81 BEAST_EXPECT(Issue(c1, i1) < Issue(c1, i2));
82 BEAST_EXPECT(Issue(c1, i1) <= Issue(c1, i2));
83 BEAST_EXPECT(Issue(c1, i2) <= Issue(c1, i2));
84 BEAST_EXPECT(Issue(c1, i2) == Issue(c1, i2));
85 BEAST_EXPECT(Issue(c1, i2) >= Issue(c1, i2));
86 BEAST_EXPECT(Issue(c1, i3) >= Issue(c1, i2));
87 BEAST_EXPECT(Issue(c1, i3) > Issue(c1, i2));
88
89 std::hash<Issue> const hash;
90
91 BEAST_EXPECT(hash(Issue(c1, i1)) == hash(Issue(c1, i1)));
92 BEAST_EXPECT(hash(Issue(c1, i2)) == hash(Issue(c1, i2)));
93 BEAST_EXPECT(hash(Issue(c1, i3)) == hash(Issue(c1, i3)));
94 BEAST_EXPECT(hash(Issue(c2, i1)) == hash(Issue(c2, i1)));
95 BEAST_EXPECT(hash(Issue(c2, i2)) == hash(Issue(c2, i2)));
96 BEAST_EXPECT(hash(Issue(c2, i3)) == hash(Issue(c2, i3)));
97 BEAST_EXPECT(hash(Issue(c3, i1)) == hash(Issue(c3, i1)));
98 BEAST_EXPECT(hash(Issue(c3, i2)) == hash(Issue(c3, i2)));
99 BEAST_EXPECT(hash(Issue(c3, i3)) == hash(Issue(c3, i3)));
100 BEAST_EXPECT(hash(Issue(c1, i1)) != hash(Issue(c1, i2)));
101 BEAST_EXPECT(hash(Issue(c1, i1)) != hash(Issue(c1, i3)));
102 BEAST_EXPECT(hash(Issue(c1, i1)) != hash(Issue(c2, i1)));
103 BEAST_EXPECT(hash(Issue(c1, i1)) != hash(Issue(c2, i2)));
104 BEAST_EXPECT(hash(Issue(c1, i1)) != hash(Issue(c2, i3)));
105 BEAST_EXPECT(hash(Issue(c1, i1)) != hash(Issue(c3, i1)));
106 BEAST_EXPECT(hash(Issue(c1, i1)) != hash(Issue(c3, i2)));
107 BEAST_EXPECT(hash(Issue(c1, i1)) != hash(Issue(c3, i3)));
108 }
109
110 template <class Set>
111 void
113 {
114 Currency const c1(1);
115 AccountID const i1(1);
116 Currency const c2(2);
117 AccountID const i2(2);
118 Issue const a1(c1, i1);
119 Issue const a2(c2, i2);
120
121 {
122 Set c;
123
124 c.insert(a1);
125 if (!BEAST_EXPECT(c.size() == 1))
126 return;
127 c.insert(a2);
128 if (!BEAST_EXPECT(c.size() == 2))
129 return;
130
131 if (!BEAST_EXPECT(c.erase(Issue(c1, i2)) == 0))
132 return;
133 if (!BEAST_EXPECT(c.erase(Issue(c1, i1)) == 1))
134 return;
135 if (!BEAST_EXPECT(c.erase(Issue(c2, i2)) == 1))
136 return;
137 if (!BEAST_EXPECT(c.empty()))
138 return;
139 }
140
141 {
142 Set c;
143
144 c.insert(a1);
145 if (!BEAST_EXPECT(c.size() == 1))
146 return;
147 c.insert(a2);
148 if (!BEAST_EXPECT(c.size() == 2))
149 return;
150
151 if (!BEAST_EXPECT(c.erase(Issue(c1, i2)) == 0))
152 return;
153 if (!BEAST_EXPECT(c.erase(Issue(c1, i1)) == 1))
154 return;
155 if (!BEAST_EXPECT(c.erase(Issue(c2, i2)) == 1))
156 return;
157 if (!BEAST_EXPECT(c.empty()))
158 return;
159
160#if STL_SET_HAS_EMPLACE
161 c.emplace(c1, i1);
162 if (!BEAST_EXPECT(c.size() == 1))
163 return;
164 c.emplace(c2, i2);
165 if (!BEAST_EXPECT(c.size() == 2))
166 return;
167#endif
168 }
169 }
170
171 template <class Map>
172 void
174 {
175 Currency const c1(1);
176 AccountID const i1(1);
177 Currency const c2(2);
178 AccountID const i2(2);
179 Issue const a1(c1, i1);
180 Issue const a2(c2, i2);
181
182 {
183 Map c;
184
185 c.insert(std::make_pair(a1, 1));
186 if (!BEAST_EXPECT(c.size() == 1))
187 return;
188 c.insert(std::make_pair(a2, 2));
189 if (!BEAST_EXPECT(c.size() == 2))
190 return;
191
192 if (!BEAST_EXPECT(c.erase(Issue(c1, i2)) == 0))
193 return;
194 if (!BEAST_EXPECT(c.erase(Issue(c1, i1)) == 1))
195 return;
196 if (!BEAST_EXPECT(c.erase(Issue(c2, i2)) == 1))
197 return;
198 if (!BEAST_EXPECT(c.empty()))
199 return;
200 }
201
202 {
203 Map c;
204
205 c.insert(std::make_pair(a1, 1));
206 if (!BEAST_EXPECT(c.size() == 1))
207 return;
208 c.insert(std::make_pair(a2, 2));
209 if (!BEAST_EXPECT(c.size() == 2))
210 return;
211
212 if (!BEAST_EXPECT(c.erase(Issue(c1, i2)) == 0))
213 return;
214 if (!BEAST_EXPECT(c.erase(Issue(c1, i1)) == 1))
215 return;
216 if (!BEAST_EXPECT(c.erase(Issue(c2, i2)) == 1))
217 return;
218 if (!BEAST_EXPECT(c.empty()))
219 return;
220 }
221 }
222
223 template <class Set>
224 void
226 {
227 Currency const c1(1);
228 AccountID const i1(1);
229 Currency const c2(2);
230 AccountID const i2(2);
231 Issue const a1(c1, i1);
232 Issue const a2(c2, i2);
233 uint256 const domain1{1};
234 uint256 const domain2{2};
235
236 Set c;
237
238 c.insert(std::make_pair(a1, domain1));
239 if (!BEAST_EXPECT(c.size() == 1))
240 return;
241 c.insert(std::make_pair(a2, domain1));
242 if (!BEAST_EXPECT(c.size() == 2))
243 return;
244 c.insert(std::make_pair(a2, domain2));
245 if (!BEAST_EXPECT(c.size() == 3))
246 return;
247
248 if (!BEAST_EXPECT(c.erase(std::make_pair(Issue(c1, i2), domain1)) == 0))
249 return;
250 if (!BEAST_EXPECT(c.erase(std::make_pair(a1, domain1)) == 1))
251 return;
252 if (!BEAST_EXPECT(c.erase(std::make_pair(a2, domain1)) == 1))
253 return;
254 if (!BEAST_EXPECT(c.erase(std::make_pair(a2, domain2)) == 1))
255 return;
256 if (!BEAST_EXPECT(c.empty()))
257 return;
258 }
259
260 template <class Map>
261 void
263 {
264 Currency const c1(1);
265 AccountID const i1(1);
266 Currency const c2(2);
267 AccountID const i2(2);
268 Issue const a1(c1, i1);
269 Issue const a2(c2, i2);
270 uint256 const domain1{1};
271 uint256 const domain2{2};
272
273 Map c;
274
275 c.insert(std::make_pair(std::make_pair(a1, domain1), 1));
276 if (!BEAST_EXPECT(c.size() == 1))
277 return;
278 c.insert(std::make_pair(std::make_pair(a2, domain1), 2));
279 if (!BEAST_EXPECT(c.size() == 2))
280 return;
281 c.insert(std::make_pair(std::make_pair(a2, domain2), 2));
282 if (!BEAST_EXPECT(c.size() == 3))
283 return;
284
285 if (!BEAST_EXPECT(c.erase(std::make_pair(Issue(c1, i2), domain1)) == 0))
286 return;
287 if (!BEAST_EXPECT(c.erase(std::make_pair(a1, domain1)) == 1))
288 return;
289 if (!BEAST_EXPECT(c.erase(std::make_pair(a2, domain1)) == 1))
290 return;
291 if (!BEAST_EXPECT(c.erase(std::make_pair(a2, domain2)) == 1))
292 return;
293 if (!BEAST_EXPECT(c.empty()))
294 return;
295 }
296
297 void
299 {
300 testcase("std::set <std::pair<Issue, Domain>>");
302
303 testcase("std::set <std::pair<Issue, Domain>>");
305
306 testcase("hash_set <std::pair<Issue, Domain>>");
308
309 testcase("hash_set <std::pair<Issue, Domain>>");
311 }
312
313 void
315 {
316 testcase("std::map <std::pair<Issue, Domain>, int>");
318
319 testcase("std::map <std::pair<Issue, Domain>, int>");
321
322#if XRPL_ASSETS_ENABLE_STD_HASH
323 testcase("hash_map <std::pair<Issue, Domain>, int>");
325
326 testcase("hash_map <std::pair<Issue, Domain>, int>");
328
329 testcase("hardened_hash_map <std::pair<Issue, Domain>, int>");
331
332 testcase("hardened_hash_map <std::pair<Issue, Domain>, int>");
334#endif
335 }
336
337 void
339 {
340 testcase("std::set <Issue>");
342
343 testcase("std::set <Issue>");
345
346#if XRPL_ASSETS_ENABLE_STD_HASH
347 testcase("std::unordered_set <Issue>");
349
350 testcase("std::unordered_set <Issue>");
352#endif
353
354 testcase("hash_set <Issue>");
356
357 testcase("hash_set <Issue>");
359 }
360
361 void
363 {
364 testcase("std::map <Issue, int>");
366
367 testcase("std::map <Issue, int>");
369
370#if XRPL_ASSETS_ENABLE_STD_HASH
371 testcase("std::unordered_map <Issue, int>");
373
374 testcase("std::unordered_map <Issue, int>");
376
377 testcase("hash_map <Issue, int>");
379
380 testcase("hash_map <Issue, int>");
382
383#endif
384 }
385
386 //--------------------------------------------------------------------------
387
388 // Comparison, hash tests for Book
389 template <class Book>
390 void
392 {
393 Currency const c1(1);
394 AccountID const i1(1);
395 Currency const c2(2);
396 AccountID const i2(2);
397 Currency const c3(3);
398 AccountID const i3(3);
399
400 Issue const a1(c1, i1);
401 Issue const a2(c1, i2);
402 Issue const a3(c2, i2);
403 Issue const a4(c3, i2);
404 uint256 const domain1{1};
405 uint256 const domain2{2};
406
407 // Books without domains
408 BEAST_EXPECT(Book(a1, a2, std::nullopt) != Book(a2, a3, std::nullopt));
409 BEAST_EXPECT(Book(a1, a2, std::nullopt) < Book(a2, a3, std::nullopt));
410 BEAST_EXPECT(Book(a1, a2, std::nullopt) <= Book(a2, a3, std::nullopt));
411 BEAST_EXPECT(Book(a2, a3, std::nullopt) <= Book(a2, a3, std::nullopt));
412 BEAST_EXPECT(Book(a2, a3, std::nullopt) == Book(a2, a3, std::nullopt));
413 BEAST_EXPECT(Book(a2, a3, std::nullopt) >= Book(a2, a3, std::nullopt));
414 BEAST_EXPECT(Book(a3, a4, std::nullopt) >= Book(a2, a3, std::nullopt));
415 BEAST_EXPECT(Book(a3, a4, std::nullopt) > Book(a2, a3, std::nullopt));
416
417 // test domain books
418 {
419 // Books with different domains
420 BEAST_EXPECT(Book(a2, a3, domain1) != Book(a2, a3, domain2));
421 BEAST_EXPECT(Book(a2, a3, domain1) < Book(a2, a3, domain2));
422 BEAST_EXPECT(Book(a2, a3, domain2) > Book(a2, a3, domain1));
423
424 // One Book has a domain, the other does not
425 BEAST_EXPECT(Book(a2, a3, domain1) != Book(a2, a3, std::nullopt));
426 BEAST_EXPECT(Book(a2, a3, std::nullopt) < Book(a2, a3, domain1));
427 BEAST_EXPECT(Book(a2, a3, domain1) > Book(a2, a3, std::nullopt));
428
429 // Both Books have the same domain
430 BEAST_EXPECT(Book(a2, a3, domain1) == Book(a2, a3, domain1));
431 BEAST_EXPECT(Book(a2, a3, domain2) == Book(a2, a3, domain2));
432 BEAST_EXPECT(Book(a2, a3, std::nullopt) == Book(a2, a3, std::nullopt));
433
434 // Both Books have no domain
435 BEAST_EXPECT(Book(a2, a3, std::nullopt) == Book(a2, a3, std::nullopt));
436
437 // Testing comparisons with >= and <=
438
439 // When comparing books with domain1 vs domain2
440 BEAST_EXPECT(Book(a2, a3, domain1) <= Book(a2, a3, domain2));
441 BEAST_EXPECT(Book(a2, a3, domain2) >= Book(a2, a3, domain1));
442 BEAST_EXPECT(Book(a2, a3, domain1) >= Book(a2, a3, domain1));
443 BEAST_EXPECT(Book(a2, a3, domain2) <= Book(a2, a3, domain2));
444
445 // One Book has domain1 and the other has no domain
446 BEAST_EXPECT(Book(a2, a3, domain1) > Book(a2, a3, std::nullopt));
447 BEAST_EXPECT(Book(a2, a3, std::nullopt) < Book(a2, a3, domain1));
448
449 // One Book has domain2 and the other has no domain
450 BEAST_EXPECT(Book(a2, a3, domain2) > Book(a2, a3, std::nullopt));
451 BEAST_EXPECT(Book(a2, a3, std::nullopt) < Book(a2, a3, domain2));
452
453 // Comparing two Books with no domains
454 BEAST_EXPECT(Book(a2, a3, std::nullopt) <= Book(a2, a3, std::nullopt));
455 BEAST_EXPECT(Book(a2, a3, std::nullopt) >= Book(a2, a3, std::nullopt));
456
457 // Test case where domain1 is less than domain2
458 BEAST_EXPECT(Book(a2, a3, domain1) <= Book(a2, a3, domain2));
459 BEAST_EXPECT(Book(a2, a3, domain2) >= Book(a2, a3, domain1));
460
461 // Test case where domain2 is equal to domain1
462 BEAST_EXPECT(Book(a2, a3, domain1) >= Book(a2, a3, domain1));
463 BEAST_EXPECT(Book(a2, a3, domain1) <= Book(a2, a3, domain1));
464
465 // More test cases involving a4 (with domain2)
466
467 // Comparing Book with domain2 (a4) to a Book with domain1
468 BEAST_EXPECT(Book(a2, a3, domain1) < Book(a3, a4, domain2));
469 BEAST_EXPECT(Book(a3, a4, domain2) > Book(a2, a3, domain1));
470
471 // Comparing Book with domain2 (a4) to a Book with no domain
472 BEAST_EXPECT(Book(a3, a4, domain2) > Book(a2, a3, std::nullopt));
473 BEAST_EXPECT(Book(a2, a3, std::nullopt) < Book(a3, a4, domain2));
474
475 // Comparing Book with domain2 (a4) to a Book with the same domain
476 BEAST_EXPECT(Book(a3, a4, domain2) == Book(a3, a4, domain2));
477
478 // Comparing Book with domain2 (a4) to a Book with domain1
479 BEAST_EXPECT(Book(a2, a3, domain1) < Book(a3, a4, domain2));
480 BEAST_EXPECT(Book(a3, a4, domain2) > Book(a2, a3, domain1));
481 }
482
483 std::hash<Book> const hash;
484
485 // log << std::hex << hash (Book (a1, a2));
486 // log << std::hex << hash (Book (a1, a2));
487 //
488 // log << std::hex << hash (Book (a1, a3));
489 // log << std::hex << hash (Book (a1, a3));
490 //
491 // log << std::hex << hash (Book (a1, a4));
492 // log << std::hex << hash (Book (a1, a4));
493 //
494 // log << std::hex << hash (Book (a2, a3));
495 // log << std::hex << hash (Book (a2, a3));
496 //
497 // log << std::hex << hash (Book (a2, a4));
498 // log << std::hex << hash (Book (a2, a4));
499 //
500 // log << std::hex << hash (Book (a3, a4));
501 // log << std::hex << hash (Book (a3, a4));
502
503 BEAST_EXPECT(hash(Book(a1, a2, std::nullopt)) == hash(Book(a1, a2, std::nullopt)));
504 BEAST_EXPECT(hash(Book(a1, a3, std::nullopt)) == hash(Book(a1, a3, std::nullopt)));
505 BEAST_EXPECT(hash(Book(a1, a4, std::nullopt)) == hash(Book(a1, a4, std::nullopt)));
506 BEAST_EXPECT(hash(Book(a2, a3, std::nullopt)) == hash(Book(a2, a3, std::nullopt)));
507 BEAST_EXPECT(hash(Book(a2, a4, std::nullopt)) == hash(Book(a2, a4, std::nullopt)));
508 BEAST_EXPECT(hash(Book(a3, a4, std::nullopt)) == hash(Book(a3, a4, std::nullopt)));
509
510 BEAST_EXPECT(hash(Book(a1, a2, std::nullopt)) != hash(Book(a1, a3, std::nullopt)));
511 BEAST_EXPECT(hash(Book(a1, a2, std::nullopt)) != hash(Book(a1, a4, std::nullopt)));
512 BEAST_EXPECT(hash(Book(a1, a2, std::nullopt)) != hash(Book(a2, a3, std::nullopt)));
513 BEAST_EXPECT(hash(Book(a1, a2, std::nullopt)) != hash(Book(a2, a4, std::nullopt)));
514 BEAST_EXPECT(hash(Book(a1, a2, std::nullopt)) != hash(Book(a3, a4, std::nullopt)));
515
516 // Books with domain
517 BEAST_EXPECT(hash(Book(a1, a2, domain1)) == hash(Book(a1, a2, domain1)));
518 BEAST_EXPECT(hash(Book(a1, a3, domain1)) == hash(Book(a1, a3, domain1)));
519 BEAST_EXPECT(hash(Book(a1, a4, domain1)) == hash(Book(a1, a4, domain1)));
520 BEAST_EXPECT(hash(Book(a2, a3, domain1)) == hash(Book(a2, a3, domain1)));
521 BEAST_EXPECT(hash(Book(a2, a4, domain1)) == hash(Book(a2, a4, domain1)));
522 BEAST_EXPECT(hash(Book(a3, a4, domain1)) == hash(Book(a3, a4, domain1)));
523 BEAST_EXPECT(hash(Book(a1, a2, std::nullopt)) == hash(Book(a1, a2, std::nullopt)));
524
525 // Comparing Books with domain1 vs no domain
526 BEAST_EXPECT(hash(Book(a1, a2, std::nullopt)) != hash(Book(a1, a2, domain1)));
527 BEAST_EXPECT(hash(Book(a1, a3, std::nullopt)) != hash(Book(a1, a3, domain1)));
528 BEAST_EXPECT(hash(Book(a1, a4, std::nullopt)) != hash(Book(a1, a4, domain1)));
529 BEAST_EXPECT(hash(Book(a2, a3, std::nullopt)) != hash(Book(a2, a3, domain1)));
530 BEAST_EXPECT(hash(Book(a2, a4, std::nullopt)) != hash(Book(a2, a4, domain1)));
531 BEAST_EXPECT(hash(Book(a3, a4, std::nullopt)) != hash(Book(a3, a4, domain1)));
532
533 // Books with domain1 but different Issues
534 BEAST_EXPECT(hash(Book(a1, a2, domain1)) != hash(Book(a1, a3, domain1)));
535 BEAST_EXPECT(hash(Book(a1, a2, domain1)) != hash(Book(a1, a4, domain1)));
536 BEAST_EXPECT(hash(Book(a2, a3, domain1)) != hash(Book(a2, a4, domain1)));
537 BEAST_EXPECT(hash(Book(a1, a2, domain1)) != hash(Book(a2, a3, domain1)));
538 BEAST_EXPECT(hash(Book(a2, a4, domain1)) != hash(Book(a3, a4, domain1)));
539 BEAST_EXPECT(hash(Book(a3, a4, domain1)) != hash(Book(a1, a4, domain1)));
540
541 // Books with domain1 and domain2
542 BEAST_EXPECT(hash(Book(a1, a2, domain1)) != hash(Book(a1, a2, domain2)));
543 BEAST_EXPECT(hash(Book(a1, a3, domain1)) != hash(Book(a1, a3, domain2)));
544 BEAST_EXPECT(hash(Book(a1, a4, domain1)) != hash(Book(a1, a4, domain2)));
545 BEAST_EXPECT(hash(Book(a2, a3, domain1)) != hash(Book(a2, a3, domain2)));
546 BEAST_EXPECT(hash(Book(a2, a4, domain1)) != hash(Book(a2, a4, domain2)));
547 BEAST_EXPECT(hash(Book(a3, a4, domain1)) != hash(Book(a3, a4, domain2)));
548 }
549
550 //--------------------------------------------------------------------------
551
552 template <class Set>
553 void
555 {
556 Currency const c1(1);
557 AccountID const i1(1);
558 Currency const c2(2);
559 AccountID const i2(2);
560 Issue const a1(c1, i1);
561 Issue const a2(c2, i2);
562 Book const b1(a1, a2, std::nullopt);
563 Book const b2(a2, a1, std::nullopt);
564
565 uint256 const domain1{1};
566 uint256 const domain2{2};
567
568 Book const b1D1(a1, a2, domain1);
569 Book const b2D1(a2, a1, domain1);
570 Book const b1D2(a1, a2, domain2);
571 Book const b2D2(a2, a1, domain2);
572
573 {
574 Set c;
575
576 c.insert(b1);
577 if (!BEAST_EXPECT(c.size() == 1))
578 return;
579 c.insert(b2);
580 if (!BEAST_EXPECT(c.size() == 2))
581 return;
582
583 if (!BEAST_EXPECT(c.erase(Book(a1, a1, std::nullopt)) == 0))
584 return;
585 if (!BEAST_EXPECT(c.erase(Book(a1, a2, std::nullopt)) == 1))
586 return;
587 if (!BEAST_EXPECT(c.erase(Book(a2, a1, std::nullopt)) == 1))
588 return;
589 if (!BEAST_EXPECT(c.empty()))
590 return;
591 }
592
593 {
594 Set c;
595
596 c.insert(b1);
597 if (!BEAST_EXPECT(c.size() == 1))
598 return;
599 c.insert(b2);
600 if (!BEAST_EXPECT(c.size() == 2))
601 return;
602
603 if (!BEAST_EXPECT(c.erase(Book(a1, a1, std::nullopt)) == 0))
604 return;
605 if (!BEAST_EXPECT(c.erase(Book(a1, a2, std::nullopt)) == 1))
606 return;
607 if (!BEAST_EXPECT(c.erase(Book(a2, a1, std::nullopt)) == 1))
608 return;
609 if (!BEAST_EXPECT(c.empty()))
610 return;
611
612#if STL_SET_HAS_EMPLACE
613 c.emplace(a1, a2);
614 if (!BEAST_EXPECT(c.size() == 1))
615 return;
616 c.emplace(a2, a1);
617 if (!BEAST_EXPECT(c.size() == 2))
618 return;
619#endif
620 }
621
622 {
623 Set c;
624
625 c.insert(b1D1);
626 if (!BEAST_EXPECT(c.size() == 1))
627 return;
628 c.insert(b2D1);
629 if (!BEAST_EXPECT(c.size() == 2))
630 return;
631 c.insert(b1D2);
632 if (!BEAST_EXPECT(c.size() == 3))
633 return;
634 c.insert(b2D2);
635 if (!BEAST_EXPECT(c.size() == 4))
636 return;
637
638 // Try removing non-existent elements
639 if (!BEAST_EXPECT(c.erase(Book(a2, a2, domain1)) == 0))
640 return;
641
642 if (!BEAST_EXPECT(c.erase(Book(a1, a2, domain1)) == 1))
643 return;
644 if (!BEAST_EXPECT(c.erase(Book(a2, a1, domain1)) == 1))
645 return;
646 if (!BEAST_EXPECT(c.size() == 2))
647 return;
648
649 if (!BEAST_EXPECT(c.erase(Book(a1, a2, domain2)) == 1))
650 return;
651 if (!BEAST_EXPECT(c.erase(Book(a2, a1, domain2)) == 1))
652 return;
653 if (!BEAST_EXPECT(c.empty()))
654 return;
655 }
656
657 {
658 Set c;
659
660 c.insert(b1);
661 c.insert(b2);
662 c.insert(b1D1);
663 c.insert(b2D1);
664 if (!BEAST_EXPECT(c.size() == 4))
665 return;
666
667 if (!BEAST_EXPECT(c.erase(Book(a1, a2, std::nullopt)) == 1))
668 return;
669 if (!BEAST_EXPECT(c.erase(Book(a2, a1, std::nullopt)) == 1))
670 return;
671 if (!BEAST_EXPECT(c.size() == 2))
672 return;
673
674 if (!BEAST_EXPECT(c.erase(Book(a1, a2, domain1)) == 1))
675 return;
676 if (!BEAST_EXPECT(c.erase(Book(a2, a1, domain1)) == 1))
677 return;
678 if (!BEAST_EXPECT(c.empty()))
679 return;
680 }
681 }
682
683 template <class Map>
684 void
686 {
687 Currency const c1(1);
688 AccountID const i1(1);
689 Currency const c2(2);
690 AccountID const i2(2);
691 Issue const a1(c1, i1);
692 Issue const a2(c2, i2);
693 Book const b1(a1, a2, std::nullopt);
694 Book const b2(a2, a1, std::nullopt);
695
696 uint256 const domain1{1};
697 uint256 const domain2{2};
698
699 Book const b1D1(a1, a2, domain1);
700 Book const b2D1(a2, a1, domain1);
701 Book const b1D2(a1, a2, domain2);
702 Book const b2D2(a2, a1, domain2);
703
704 // typename Map::value_type value_type;
705 // std::pair <Book const, int> value_type;
706
707 {
708 Map c;
709
710 // c.insert (value_type (b1, 1));
711 c.insert(std::make_pair(b1, 1));
712 if (!BEAST_EXPECT(c.size() == 1))
713 return;
714 // c.insert (value_type (b2, 2));
715 c.insert(std::make_pair(b2, 1));
716 if (!BEAST_EXPECT(c.size() == 2))
717 return;
718
719 if (!BEAST_EXPECT(c.erase(Book(a1, a1, std::nullopt)) == 0))
720 return;
721 if (!BEAST_EXPECT(c.erase(Book(a1, a2, std::nullopt)) == 1))
722 return;
723 if (!BEAST_EXPECT(c.erase(Book(a2, a1, std::nullopt)) == 1))
724 return;
725 if (!BEAST_EXPECT(c.empty()))
726 return;
727 }
728
729 {
730 Map c;
731
732 // c.insert (value_type (b1, 1));
733 c.insert(std::make_pair(b1, 1));
734 if (!BEAST_EXPECT(c.size() == 1))
735 return;
736 // c.insert (value_type (b2, 2));
737 c.insert(std::make_pair(b2, 1));
738 if (!BEAST_EXPECT(c.size() == 2))
739 return;
740
741 if (!BEAST_EXPECT(c.erase(Book(a1, a1, std::nullopt)) == 0))
742 return;
743 if (!BEAST_EXPECT(c.erase(Book(a1, a2, std::nullopt)) == 1))
744 return;
745 if (!BEAST_EXPECT(c.erase(Book(a2, a1, std::nullopt)) == 1))
746 return;
747 if (!BEAST_EXPECT(c.empty()))
748 return;
749 }
750
751 {
752 Map c;
753
754 c.insert(std::make_pair(b1D1, 10));
755 if (!BEAST_EXPECT(c.size() == 1))
756 return;
757 c.insert(std::make_pair(b2D1, 20));
758 if (!BEAST_EXPECT(c.size() == 2))
759 return;
760 c.insert(std::make_pair(b1D2, 30));
761 if (!BEAST_EXPECT(c.size() == 3))
762 return;
763 c.insert(std::make_pair(b2D2, 40));
764 if (!BEAST_EXPECT(c.size() == 4))
765 return;
766
767 // Try removing non-existent elements
768 if (!BEAST_EXPECT(c.erase(Book(a2, a2, domain1)) == 0))
769 return;
770
771 if (!BEAST_EXPECT(c.erase(Book(a1, a2, domain1)) == 1))
772 return;
773 if (!BEAST_EXPECT(c.erase(Book(a2, a1, domain1)) == 1))
774 return;
775 if (!BEAST_EXPECT(c.size() == 2))
776 return;
777
778 if (!BEAST_EXPECT(c.erase(Book(a1, a2, domain2)) == 1))
779 return;
780 if (!BEAST_EXPECT(c.erase(Book(a2, a1, domain2)) == 1))
781 return;
782 if (!BEAST_EXPECT(c.empty()))
783 return;
784 }
785
786 {
787 Map c;
788
789 c.insert(std::make_pair(b1, 1));
790 c.insert(std::make_pair(b2, 2));
791 c.insert(std::make_pair(b1D1, 3));
792 c.insert(std::make_pair(b2D1, 4));
793 if (!BEAST_EXPECT(c.size() == 4))
794 return;
795
796 // Try removing non-existent elements
797 if (!BEAST_EXPECT(c.erase(Book(a1, a1, domain1)) == 0))
798 return;
799 if (!BEAST_EXPECT(c.erase(Book(a2, a2, domain2)) == 0))
800 return;
801
802 if (!BEAST_EXPECT(c.erase(Book(a1, a2, std::nullopt)) == 1))
803 return;
804 if (!BEAST_EXPECT(c.erase(Book(a2, a1, std::nullopt)) == 1))
805 return;
806 if (!BEAST_EXPECT(c.size() == 2))
807 return;
808
809 if (!BEAST_EXPECT(c.erase(Book(a1, a2, domain1)) == 1))
810 return;
811 if (!BEAST_EXPECT(c.erase(Book(a2, a1, domain1)) == 1))
812 return;
813 if (!BEAST_EXPECT(c.empty()))
814 return;
815 }
816 }
817
818 void
820 {
821 testcase("std::set <Book>");
823
824 testcase("std::set <Book>");
826
827#if XRPL_ASSETS_ENABLE_STD_HASH
828 testcase("std::unordered_set <Book>");
830
831 testcase("std::unordered_set <Book>");
833#endif
834
835 testcase("hash_set <Book>");
837
838 testcase("hash_set <Book>");
840 }
841
842 void
844 {
845 testcase("std::map <Book, int>");
847
848 testcase("std::map <Book, int>");
850
851#if XRPL_ASSETS_ENABLE_STD_HASH
852 testcase("std::unordered_map <Book, int>");
854
855 testcase("std::unordered_map <Book, int>");
857
858 testcase("hash_map <Book, int>");
860
861 testcase("hash_map <Book, int>");
863#endif
864 }
865
866 //--------------------------------------------------------------------------
867
868 void
870 {
871 testcase("issueFromJson");
872
873 // Valid XRP — no issuer field
874 {
875 json::Value jv;
876 jv[jss::currency] = "XRP";
877 auto const issue = issueFromJson(jv);
878 BEAST_EXPECT(isXRP(issue));
879 }
880
881 // Valid IOU — legitimate issuer
882 {
883 json::Value jv;
884 jv[jss::currency] = "USD";
885 jv[jss::issuer] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
886 auto const issue = issueFromJson(jv);
887 BEAST_EXPECT(!isXRP(issue));
888 BEAST_EXPECT(issue.account != noAccount());
889 }
890
891 // noAccount() is the MPT sentinel in binary serialization - must be
892 // rejected
893 try
894 {
895 json::Value jv;
896 jv[jss::currency] = "USD";
897 jv[jss::issuer] = to_string(noAccount());
898 issueFromJson(jv);
899 fail("noAccount() accepted as IOU issuer");
900 }
901 catch (...)
902 {
903 pass();
904 }
905
906 // xrpAccount() is the XRP sentinel (all zeros) - must be rejected
907 // as IOU issuer
908 try
909 {
910 json::Value jv;
911 jv[jss::currency] = "USD";
912 jv[jss::issuer] = to_string(xrpAccount());
913 issueFromJson(jv);
914 fail("xrpAccount() accepted as IOU issuer");
915 }
916 catch (...)
917 {
918 pass();
919 }
920
921 // Invalid base58 — must be rejected
922 try
923 {
924 json::Value jv;
925 jv[jss::currency] = "USD";
926 jv[jss::issuer] = "not_a_valid_address";
927 issueFromJson(jv);
928 fail("invalid base58 accepted as IOU issuer");
929 }
930 catch (...)
931 {
932 pass();
933 }
934
935 // Non-XRP currency with no issuer field — must be rejected
936 try
937 {
938 json::Value jv;
939 jv[jss::currency] = "USD";
940 issueFromJson(jv);
941 fail("missing issuer accepted");
942 }
943 catch (...)
944 {
945 pass();
946 }
947
948 // XRP with an issuer field — must be rejected
949 try
950 {
951 json::Value jv;
952 jv[jss::currency] = "XRP";
953 jv[jss::issuer] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
954 issueFromJson(jv);
955 fail("XRP with issuer accepted");
956 }
957 catch (...)
958 {
959 pass();
960 }
961 }
962
963 void
964 run() override
965 {
966 testcase("Currency");
968
969 testcase("AccountID");
971
972 // ---
973
974 testcase("Issue");
976
977 testcase("Issue");
979
982
983 // ---
984
985 testcase("Book");
987
988 testcase("Book");
990
991 testBookSets();
992 testBookMaps();
993
994 // ---
997
998 // ---
1000 }
1001};
1002
1004
1005} // namespace xrpl
A testsuite class.
Definition suite.h:52
void pass()
Record a successful test condition.
Definition suite.h:532
void fail(String const &reason, char const *file, int line)
Record a failure.
Definition suite.h:554
TestcaseT testcase
Memberspace for declaring test cases.
Definition suite.h:155
Represents a JSON value.
Definition json_value.h:117
Specifies an order book.
Definition Book.h:28
void run() override
Runs the suite.
void testIssueDomainMaps()
void testIssueDomainMap()
void testIssueDomainSet()
void testIssueDomainSets()
A currency issued by an account.
Definition Issue.h:18
T make_pair(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
Issue issueFromJson(json::Value const &v)
Definition Issue.cpp:89
bool isXRP(AccountID const &c)
Definition AccountID.h:84
BaseUInt< 160, detail::CurrencyTag > Currency
Currency is a hash representing a specific currency.
Definition UintTypes.h:42
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:651
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:34
AccountID const & noAccount()
A placeholder for empty accounts.
AccountID const & xrpAccount()
Compute AccountID from public key.
BaseUInt< 256 > uint256
Definition base_uint.h:580
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, xrpl)