rippled
Loading...
Searching...
No Matches
MultiApiJson_test.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/XRPLF/rippled/
4 Copyright (c) 2023 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 <xrpl/beast/unit_test.h>
21#include <xrpl/protocol/MultiApiJson.h>
22
23#include <cstdint>
24#include <limits>
25#include <optional>
26#include <type_traits>
27#include <utility>
28
29namespace ripple {
30namespace test {
31
32namespace {
33
34// This needs to be in a namespace because of deduction guide
35template <typename... Ts>
36struct Overload : Ts...
37{
38 using Ts::operator()...;
39};
40template <typename... Ts>
41Overload(Ts...) -> Overload<Ts...>;
42
43} // namespace
44
46{
47 static auto
48 makeJson(char const* key, int val)
49 {
51 obj1[key] = val;
52 return obj1;
53 }
54
55 void
56 run() override
57 {
59
60 Json::Value const obj1 = makeJson("value", 1);
61 Json::Value const obj2 = makeJson("value", 2);
62 Json::Value const obj3 = makeJson("value", 3);
63 Json::Value const jsonNull{};
64
65 MultiApiJson<1, 3> subject{};
66 static_assert(sizeof(subject) == sizeof(subject.val));
67 static_assert(subject.size == subject.val.size());
68 static_assert(
69 std::is_same_v<decltype(subject.val), std::array<Json::Value, 3>>);
70
71 BEAST_EXPECT(subject.val.size() == 3);
72 BEAST_EXPECT(
73 (subject.val ==
74 std::array<Json::Value, 3>{jsonNull, jsonNull, jsonNull}));
75
76 subject.val[0] = obj1;
77 subject.val[1] = obj2;
78
79 {
80 testcase("forApiVersions, forAllApiVersions");
81
82 // Some static data for test inputs
83 static int const primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23,
84 29, 31, 37, 41, 43, 47, 53, 59, 61,
85 67, 71, 73, 79, 83, 89, 97};
86 static_assert(std::size(primes) > RPC::apiMaximumValidVersion);
87
89 static_assert(
90 s1.size ==
93
94 int productAllVersions = 1;
95 for (unsigned i = RPC::apiMinimumSupportedVersion;
97 ++i)
98 {
99 auto const index = i - RPC::apiMinimumSupportedVersion;
100 BEAST_EXPECT(index == s1.index(i));
101 BEAST_EXPECT(s1.valid(i));
102 s1.val[index] = makeJson("value", primes[i]);
103 productAllVersions *= primes[i];
104 }
105 BEAST_EXPECT(!s1.valid(0));
106 BEAST_EXPECT(!s1.valid(RPC::apiMaximumValidVersion + 1));
107 BEAST_EXPECT(
108 !s1.valid(std::numeric_limits<
109 decltype(RPC::apiMaximumValidVersion.value)>::max()));
110
111 int result = 1;
112 static_assert(
118 std::as_const(s1).visit(),
119 [this](
120 Json::Value const& json,
121 unsigned int version,
122 int* result) {
123 BEAST_EXPECT(
125 version <= RPC::apiMinimumSupportedVersion + 1);
126 if (BEAST_EXPECT(json.isMember("value")))
127 {
128 *result *= json["value"].asInt();
129 }
130 },
131 &result);
132 BEAST_EXPECT(
133 result ==
136
137 // Check all the values with mutable data
139 s1.visit(), [&s1, this](Json::Value& json, auto version) {
140 BEAST_EXPECT(s1.val[s1.index(version)] == json);
141 if (BEAST_EXPECT(json.isMember("value")))
142 {
143 BEAST_EXPECT(json["value"].asInt() == primes[version]);
144 }
145 });
146
147 result = 1;
149 std::as_const(s1).visit(),
150 [this](
151 Json::Value const& json,
152 unsigned int version,
153 int* result) {
154 BEAST_EXPECT(
156 version <= RPC::apiMaximumValidVersion);
157 if (BEAST_EXPECT(json.isMember("value")))
158 {
159 *result *= json["value"].asInt();
160 }
161 },
162 &result);
163
164 BEAST_EXPECT(result == productAllVersions);
165
166 // Several overloads we want to fail
167 static_assert([](auto&& v) {
168 return !requires {
170 std::forward<decltype(v)>(v).visit(), //
171 [](Json::Value&, auto) {}); // missing const
172 };
173 }(std::as_const(s1)));
174 static_assert([](auto&& v) {
175 return !requires {
177 std::forward<decltype(v)>(v).visit(), //
178 [](Json::Value&) {}); // missing const
179 };
180 }(std::as_const(s1)));
181 static_assert([](auto&& v) {
182 return !requires {
184 std::forward<decltype(v)>(v).visit(), //
185 []() {}); // missing parameters
186 };
187 }(std::as_const(s1)));
188 static_assert([](auto&& v) {
189 return !requires {
191 std::forward<decltype(v)>(v).visit(), //
192 [](auto) {},
193 1); // missing parameters
194 };
195 }(std::as_const(s1)));
196 static_assert([](auto&& v) {
197 return !requires {
199 std::forward<decltype(v)>(v).visit(), //
200 [](auto, auto) {},
201 1); // missing parameters
202 };
203 }(std::as_const(s1)));
204 static_assert([](auto&& v) {
205 return !requires {
207 std::forward<decltype(v)>(v).visit(), //
208 [](auto, auto, char const*) {},
209 1); // parameter type mismatch
210 };
211 }(std::as_const(s1)));
212
213 // Sanity checks
214 static_assert([](auto&& v) {
215 return requires {
217 std::forward<decltype(v)>(v).visit(), //
218 [](auto) {});
219 };
220 }(s1));
221 static_assert([](auto&& v) {
222 return requires {
224 std::forward<decltype(v)>(v).visit(), //
225 [](Json::Value const&) {});
226 };
227 }(std::as_const(s1)));
228 static_assert([](auto&& v) {
229 return requires {
231 std::forward<decltype(v)>(v).visit(), //
232 [](auto...) {});
233 };
234 }(s1));
235 static_assert([](auto&& v) {
236 return requires {
238 std::forward<decltype(v)>(v).visit(), //
239 [](Json::Value const&, auto...) {});
240 };
241 }(std::as_const(s1)));
242 static_assert([](auto&& v) {
243 return requires {
245 std::forward<decltype(v)>(v).visit(), //
246 [](Json::Value&, auto, auto, auto...) {},
247 0,
248 "");
249 };
250 }(s1));
251 static_assert([](auto&& v) {
252 return requires {
254 std::forward<decltype(v)>(v).visit(), //
255 []<unsigned int Version>(
256 Json::Value const&,
258 int,
259 char const*) {},
260 0,
261 "");
262 };
263 }(std::as_const(s1)));
264 static_assert([](auto&& v) {
265 return requires {
267 std::forward<decltype(v)>(v).visit(), //
268 [](auto...) {});
269 };
270 }(std::move(s1)));
271 static_assert([](auto&& v) {
272 return requires {
274 std::forward<decltype(v)>(v).visit(), //
275 [](auto...) {});
276 };
277 }(std::move(std::as_const(s1))));
278 }
279
280 {
281 testcase("default copy construction / assignment");
282
283 MultiApiJson<1, 3> x{subject};
284
285 BEAST_EXPECT(x.val.size() == subject.val.size());
286 BEAST_EXPECT(x.val[0] == subject.val[0]);
287 BEAST_EXPECT(x.val[1] == subject.val[1]);
288 BEAST_EXPECT(x.val[2] == subject.val[2]);
289 BEAST_EXPECT(x.val == subject.val);
290 BEAST_EXPECT(&x.val[0] != &subject.val[0]);
291 BEAST_EXPECT(&x.val[1] != &subject.val[1]);
292 BEAST_EXPECT(&x.val[2] != &subject.val[2]);
293
295 BEAST_EXPECT((y.val == std::array<Json::Value, 3>{}));
296 y = subject;
297 BEAST_EXPECT(y.val == subject.val);
298 BEAST_EXPECT(&y.val[0] != &subject.val[0]);
299 BEAST_EXPECT(&y.val[1] != &subject.val[1]);
300 BEAST_EXPECT(&y.val[2] != &subject.val[2]);
301
302 y = std::move(x);
303 BEAST_EXPECT(y.val == subject.val);
304 BEAST_EXPECT(&y.val[0] != &subject.val[0]);
305 BEAST_EXPECT(&y.val[1] != &subject.val[1]);
306 BEAST_EXPECT(&y.val[2] != &subject.val[2]);
307 }
308
309 {
310 testcase("set");
311
312 auto x = MultiApiJson<1, 2>{Json::objectValue};
313 x.set("name1", 42);
314 BEAST_EXPECT(x.val[0].isMember("name1"));
315 BEAST_EXPECT(x.val[1].isMember("name1"));
316 BEAST_EXPECT(x.val[0]["name1"].isInt());
317 BEAST_EXPECT(x.val[1]["name1"].isInt());
318 BEAST_EXPECT(x.val[0]["name1"].asInt() == 42);
319 BEAST_EXPECT(x.val[1]["name1"].asInt() == 42);
320
321 x.set("name2", "bar");
322 BEAST_EXPECT(x.val[0].isMember("name2"));
323 BEAST_EXPECT(x.val[1].isMember("name2"));
324 BEAST_EXPECT(x.val[0]["name2"].isString());
325 BEAST_EXPECT(x.val[1]["name2"].isString());
326 BEAST_EXPECT(x.val[0]["name2"].asString() == "bar");
327 BEAST_EXPECT(x.val[1]["name2"].asString() == "bar");
328
329 // Tests of requires clause - these are expected to match
330 static_assert([](auto&& v) {
331 return requires { v.set("name", Json::nullValue); };
332 }(x));
333 static_assert([](auto&& v) {
334 return requires { v.set("name", "value"); };
335 }(x));
336 static_assert(
337 [](auto&& v) { return requires { v.set("name", true); }; }(x));
338 static_assert(
339 [](auto&& v) { return requires { v.set("name", 42); }; }(x));
340
341 // Tests of requires clause - these are expected NOT to match
342 struct foo_t final
343 {
344 };
345 static_assert([](auto&& v) {
346 return !requires { v.set("name", foo_t{}); };
347 }(x));
348 static_assert([](auto&& v) {
349 return !requires { v.set("name", std::nullopt); };
350 }(x));
351 }
352
353 {
354 testcase("isMember");
355
356 // Well defined behaviour even if we have different types of members
357 BEAST_EXPECT(subject.isMember("foo") == decltype(subject)::none);
358
359 {
360 // All variants have element "One", none have element "Two"
361 MultiApiJson<1, 2> s1{};
362 s1.val[0] = makeJson("One", 12);
363 s1.val[1] = makeJson("One", 42);
364 BEAST_EXPECT(s1.isMember("One") == decltype(s1)::all);
365 BEAST_EXPECT(s1.isMember("Two") == decltype(s1)::none);
366 }
367
368 {
369 // Some variants have element "One" and some have "Two"
370 MultiApiJson<1, 2> s2{};
371 s2.val[0] = makeJson("One", 12);
372 s2.val[1] = makeJson("Two", 42);
373 BEAST_EXPECT(s2.isMember("One") == decltype(s2)::some);
374 BEAST_EXPECT(s2.isMember("Two") == decltype(s2)::some);
375 }
376
377 {
378 // Not all variants have element "One", because last one is null
379 MultiApiJson<1, 3> s3{};
380 s3.val[0] = makeJson("One", 12);
381 s3.val[1] = makeJson("One", 42);
382 BEAST_EXPECT(s3.isMember("One") == decltype(s3)::some);
383 BEAST_EXPECT(s3.isMember("Two") == decltype(s3)::none);
384 }
385 }
386
387 {
388 testcase("visitor");
389
390 MultiApiJson<1, 3> s1{};
391 s1.val[0] = makeJson("value", 2);
392 s1.val[1] = makeJson("value", 3);
393 s1.val[2] = makeJson("value", 5);
394
395 BEAST_EXPECT(not s1.valid(0));
396 BEAST_EXPECT(s1.index(0) == 0);
397
398 BEAST_EXPECT(s1.valid(1));
399 BEAST_EXPECT(s1.index(1) == 0);
400
401 BEAST_EXPECT(not s1.valid(4));
402
403 // Test different overloads
404 static_assert([](auto&& v) {
405 return requires {
406 v.visitor(
407 v,
410 });
411 };
412 }(s1));
413 BEAST_EXPECT(
414 s1.visitor(
415 s1,
417 Overload{
418 [](Json::Value& v,
419 std::integral_constant<unsigned, 1>) {
420 return v["value"].asInt();
421 },
422 [](Json::Value const&, auto) { return 0; },
423 [](auto, auto) { return 0; }}) == 2);
424
425 static_assert([](auto&& v) {
426 return requires {
427 v.visitor(
428 v,
430 [](Json::Value&) {});
431 };
432 }(s1));
433 BEAST_EXPECT(
434 s1.visitor(
435 s1,
437 Overload{
438 [](Json::Value& v) { return v["value"].asInt(); },
439 [](Json::Value const&) { return 0; },
440 [](auto...) { return 0; }}) == 2);
441
442 static_assert([](auto&& v) {
443 return requires {
444 v.visitor(
445 v,
447 [](Json::Value const&,
449 };
450 }(std::as_const(s1)));
451 BEAST_EXPECT(
452 s1.visitor(
453 std::as_const(s1),
455 Overload{
456 [](Json::Value const& v,
457 std::integral_constant<unsigned, 2>) {
458 return v["value"].asInt();
459 },
460 [](Json::Value&, auto) { return 0; },
461 [](auto, auto) { return 0; }}) == 3);
462
463 static_assert([](auto&& v) {
464 return requires {
465 v.visitor(
466 v,
468 [](Json::Value const&) {});
469 };
470 }(std::as_const(s1)));
471 BEAST_EXPECT(
472 s1.visitor(
473 std::as_const(s1),
475 Overload{
476 [](Json::Value const& v) { return v["value"].asInt(); },
477 [](Json::Value&) { return 0; },
478 [](auto...) { return 0; }}) == 3);
479
480 static_assert([](auto&& v) {
481 return requires {
482 v.visitor(v, 1, [](Json::Value&, unsigned) {});
483 };
484 }(s1));
485 BEAST_EXPECT(
486 s1.visitor(
487 s1, //
488 3u,
489 Overload{
490 [](Json::Value& v, unsigned) {
491 return v["value"].asInt();
492 },
493 [](Json::Value const&, unsigned) { return 0; },
494 [](auto, auto) { return 0; }}) == 5);
495
496 static_assert([](auto&& v) {
497 return requires { v.visitor(v, 1, [](Json::Value&) {}); };
498 }(s1));
499 BEAST_EXPECT(
500 s1.visitor(
501 s1, //
502 3,
503 Overload{
504 [](Json::Value& v) { return v["value"].asInt(); },
505 [](Json::Value const&) { return 0; },
506 [](auto...) { return 0; }}) == 5);
507
508 static_assert([](auto&& v) {
509 return requires {
510 v.visitor(v, 1, [](Json::Value const&, unsigned) {});
511 };
512 }(std::as_const(s1)));
513 BEAST_EXPECT(
514 s1.visitor(
515 std::as_const(s1), //
516 2u,
517 Overload{
518 [](Json::Value const& v, unsigned) {
519 return v["value"].asInt();
520 },
521 [](Json::Value const&, auto) { return 0; },
522 [](auto, auto) { return 0; }}) == 3);
523
524 static_assert([](auto&& v) {
525 return requires { v.visitor(v, 1, [](Json::Value const&) {}); };
526 }(std::as_const(s1)));
527 BEAST_EXPECT(
528 s1.visitor(
529 std::as_const(s1), //
530 2,
531 Overload{
532 [](Json::Value const& v) { return v["value"].asInt(); },
533 [](Json::Value&) { return 0; },
534 [](auto...) { return 0; }}) == 3);
535
536 // Test type conversions
537 BEAST_EXPECT(
538 s1.visitor(
539 s1,
541 [](Json::Value& v, unsigned) {
542 return v["value"].asInt();
543 }) == 2);
544 BEAST_EXPECT(
545 s1.visitor(
546 std::as_const(s1),
548 [](Json::Value const& v, unsigned) {
549 return v["value"].asInt();
550 }) == 3);
551 BEAST_EXPECT(
552 s1.visitor(
553 s1, // to const
555 [](Json::Value const& v, auto) {
556 return v["value"].asInt();
557 }) == 5);
558 BEAST_EXPECT(
559 s1.visitor(
560 s1, // to const
562 [](Json::Value const& v) { return v["value"].asInt(); }) ==
563 5);
564 BEAST_EXPECT(
565 s1.visitor(
566 s1,
567 3, // to long
568 [](Json::Value& v, long) { return v["value"].asInt(); }) ==
569 5);
570 BEAST_EXPECT(
571 s1.visitor(
572 std::as_const(s1),
573 1, // to long
574 [](Json::Value const& v, long) {
575 return v["value"].asInt();
576 }) == 2);
577 BEAST_EXPECT(
578 s1.visitor(
579 s1, // to const
580 2,
581 [](Json::Value const& v, auto) {
582 return v["value"].asInt();
583 }) == 3);
584 BEAST_EXPECT(
585 s1.visitor(
586 s1, // type deduction
587 2,
588 [](auto& v, auto) { return v["value"].asInt(); }) == 3);
589 BEAST_EXPECT(
590 s1.visitor(
591 s1, // to const, type deduction
592 2,
593 [](auto const& v, auto) { return v["value"].asInt(); }) ==
594 3);
595 BEAST_EXPECT(
596 s1.visitor(
597 s1, // type deduction
598 2,
599 [](auto& v) { return v["value"].asInt(); }) == 3);
600 BEAST_EXPECT(
601 s1.visitor(
602 s1, // to const, type deduction
603 2,
604 [](auto const& v) { return v["value"].asInt(); }) == 3);
605
606 // Test passing of additional arguments
607 BEAST_EXPECT(
608 s1.visitor(
609 s1,
611 [](Json::Value& v, auto ver, auto a1, auto a2) {
612 return ver * a1 * a2 * v["value"].asInt();
613 },
614 5,
615 7) == 2 * 5 * 7 * 3);
616 BEAST_EXPECT(
617 s1.visitor(
618 s1,
620 [](Json::Value& v, auto ver, auto... args) {
621 return ver * (1 * ... * args) * v["value"].asInt();
622 },
623 5,
624 7) == 2 * 5 * 7 * 3);
625
626 // Several overloads we want to fail
627 static_assert([](auto&& v) {
628 return !requires {
629 v.visitor(
630 v,
631 1, //
632 [](Json::Value&, auto) {}); // missing const
633 };
634 }(std::as_const(s1)));
635
636 static_assert([](auto&& v) {
637 return !requires {
638 v.visitor(
639 std::move(v), // cannot bind rvalue
640 1,
641 [](Json::Value&, auto) {});
642 };
643 }(s1));
644
645 static_assert([](auto&& v) {
646 return !requires {
647 v.visitor(
648 v,
649 1, //
650 []() {}); // missing parameter
651 };
652 }(s1));
653
654 static_assert([](auto&& v) {
655 return !requires {
656 v.visitor(
657 v,
658 1, //
659 [](Json::Value&, int, int) {}); // too many parameters
660 };
661 }(s1));
662
663 // Want these to be unambiguous
664 static_assert([](auto&& v) {
665 return requires { v.visitor(v, 1, [](auto) {}); };
666 }(s1));
667
668 static_assert([](auto&& v) {
669 return requires { v.visitor(v, 1, [](Json::Value&) {}); };
670 }(s1));
671
672 static_assert([](auto&& v) {
673 return requires {
674 v.visitor(v, 1, [](Json::Value&, auto...) {});
675 };
676 }(s1));
677
678 static_assert([](auto&& v) {
679 return requires { v.visitor(v, 1, [](Json::Value const&) {}); };
680 }(s1));
681
682 static_assert([](auto&& v) {
683 return requires {
684 v.visitor(v, 1, [](Json::Value const&, auto...) {});
685 };
686 }(s1));
687
688 static_assert([](auto&& v) {
689 return requires { v.visitor(v, 1, [](auto...) {}); };
690 }(s1));
691
692 static_assert([](auto&& v) {
693 return requires { v.visitor(v, 1, [](auto, auto...) {}); };
694 }(s1));
695
696 static_assert([](auto&& v) {
697 return requires {
698 v.visitor(v, 1, [](auto, auto, auto...) {});
699 };
700 }(s1));
701
702 static_assert([](auto&& v) {
703 return requires {
704 v.visitor(v, 1, [](auto, auto, auto...) {}, "");
705 };
706 }(s1));
707
708 static_assert([](auto&& v) {
709 return requires {
710 v.visitor(v, 1, [](auto, auto, auto, auto...) {}, "");
711 };
712 }(s1));
713 }
714
715 {
716 testcase("visit");
717
718 MultiApiJson<1, 3> s1{};
719 s1.val[0] = makeJson("value", 2);
720 s1.val[1] = makeJson("value", 3);
721 s1.val[2] = makeJson("value", 5);
722
723 // Test different overloads
724 static_assert([](auto&& v) {
725 return requires {
726 v.visit(
729 });
730 };
731 }(s1));
732 BEAST_EXPECT(
733 s1.visit(
735 Overload{
736 [](Json::Value& v,
737 std::integral_constant<unsigned, 1>) {
738 return v["value"].asInt();
739 },
740 [](Json::Value const&, auto) { return 0; },
741 [](auto, auto) { return 0; }}) == 2);
742 static_assert([](auto&& v) {
743 return requires {
744 v.visit()(
747 });
748 };
749 }(s1));
750 BEAST_EXPECT(
751 s1.visit()(
753 Overload{
754 [](Json::Value& v,
755 std::integral_constant<unsigned, 1>) {
756 return v["value"].asInt();
757 },
758 [](Json::Value const&, auto) { return 0; },
759 [](auto, auto) { return 0; }}) == 2);
760
761 static_assert([](auto&& v) {
762 return requires {
763 v.visit(
765 [](Json::Value&) {});
766 };
767 }(s1));
768 BEAST_EXPECT(
769 s1.visit(
771 Overload{
772 [](Json::Value& v) { return v["value"].asInt(); },
773 [](Json::Value const&) { return 0; },
774 [](auto...) { return 0; }}) == 2);
775 static_assert([](auto&& v) {
776 return requires {
777 v.visit()(
779 [](Json::Value&) {});
780 };
781 }(s1));
782 BEAST_EXPECT(
783 s1.visit()(
785 Overload{
786 [](Json::Value& v) { return v["value"].asInt(); },
787 [](Json::Value const&) { return 0; },
788 [](auto...) { return 0; }}) == 2);
789
790 static_assert([](auto&& v) {
791 return requires {
792 v.visit(
794 [](Json::Value const&,
796 };
797 }(std::as_const(s1)));
798 BEAST_EXPECT(
801 Overload{
802 [](Json::Value const& v,
804 return v["value"].asInt();
805 },
806 [](Json::Value&, auto) { return 0; },
807 [](auto, auto) { return 0; }}) == 3);
808 static_assert([](auto&& v) {
809 return requires {
810 v.visit()(
812 [](Json::Value const&,
814 };
815 }(std::as_const(s1)));
816 BEAST_EXPECT(
817 std::as_const(s1).visit()(
819 Overload{
820 [](Json::Value const& v,
822 return v["value"].asInt();
823 },
824 [](Json::Value&, auto) { return 0; },
825 [](auto, auto) { return 0; }}) == 3);
826
827 static_assert([](auto&& v) {
828 return requires {
829 v.visit(
831 [](Json::Value const&) {});
832 };
833 }(std::as_const(s1)));
834 BEAST_EXPECT(
837 Overload{
838 [](Json::Value const& v) { return v["value"].asInt(); },
839 [](Json::Value&) { return 0; },
840 [](auto...) { return 0; }}) == 3);
841 static_assert([](auto&& v) {
842 return requires {
843 v.visit()(
845 [](Json::Value const&) {});
846 };
847 }(std::as_const(s1)));
848 BEAST_EXPECT(
849 std::as_const(s1).visit()(
851 Overload{
852 [](Json::Value const& v) { return v["value"].asInt(); },
853 [](Json::Value&) { return 0; },
854 [](auto...) { return 0; }}) == 3);
855
856 static_assert([](auto&& v) {
857 return requires { v.visit(1, [](Json::Value&, unsigned) {}); };
858 }(s1));
859 BEAST_EXPECT(
860 s1.visit(
861 3u,
862 Overload{
863 [](Json::Value& v, unsigned) {
864 return v["value"].asInt();
865 },
866 [](Json::Value const&, unsigned) { return 0; },
867 [](Json::Value&, auto) { return 0; },
868 [](auto, auto) { return 0; }}) == 5);
869 static_assert([](auto&& v) {
870 return requires {
871 v.visit()(1, [](Json::Value&, unsigned) {});
872 };
873 }(s1));
874 BEAST_EXPECT(
875 s1.visit()(
876 3u,
877 Overload{
878 [](Json::Value& v, unsigned) {
879 return v["value"].asInt();
880 },
881 [](Json::Value const&, unsigned) { return 0; },
882 [](Json::Value&, auto) { return 0; },
883 [](auto, auto) { return 0; }}) == 5);
884
885 static_assert([](auto&& v) {
886 return requires { v.visit(1, [](Json::Value&) {}); };
887 }(s1));
888 BEAST_EXPECT(
889 s1.visit(
890 3,
891 Overload{
892 [](Json::Value& v) { return v["value"].asInt(); },
893 [](Json::Value const&) { return 0; },
894 [](auto...) { return 0; }}) == 5);
895 static_assert([](auto&& v) {
896 return requires { v.visit()(1, [](Json::Value&) {}); };
897 }(s1));
898 BEAST_EXPECT(
899 s1.visit()(
900 3,
901 Overload{
902 [](Json::Value& v) { return v["value"].asInt(); },
903 [](Json::Value const&) { return 0; },
904 [](auto...) { return 0; }}) == 5);
905
906 static_assert([](auto&& v) {
907 return requires {
908 v.visit(1, [](Json::Value const&, unsigned) {});
909 };
910 }(std::as_const(s1)));
911 BEAST_EXPECT(
913 2u,
914 Overload{
915 [](Json::Value const& v, unsigned) {
916 return v["value"].asInt();
917 },
918 [](Json::Value const&, auto) { return 0; },
919 [](Json::Value&, unsigned) { return 0; },
920 [](auto, auto) { return 0; }}) == 3);
921 static_assert([](auto&& v) {
922 return requires {
923 v.visit()(1, [](Json::Value const&, unsigned) {});
924 };
925 }(std::as_const(s1)));
926 BEAST_EXPECT(
927 std::as_const(s1).visit()(
928 2u,
929 Overload{
930 [](Json::Value const& v, unsigned) {
931 return v["value"].asInt();
932 },
933 [](Json::Value const&, auto) { return 0; },
934 [](Json::Value&, unsigned) { return 0; },
935 [](auto, auto) { return 0; }}) == 3);
936
937 static_assert([](auto&& v) {
938 return requires { v.visit(1, [](Json::Value const&) {}); };
939 }(std::as_const(s1)));
940 BEAST_EXPECT(
942 2,
943 Overload{
944 [](Json::Value const& v) { return v["value"].asInt(); },
945 [](Json::Value&) { return 0; },
946 [](auto...) { return 0; }}) == 3);
947 static_assert([](auto&& v) {
948 return requires { v.visit()(1, [](Json::Value const&) {}); };
949 }(std::as_const(s1)));
950 BEAST_EXPECT(
951 std::as_const(s1).visit()(
952 2,
953 Overload{
954 [](Json::Value const& v) { return v["value"].asInt(); },
955 [](Json::Value&) { return 0; },
956 [](auto...) { return 0; }}) == 3);
957
958 // Rvalue MultivarJson visitor only binds to regular reference
959 static_assert([](auto&& v) {
960 return !requires {
961 std::forward<decltype(v)>(v).visit(1, [](Json::Value&&) {});
962 };
963 }(std::move(s1)));
964 static_assert([](auto&& v) {
965 return !requires {
967 1, [](Json::Value const&&) {});
968 };
969 }(std::move(s1)));
970 static_assert([](auto&& v) {
971 return requires {
972 std::forward<decltype(v)>(v).visit(1, [](Json::Value&) {});
973 };
974 }(std::move(s1)));
975 static_assert([](auto&& v) {
976 return requires {
978 1, [](Json::Value const&) {});
979 };
980 }(std::move(s1)));
981 static_assert([](auto&& v) {
982 return !requires {
983 std::forward<decltype(v)>(v).visit()(
984 1, [](Json::Value&&) {});
985 };
986 }(std::move(s1)));
987 static_assert([](auto&& v) {
988 return !requires {
989 std::forward<decltype(v)>(v).visit()(
990 1, [](Json::Value const&&) {});
991 };
992 }(std::move(s1)));
993 static_assert([](auto&& v) {
994 return requires {
995 std::forward<decltype(v)>(v).visit()(
996 1, [](Json::Value&) {});
997 };
998 }(std::move(s1)));
999 static_assert([](auto&& v) {
1000 return requires {
1001 std::forward<decltype(v)>(v).visit()(
1002 1, [](Json::Value const&) {});
1003 };
1004 }(std::move(s1)));
1005 static_assert([](auto&& v) {
1006 return !requires {
1008 1, [](Json::Value const&&) {});
1009 };
1010 }(std::move(std::as_const(s1))));
1011 static_assert([](auto&& v) {
1012 return requires {
1014 1, [](Json::Value const&) {});
1015 };
1016 }(std::move(std::as_const(s1))));
1017 static_assert([](auto&& v) {
1018 return !requires {
1019 std::forward<decltype(v)>(v).visit()(
1020 1, [](Json::Value const&&) {});
1021 };
1022 }(std::move(std::as_const(s1))));
1023 static_assert([](auto&& v) {
1024 return requires {
1025 std::forward<decltype(v)>(v).visit()(
1026 1, [](Json::Value const&) {});
1027 };
1028 }(std::move(std::as_const(s1))));
1029
1030 // Missing const
1031 static_assert([](auto&& v) {
1032 return !requires {
1034 1, [](Json::Value&, auto) {});
1035 };
1036 }(std::as_const(s1)));
1037 static_assert([](auto&& v) {
1038 return !requires {
1039 std::forward<decltype(v)>(v).visit()(
1040 1, [](Json::Value&, auto) {});
1041 };
1042 }(std::as_const(s1)));
1043
1044 // Missing parameter
1045 static_assert([](auto&& v) {
1046 return !requires {
1047 std::forward<decltype(v)>(v).visit(1, []() {});
1048 };
1049 }(s1));
1050 static_assert([](auto&& v) {
1051 return !requires {
1052 std::forward<decltype(v)>(v).visit()(1, []() {});
1053 };
1054 }(s1));
1055
1056 // Sanity checks
1057 static_assert([](auto&& v) {
1058 return requires {
1059 std::forward<decltype(v)>(v).visit(1, [](auto...) {});
1060 };
1061 }(std::as_const(s1)));
1062 static_assert([](auto&& v) {
1063 return requires {
1064 std::forward<decltype(v)>(v).visit()(1, [](auto...) {});
1065 };
1066 }(std::as_const(s1)));
1067 }
1068 }
1069};
1070
1071BEAST_DEFINE_TESTSUITE(MultiApiJson, protocol, ripple);
1072
1073} // namespace test
1074} // namespace ripple
T as_const(T... args)
Represents a JSON value.
Definition json_value.h:149
Int asInt() const
A testsuite class.
Definition suite.h:55
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:155
Inject raw JSON.
Definition jtx_json.h:33
T forward(T... args)
T is_same_v
@ nullValue
'null' value
Definition json_value.h:38
@ objectValue
object value (collection of name/value pairs).
Definition json_value.h:45
static constexpr auto apiMaximumValidVersion
Definition ApiVersion.h:62
static constexpr auto apiMinimumSupportedVersion
Definition ApiVersion.h:56
static none_t const none
Definition tags.h:34
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
void forAllApiVersions(Fn const &fn, Args &&... args)
Definition ApiVersion.h:101
void forApiVersions(Fn const &fn, Args &&... args)
Definition ApiVersion.h:79
T size(T... args)
std::array< Json::Value, size > val
void run() override
Runs the suite.
static auto makeJson(char const *key, int val)
T visit(T... args)