rippled
Loading...
Searching...
No Matches
STParsedJSON_test.cpp
1#include <test/jtx.h>
2
3#include <xrpl/beast/unit_test.h>
4#include <xrpl/json/json_reader.h>
5#include <xrpl/protocol/STNumber.h>
6#include <xrpl/protocol/STParsedJSON.h>
7#include <xrpl/protocol/STXChainBridge.h>
8#include <xrpl/protocol/st.h>
9
10namespace ripple {
11
13{
14 bool
16 {
17 Json::Reader reader;
18 return reader.parse(json, to) && to.isObject();
19 }
20
21 void
23 {
24 testcase("UInt8");
25 {
27 j[sfCloseResolution] = 255;
28 STParsedJSONObject obj("Test", j);
29 BEAST_EXPECT(obj.object.has_value());
30 BEAST_EXPECT(obj.object->isFieldPresent(sfCloseResolution));
31 BEAST_EXPECT(obj.object->getFieldU8(sfCloseResolution) == 255);
32 }
33
34 // test with uint value
35 {
37 j[sfCloseResolution] = 255u;
38 STParsedJSONObject obj("Test", j);
39 BEAST_EXPECT(obj.object.has_value());
40 BEAST_EXPECT(obj.object->isFieldPresent(sfCloseResolution));
41 BEAST_EXPECT(obj.object->getFieldU8(sfCloseResolution) == 255);
42 }
43
44 // Test with string value
45 {
47 j[sfCloseResolution] = "255";
48 STParsedJSONObject obj("Test", j);
49 BEAST_EXPECT(obj.object.has_value());
50 BEAST_EXPECT(obj.object->isFieldPresent(sfCloseResolution));
51 BEAST_EXPECT(obj.object->getFieldU8(sfCloseResolution) == 255);
52 }
53
54 // Test min value for uint8
55 {
57 j[sfCloseResolution] = 0;
58 STParsedJSONObject obj("Test", j);
59 BEAST_EXPECT(obj.object.has_value());
60 BEAST_EXPECT(obj.object->getFieldU8(sfCloseResolution) == 0);
61 }
62
63 // Test out of range value for UInt8 (negative)
64 {
66 j[sfCloseResolution] = -1;
67 STParsedJSONObject obj("Test", j);
68 BEAST_EXPECT(!obj.object.has_value());
69 }
70
71 // Test out of range value for UInt8 (too large)
72 {
74 j[sfCloseResolution] = 256;
75 STParsedJSONObject obj("Test", j);
76 BEAST_EXPECT(!obj.object.has_value());
77 }
78
79 // Test bad_type (not a string/int/uint)
80 {
82 j[sfCloseResolution] = Json::Value(Json::arrayValue);
83 STParsedJSONObject obj("Test", j);
84 BEAST_EXPECT(!obj.object.has_value());
85 }
86
87 // Test bad_type (not a string/int/uint)
88 {
90 j[sfCloseResolution] = Json::Value(Json::objectValue);
91 STParsedJSONObject obj("Test", j);
92 BEAST_EXPECT(!obj.object.has_value());
93 }
94 }
95
96 void
98 {
99 testcase("UInt16");
100 // Test with int value
101 {
102 Json::Value j;
103 j[sfLedgerEntryType] = 65535;
104 STParsedJSONObject obj("Test", j);
105 BEAST_EXPECT(obj.object.has_value());
106 BEAST_EXPECT(obj.object->isFieldPresent(sfLedgerEntryType));
107 BEAST_EXPECT(obj.object->getFieldU16(sfLedgerEntryType) == 65535);
108 }
109
110 // Test with uint value
111 {
112 Json::Value j;
113 j[sfLedgerEntryType] = 65535u;
114 STParsedJSONObject obj("Test", j);
115 BEAST_EXPECT(obj.object.has_value());
116 BEAST_EXPECT(obj.object->isFieldPresent(sfLedgerEntryType));
117 BEAST_EXPECT(obj.object->getFieldU16(sfLedgerEntryType) == 65535);
118 }
119
120 // Test with string value
121 {
122 Json::Value j;
123 j[sfLedgerEntryType] = "65535";
124 STParsedJSONObject obj("Test", j);
125 BEAST_EXPECT(obj.object.has_value());
126 BEAST_EXPECT(obj.object->isFieldPresent(sfLedgerEntryType));
127 BEAST_EXPECT(obj.object->getFieldU16(sfLedgerEntryType) == 65535);
128 }
129
130 // Test min value for uint16
131 {
132 Json::Value j;
133 j[sfLedgerEntryType] = 0;
134 STParsedJSONObject obj("Test", j);
135 BEAST_EXPECT(obj.object.has_value());
136 BEAST_EXPECT(obj.object->getFieldU16(sfLedgerEntryType) == 0);
137 }
138
139 // Test out of range value for UInt16 (negative)
140 {
141 Json::Value j;
142 j[sfLedgerEntryType] = -1;
143 STParsedJSONObject obj("Test", j);
144 BEAST_EXPECT(!obj.object.has_value());
145 }
146
147 // Test out of range value for UInt16 (too large)
148 {
149 Json::Value j;
150 j[sfLedgerEntryType] = 65536;
151 STParsedJSONObject obj("Test", j);
152 BEAST_EXPECT(!obj.object.has_value());
153 }
154
155 // Test string value out of range
156 {
157 Json::Value j;
158 j[sfLedgerEntryType] = "65536";
159 STParsedJSONObject obj("Test", j);
160 BEAST_EXPECT(!obj.object.has_value());
161 }
162
163 // Test bad_type (not a string/int/uint)
164 {
165 Json::Value j;
166 j[sfLedgerEntryType] = Json::Value(Json::arrayValue);
167 STParsedJSONObject obj("Test", j);
168 BEAST_EXPECT(!obj.object.has_value());
169 }
170
171 // Test bad_type (not a string/int/uint)
172 {
173 Json::Value j;
174 j[sfLedgerEntryType] = Json::Value(Json::objectValue);
175 STParsedJSONObject obj("Test", j);
176 BEAST_EXPECT(!obj.object.has_value());
177 }
178
179 // Invalid input for other field
180 {
181 Json::Value j;
182 j[sfTransferFee] = "Payment";
183 STParsedJSONObject obj("Test", j);
184 BEAST_EXPECT(!obj.object.has_value());
185 }
186 }
187
188 void
190 {
191 testcase("UInt32");
192 {
193 Json::Value j;
194 j[sfNetworkID] = 4294967295u;
195 STParsedJSONObject obj("Test", j);
196 BEAST_EXPECT(obj.object.has_value());
197 BEAST_EXPECT(obj.object->isFieldPresent(sfNetworkID));
198 BEAST_EXPECT(obj.object->getFieldU32(sfNetworkID) == 4294967295u);
199 }
200
201 // Test with string value
202 {
203 Json::Value j;
204 j[sfNetworkID] = "4294967295";
205 STParsedJSONObject obj("Test", j);
206 BEAST_EXPECT(obj.object.has_value());
207 BEAST_EXPECT(obj.object->isFieldPresent(sfNetworkID));
208 BEAST_EXPECT(obj.object->getFieldU32(sfNetworkID) == 4294967295u);
209 }
210
211 // Test min value for uint32
212 {
213 Json::Value j;
214 j[sfNetworkID] = 0;
215 STParsedJSONObject obj("Test", j);
216 BEAST_EXPECT(obj.object.has_value());
217 BEAST_EXPECT(obj.object->getFieldU32(sfNetworkID) == 0);
218 }
219
220 // Test out of range value for uint32 (negative)
221 {
222 Json::Value j;
223 j[sfNetworkID] = -1;
224 STParsedJSONObject obj("Test", j);
225 BEAST_EXPECT(!obj.object.has_value());
226 }
227
228 // Test string value out of range
229 {
230 Json::Value j;
231 j[sfNetworkID] = "4294967296";
232 STParsedJSONObject obj("Test", j);
233 BEAST_EXPECT(!obj.object.has_value());
234 }
235
236 // Test bad_type (arrayValue)
237 {
238 Json::Value j;
239 j[sfNetworkID] = Json::Value(Json::arrayValue);
240 STParsedJSONObject obj("Test", j);
241 BEAST_EXPECT(!obj.object.has_value());
242 }
243
244 // Test bad_type (objectValue)
245 {
246 Json::Value j;
247 j[sfNetworkID] = Json::Value(Json::objectValue);
248 STParsedJSONObject obj("Test", j);
249 BEAST_EXPECT(!obj.object.has_value());
250 }
251 }
252
253 void
255 {
256 testcase("UInt64");
257 {
258 Json::Value j;
259 j[sfIndexNext] = "ffffffffffffffff";
260 STParsedJSONObject obj("Test", j);
261 BEAST_EXPECT(obj.object.has_value());
262 BEAST_EXPECT(obj.object->isFieldPresent(sfIndexNext));
263 BEAST_EXPECT(
264 obj.object->getFieldU64(sfIndexNext) ==
265 18446744073709551615ull);
266 }
267
268 // Test min value for uint64
269 {
270 Json::Value j;
271 j[sfIndexNext] = 0;
272 STParsedJSONObject obj("Test", j);
273 BEAST_EXPECT(obj.object.has_value());
274 BEAST_EXPECT(obj.object->getFieldU64(sfIndexNext) == 0ull);
275 }
276
277 // Test out of range value for uint64 (negative)
278 {
279 Json::Value j;
280 j[sfIndexNext] = -1;
281 STParsedJSONObject obj("Test", j);
282 BEAST_EXPECT(!obj.object.has_value());
283 }
284
285 // NOTE: the JSON parser doesn't support > UInt32, so those values must
286 // be in hex
287 // Test string value out of range
288 // string is interpreted as hex
289 {
290 Json::Value j;
291 j[sfIndexNext] = "10000000000000000"; // uint64 max + 1 (in hex)
292 STParsedJSONObject obj("Test", j);
293 BEAST_EXPECT(!obj.object.has_value());
294 }
295
296 // Test hex string value with 0x prefix (should fail)
297 {
298 Json::Value j;
299 j[sfIndexNext] = "0xabcdefabcdef";
300 STParsedJSONObject obj("Test", j);
301 BEAST_EXPECT(!obj.object.has_value());
302 }
303
304 // Test hex string value with invalid characters
305 {
306 Json::Value j;
307 j[sfIndexNext] = "abcdefga";
308 STParsedJSONObject obj("Test", j);
309 BEAST_EXPECT(!obj.object.has_value());
310 }
311
312 // test arrayValue
313 {
314 Json::Value j;
315 j[sfIndexNext] = Json::Value(Json::arrayValue);
316 STParsedJSONObject obj("Test", j);
317 BEAST_EXPECT(!obj.object.has_value());
318 }
319
320 // test objectValue
321 {
322 Json::Value j;
323 j[sfIndexNext] = Json::Value(Json::objectValue);
324 STParsedJSONObject obj("Test", j);
325 BEAST_EXPECT(!obj.object.has_value());
326 }
327 }
328
329 void
331 {
332 testcase("UInt128");
333 {
334 Json::Value j;
335 j[sfEmailHash] = "0123456789ABCDEF0123456789ABCDEF";
336 STParsedJSONObject obj("Test", j);
337 BEAST_EXPECT(obj.object.has_value());
338 BEAST_EXPECT(obj.object->isFieldPresent(sfEmailHash));
339 BEAST_EXPECT(obj.object->getFieldH128(sfEmailHash).size() == 16);
340 std::array<uint8_t, 16> expected = {
341 0x01,
342 0x23,
343 0x45,
344 0x67,
345 0x89,
346 0xAB,
347 0xCD,
348 0xEF,
349 0x01,
350 0x23,
351 0x45,
352 0x67,
353 0x89,
354 0xAB,
355 0xCD,
356 0xEF};
357 BEAST_EXPECT(
358 obj.object->getFieldH128(sfEmailHash) == uint128{expected});
359 }
360
361 // Valid lowercase hex string for UInt128
362 {
363 Json::Value j;
364 j[sfEmailHash] = "0123456789abcdef0123456789abcdef";
365 STParsedJSONObject obj("Test", j);
366 BEAST_EXPECT(obj.object.has_value());
367 BEAST_EXPECT(obj.object->isFieldPresent(sfEmailHash));
368 BEAST_EXPECT(obj.object->getFieldH128(sfEmailHash).size() == 16);
369 }
370
371 // Empty string for UInt128 (should be valid, all zero)
372 {
373 Json::Value j;
374 j[sfEmailHash] = "";
375 STParsedJSONObject obj("Test", j);
376 BEAST_EXPECT(obj.object.has_value());
377 BEAST_EXPECT(obj.object->isFieldPresent(sfEmailHash));
378 auto const& h128 = obj.object->getFieldH128(sfEmailHash);
379 BEAST_EXPECT(h128.size() == 16);
380 bool allZero = std::all_of(
381 h128.begin(), h128.end(), [](auto b) { return b == 0; });
382 BEAST_EXPECT(allZero);
383 }
384
385 // Odd-length hex string for UInt128 (should fail)
386 {
387 Json::Value j;
388 j[sfEmailHash] = "0123456789ABCDEF0123456789ABCDE";
389 STParsedJSONObject obj("Test", j);
390 BEAST_EXPECT(!obj.object.has_value());
391 }
392
393 // Non-hex string for UInt128 (should fail)
394 {
395 Json::Value j;
396 j[sfEmailHash] = "nothexstring";
397 STParsedJSONObject obj("Test", j);
398 BEAST_EXPECT(!obj.object.has_value());
399 }
400
401 // Hex string too short for UInt128 (should fail)
402 {
403 Json::Value j;
404 j[sfEmailHash] = "01234567";
405 STParsedJSONObject obj("Test", j);
406 BEAST_EXPECT(!obj.object.has_value());
407 }
408
409 // Hex string too long for UInt128 (should fail)
410 {
411 Json::Value j;
412 j[sfEmailHash] = "0123456789ABCDEF0123456789ABCDEF00";
413 STParsedJSONObject obj("Test", j);
414 BEAST_EXPECT(!obj.object.has_value());
415 }
416
417 // Array value for UInt128 (should fail)
418 {
419 Json::Value j;
420 j[sfEmailHash] = Json::Value(Json::arrayValue);
421 STParsedJSONObject obj("Test", j);
422 BEAST_EXPECT(!obj.object.has_value());
423 }
424
425 // Object value for UInt128 (should fail)
426 {
427 Json::Value j;
428 j[sfEmailHash] = Json::Value(Json::objectValue);
429 STParsedJSONObject obj("Test", j);
430 BEAST_EXPECT(!obj.object.has_value());
431 }
432 }
433
434 void
436 {
437 testcase("UInt160");
438 {
439 Json::Value j;
440 j[sfTakerPaysCurrency] = "0123456789ABCDEF0123456789ABCDEF01234567";
441 STParsedJSONObject obj("Test", j);
442 BEAST_EXPECT(obj.object.has_value());
443 BEAST_EXPECT(obj.object->isFieldPresent(sfTakerPaysCurrency));
444 BEAST_EXPECT(
445 obj.object->getFieldH160(sfTakerPaysCurrency).size() == 20);
446 std::array<uint8_t, 20> expected = {
447 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23,
448 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67};
449 BEAST_EXPECT(
450 obj.object->getFieldH160(sfTakerPaysCurrency) ==
451 uint160{expected});
452 }
453 // Valid lowercase hex string for UInt160
454 {
455 Json::Value j;
456 j[sfTakerPaysCurrency] = "0123456789abcdef0123456789abcdef01234567";
457 STParsedJSONObject obj("Test", j);
458 BEAST_EXPECT(obj.object.has_value());
459 BEAST_EXPECT(obj.object->isFieldPresent(sfTakerPaysCurrency));
460 BEAST_EXPECT(
461 obj.object->getFieldH160(sfTakerPaysCurrency).size() == 20);
462 }
463
464 // Empty string for UInt160 (should be valid, all zero)
465 {
466 Json::Value j;
467 j[sfTakerPaysCurrency] = "";
468 STParsedJSONObject obj("Test", j);
469 BEAST_EXPECT(obj.object.has_value());
470 BEAST_EXPECT(obj.object->isFieldPresent(sfTakerPaysCurrency));
471 auto const& h160 = obj.object->getFieldH160(sfTakerPaysCurrency);
472 BEAST_EXPECT(h160.size() == 20);
473 bool allZero = std::all_of(
474 h160.begin(), h160.end(), [](auto b) { return b == 0; });
475 BEAST_EXPECT(allZero);
476 }
477
478 // Non-hex string for UInt160 (should fail)
479 {
480 Json::Value j;
481 j[sfTakerPaysCurrency] = "nothexstring";
482 STParsedJSONObject obj("Test", j);
483 BEAST_EXPECT(!obj.object.has_value());
484 }
485
486 // Hex string too short for UInt160 (should fail)
487 {
488 Json::Value j;
489 j[sfTakerPaysCurrency] = "01234567";
490 STParsedJSONObject obj("Test", j);
491 BEAST_EXPECT(!obj.object.has_value());
492 }
493
494 // Hex string too long for UInt160 (should fail)
495 {
496 Json::Value j;
497 j[sfTakerPaysCurrency] =
498 "0123456789ABCDEF0123456789ABCDEF0123456789";
499 STParsedJSONObject obj("Test", j);
500 BEAST_EXPECT(!obj.object.has_value());
501 }
502
503 // Array value for UInt160 (should fail)
504 {
505 Json::Value j;
506 j[sfTakerPaysCurrency] = Json::Value(Json::arrayValue);
507 STParsedJSONObject obj("Test", j);
508 BEAST_EXPECT(!obj.object.has_value());
509 }
510
511 // Object value for UInt160 (should fail)
512 {
513 Json::Value j;
514 j[sfTakerPaysCurrency] = Json::Value(Json::objectValue);
515 STParsedJSONObject obj("Test", j);
516 BEAST_EXPECT(!obj.object.has_value());
517 }
518 }
519
520 void
522 {
523 testcase("UInt192");
524 {
525 Json::Value j;
526 j[sfMPTokenIssuanceID] =
527 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
528 STParsedJSONObject obj("Test", j);
529 BEAST_EXPECT(obj.object.has_value());
530 BEAST_EXPECT(obj.object->isFieldPresent(sfMPTokenIssuanceID));
531 BEAST_EXPECT(
532 obj.object->getFieldH192(sfMPTokenIssuanceID).size() == 24);
533 std::array<uint8_t, 24> expected = {
534 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
535 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
536 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
537 BEAST_EXPECT(
538 obj.object->getFieldH192(sfMPTokenIssuanceID) ==
539 uint192{expected});
540 }
541
542 // Valid lowercase hex string for UInt192
543 {
544 Json::Value j;
545 j[sfMPTokenIssuanceID] =
546 "ffffffffffffffffffffffffffffffffffffffffffffffff";
547 STParsedJSONObject obj("Test", j);
548 BEAST_EXPECT(obj.object.has_value());
549 BEAST_EXPECT(obj.object->isFieldPresent(sfMPTokenIssuanceID));
550 BEAST_EXPECT(
551 obj.object->getFieldH192(sfMPTokenIssuanceID).size() == 24);
552 }
553
554 // Empty string for UInt192 (should be valid, all zero)
555 {
556 Json::Value j;
557 j[sfMPTokenIssuanceID] = "";
558 STParsedJSONObject obj("Test", j);
559 BEAST_EXPECT(obj.object.has_value());
560 BEAST_EXPECT(obj.object->isFieldPresent(sfMPTokenIssuanceID));
561 auto const& h192 = obj.object->getFieldH192(sfMPTokenIssuanceID);
562 BEAST_EXPECT(h192.size() == 24);
563 bool allZero = std::all_of(
564 h192.begin(), h192.end(), [](auto b) { return b == 0; });
565 BEAST_EXPECT(allZero);
566 }
567
568 // Odd-length hex string for UInt192 (should fail)
569 {
570 Json::Value j;
571 j[sfMPTokenIssuanceID] =
572 "0123456789ABCDEF0123456789ABCDEF0123456789ABCDE";
573 STParsedJSONObject obj("Test", j);
574 BEAST_EXPECT(!obj.object.has_value());
575 }
576
577 // Non-hex string for UInt192 (should fail)
578 {
579 Json::Value j;
580 j[sfMPTokenIssuanceID] = "nothexstring";
581 STParsedJSONObject obj("Test", j);
582 BEAST_EXPECT(!obj.object.has_value());
583 }
584
585 // Hex string too short for UInt192 (should fail)
586 {
587 Json::Value j;
588 j[sfMPTokenIssuanceID] = "01234567";
589 STParsedJSONObject obj("Test", j);
590 BEAST_EXPECT(!obj.object.has_value());
591 }
592
593 // Hex string too long for UInt192 (should fail)
594 {
595 Json::Value j;
596 j[sfMPTokenIssuanceID] =
597 "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF00";
598 STParsedJSONObject obj("Test", j);
599 BEAST_EXPECT(!obj.object.has_value());
600 }
601
602 // Array value for UInt192 (should fail)
603 {
604 Json::Value j;
605 j[sfMPTokenIssuanceID] = Json::Value(Json::arrayValue);
606 STParsedJSONObject obj("Test", j);
607 BEAST_EXPECT(!obj.object.has_value());
608 }
609
610 // Object value for UInt192 (should fail)
611 {
612 Json::Value j;
613 j[sfMPTokenIssuanceID] = Json::Value(Json::objectValue);
614 STParsedJSONObject obj("Test", j);
615 BEAST_EXPECT(!obj.object.has_value());
616 }
617 }
618
619 void
621 {
622 testcase("UInt256");
623 // Test with valid hex string for UInt256
624 {
625 Json::Value j;
626 j[sfLedgerHash] =
627 "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCD"
628 "EF";
629 STParsedJSONObject obj("Test", j);
630 BEAST_EXPECT(obj.object.has_value());
631 BEAST_EXPECT(obj.object->isFieldPresent(sfLedgerHash));
632 BEAST_EXPECT(obj.object->getFieldH256(sfLedgerHash).size() == 32);
633 std::array<uint8_t, 32> expected = {
634 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
635 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
636 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
637 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
638 BEAST_EXPECT(
639 obj.object->getFieldH256(sfLedgerHash) == uint256{expected});
640 }
641 // Valid lowercase hex string for UInt256
642 {
643 Json::Value j;
644 j[sfLedgerHash] =
645 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd"
646 "ef";
647 STParsedJSONObject obj("Test", j);
648 BEAST_EXPECT(obj.object.has_value());
649 BEAST_EXPECT(obj.object->isFieldPresent(sfLedgerHash));
650 BEAST_EXPECT(obj.object->getFieldH256(sfLedgerHash).size() == 32);
651 }
652
653 // Empty string for UInt256 (should be valid, all zero)
654 {
655 Json::Value j;
656 j[sfLedgerHash] = "";
657 STParsedJSONObject obj("Test", j);
658 BEAST_EXPECT(obj.object.has_value());
659 BEAST_EXPECT(obj.object->isFieldPresent(sfLedgerHash));
660 auto const& h256 = obj.object->getFieldH256(sfLedgerHash);
661 BEAST_EXPECT(h256.size() == 32);
662 bool allZero = std::all_of(
663 h256.begin(), h256.end(), [](auto b) { return b == 0; });
664 BEAST_EXPECT(allZero);
665 }
666
667 // Odd-length hex string for UInt256 (should fail)
668 {
669 Json::Value j;
670 j[sfLedgerHash] =
671 "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCD"
672 "E";
673 STParsedJSONObject obj("Test", j);
674 BEAST_EXPECT(!obj.object.has_value());
675 }
676
677 // Non-hex string for UInt256 (should fail)
678 {
679 Json::Value j;
680 j[sfLedgerHash] = "nothexstring";
681 STParsedJSONObject obj("Test", j);
682 BEAST_EXPECT(!obj.object.has_value());
683 }
684
685 // Hex string too short for UInt256 (should fail)
686 {
687 Json::Value j;
688 j[sfLedgerHash] = "01234567";
689 STParsedJSONObject obj("Test", j);
690 BEAST_EXPECT(!obj.object.has_value());
691 }
692
693 // Hex string too long for UInt256 (should fail)
694 {
695 Json::Value j;
696 j[sfLedgerHash] =
697 "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCD"
698 "EF00";
699 STParsedJSONObject obj("Test", j);
700 BEAST_EXPECT(!obj.object.has_value());
701 }
702
703 // Array value for UInt256 (should fail)
704 {
705 Json::Value j;
706 j[sfLedgerHash] = Json::Value(Json::arrayValue);
707 STParsedJSONObject obj("Test", j);
708 BEAST_EXPECT(!obj.object.has_value());
709 }
710
711 // Object value for UInt256 (should fail)
712 {
713 Json::Value j;
714 j[sfLedgerHash] = Json::Value(Json::objectValue);
715 STParsedJSONObject obj("Test", j);
716 BEAST_EXPECT(!obj.object.has_value());
717 }
718 }
719
720 void
722 {
723 testcase("Int32");
724 {
725 Json::Value j;
726 int const minInt32 = -2147483648;
727 j[sfDummyInt32] = minInt32;
728 STParsedJSONObject obj("Test", j);
729 BEAST_EXPECT(obj.object.has_value());
730 if (BEAST_EXPECT(obj.object->isFieldPresent(sfDummyInt32)))
731 BEAST_EXPECT(obj.object->getFieldI32(sfDummyInt32) == minInt32);
732 }
733
734 // max value
735 {
736 Json::Value j;
737 int const maxInt32 = 2147483647;
738 j[sfDummyInt32] = maxInt32;
739 STParsedJSONObject obj("Test", j);
740 BEAST_EXPECT(obj.object.has_value());
741 if (BEAST_EXPECT(obj.object->isFieldPresent(sfDummyInt32)))
742 BEAST_EXPECT(obj.object->getFieldI32(sfDummyInt32) == maxInt32);
743 }
744
745 // max uint value
746 {
747 Json::Value j;
748 unsigned int const maxUInt32 = 2147483647u;
749 j[sfDummyInt32] = maxUInt32;
750 STParsedJSONObject obj("Test", j);
751 BEAST_EXPECT(obj.object.has_value());
752 if (BEAST_EXPECT(obj.object->isFieldPresent(sfDummyInt32)))
753 BEAST_EXPECT(
754 obj.object->getFieldI32(sfDummyInt32) ==
755 static_cast<int32_t>(maxUInt32));
756 }
757
758 // Test with string value
759 {
760 Json::Value j;
761 j[sfDummyInt32] = "2147483647";
762 STParsedJSONObject obj("Test", j);
763 BEAST_EXPECT(obj.object.has_value());
764 if (BEAST_EXPECT(obj.object->isFieldPresent(sfDummyInt32)))
765 BEAST_EXPECT(
766 obj.object->getFieldI32(sfDummyInt32) == 2147483647u);
767 }
768
769 // Test with string negative value
770 {
771 Json::Value j;
772 int value = -2147483648;
773 j[sfDummyInt32] = std::to_string(value);
774 STParsedJSONObject obj("Test", j);
775 BEAST_EXPECT(obj.object.has_value());
776 if (BEAST_EXPECT(obj.object->isFieldPresent(sfDummyInt32)))
777 BEAST_EXPECT(obj.object->getFieldI32(sfDummyInt32) == value);
778 }
779
780 // Test out of range value for int32 (negative)
781 {
782 Json::Value j;
783 j[sfDummyInt32] = "-2147483649";
784 STParsedJSONObject obj("Test", j);
785 BEAST_EXPECT(!obj.object.has_value());
786 }
787
788 // Test out of range value for int32 (positive)
789 {
790 Json::Value j;
791 j[sfDummyInt32] = 2147483648u;
792 STParsedJSONObject obj("Test", j);
793 BEAST_EXPECT(!obj.object.has_value());
794 }
795
796 // Test string value out of range
797 {
798 Json::Value j;
799 j[sfDummyInt32] = "2147483648";
800 STParsedJSONObject obj("Test", j);
801 BEAST_EXPECT(!obj.object.has_value());
802 }
803
804 // Test bad_type (arrayValue)
805 {
806 Json::Value j;
807 j[sfDummyInt32] = Json::Value(Json::arrayValue);
808 STParsedJSONObject obj("Test", j);
809 BEAST_EXPECT(!obj.object.has_value());
810 }
811
812 // Test bad_type (objectValue)
813 {
814 Json::Value j;
815 j[sfDummyInt32] = Json::Value(Json::objectValue);
816 STParsedJSONObject obj("Test", j);
817 BEAST_EXPECT(!obj.object.has_value());
818 }
819 }
820
821 void
823 {
824 testcase("Blob");
825 // Test with valid hex string for blob
826 {
827 Json::Value j;
828 j[sfPublicKey] = "DEADBEEF";
829 STParsedJSONObject obj("Test", j);
830 BEAST_EXPECT(obj.object.has_value());
831 BEAST_EXPECT(obj.object->isFieldPresent(sfPublicKey));
832 auto const& blob = obj.object->getFieldVL(sfPublicKey);
833 BEAST_EXPECT(blob.size() == 4);
834 BEAST_EXPECT(blob[0] == 0xDE);
835 BEAST_EXPECT(blob[1] == 0xAD);
836 BEAST_EXPECT(blob[2] == 0xBE);
837 BEAST_EXPECT(blob[3] == 0xEF);
838 }
839
840 // Test empty string for blob (should be valid, size 0)
841 {
842 Json::Value j;
843 j[sfPublicKey] = "";
844 STParsedJSONObject obj("Test", j);
845 BEAST_EXPECT(obj.object.has_value());
846 BEAST_EXPECT(obj.object->isFieldPresent(sfPublicKey));
847 auto const& blob = obj.object->getFieldVL(sfPublicKey);
848 BEAST_EXPECT(blob.size() == 0);
849 }
850
851 // Test lowercase hex string for blob
852 {
853 Json::Value j;
854 j[sfPublicKey] = "deadbeef";
855 STParsedJSONObject obj("Test", j);
856 BEAST_EXPECT(obj.object.has_value());
857 BEAST_EXPECT(obj.object->isFieldPresent(sfPublicKey));
858 auto const& blob = obj.object->getFieldVL(sfPublicKey);
859 BEAST_EXPECT(blob.size() == 4);
860 BEAST_EXPECT(blob[0] == 0xDE);
861 BEAST_EXPECT(blob[1] == 0xAD);
862 BEAST_EXPECT(blob[2] == 0xBE);
863 BEAST_EXPECT(blob[3] == 0xEF);
864 }
865
866 // Test non-hex string for blob (should fail)
867 {
868 Json::Value j;
869 j[sfPublicKey] = "XYZ123";
870 STParsedJSONObject obj("Test", j);
871 BEAST_EXPECT(!obj.object.has_value());
872 }
873
874 // Test array value for blob (should fail)
875 {
876 Json::Value j;
877 j[sfPublicKey] = Json::Value(Json::arrayValue);
878 STParsedJSONObject obj("Test", j);
879 BEAST_EXPECT(!obj.object.has_value());
880 }
881
882 // Test object value for blob (should fail)
883 {
884 Json::Value j;
885 j[sfPublicKey] = Json::Value(Json::objectValue);
886 STParsedJSONObject obj("Test", j);
887 BEAST_EXPECT(!obj.object.has_value());
888 }
889 }
890
891 void
893 {
894 testcase("Vector256");
895 // Test with valid array of hex strings for Vector256
896 {
897 Json::Value j;
899 arr.append(
900 "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCD"
901 "EF");
902 arr.append(
903 "FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA98765432"
904 "10");
905 j[sfHashes] = arr;
906 STParsedJSONObject obj("Test", j);
907 BEAST_EXPECT(obj.object.has_value());
908 BEAST_EXPECT(obj.object->isFieldPresent(sfHashes));
909 auto const& vec = obj.object->getFieldV256(sfHashes);
910 BEAST_EXPECT(vec.size() == 2);
911 BEAST_EXPECT(to_string(vec[0]) == arr[0u].asString());
912 BEAST_EXPECT(to_string(vec[1]) == arr[1u].asString());
913 }
914 // Test empty array for Vector256 (should be valid, size 0)
915 {
916 Json::Value j;
918 j[sfHashes] = arr;
919 STParsedJSONObject obj("Test", j);
920 BEAST_EXPECT(obj.object.has_value());
921 BEAST_EXPECT(obj.object->isFieldPresent(sfHashes));
922 auto const& vec = obj.object->getFieldV256(sfHashes);
923 BEAST_EXPECT(vec.size() == 0);
924 }
925
926 // Test array with invalid hex string (should fail)
927 {
928 Json::Value j;
930 arr.append("nothexstring");
931 j[sfHashes] = arr;
932 STParsedJSONObject obj("Test", j);
933 BEAST_EXPECT(!obj.object.has_value());
934 }
935
936 // Test array with string of wrong length (should fail)
937 {
938 Json::Value j;
940 arr.append("0123456789ABCDEF"); // too short for uint256
941 j[sfHashes] = arr;
942 STParsedJSONObject obj("Test", j);
943 BEAST_EXPECT(!obj.object.has_value());
944 }
945
946 // Test array with non-string element (should fail)
947 {
948 Json::Value j;
950 arr.append(12345);
951 j[sfHashes] = arr;
952 STParsedJSONObject obj("Test", j);
953 BEAST_EXPECT(!obj.object.has_value());
954 }
955
956 // Test non-array value for Vector256 (should fail)
957 {
958 Json::Value j;
959 j[sfHashes] = "notanarray";
960 STParsedJSONObject obj("Test", j);
961 BEAST_EXPECT(!obj.object.has_value());
962 }
963
964 // Test array with object element (should fail)
965 {
966 Json::Value j;
969 objElem["foo"] = "bar";
970 arr.append(objElem);
971 j[sfHashes] = arr;
972 STParsedJSONObject obj("Test", j);
973 BEAST_EXPECT(!obj.object.has_value());
974 }
975 }
976
977 void
979 {
980 testcase("Account");
981 // Test with valid base58 string for AccountID
982 {
983 Json::Value j;
984 j[sfAccount] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
985 STParsedJSONObject obj("Test", j);
986 BEAST_EXPECT(obj.object.has_value());
987 BEAST_EXPECT(obj.object->isFieldPresent(sfAccount));
988 auto const& acct = obj.object->getAccountID(sfAccount);
989 BEAST_EXPECT(acct.size() == 20);
990 BEAST_EXPECT(
991 toBase58(acct) == "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh");
992 }
993
994 // Valid hex string for AccountID
995 {
996 Json::Value j;
997 j[sfAccount] = "000102030405060708090A0B0C0D0E0F10111213";
998 STParsedJSONObject obj("Test", j);
999 BEAST_EXPECT(obj.object.has_value());
1000 BEAST_EXPECT(obj.object->isFieldPresent(sfAccount));
1001 auto const& acct = obj.object->getAccountID(sfAccount);
1002 BEAST_EXPECT(acct.size() == 20);
1003 }
1004
1005 // Invalid base58 string for AccountID
1006 {
1007 Json::Value j;
1008 j[sfAccount] = "notAValidBase58Account";
1009 STParsedJSONObject obj("Test", j);
1010 BEAST_EXPECT(!obj.object.has_value());
1011 }
1012
1013 // Invalid hex string for AccountID (too short)
1014 {
1015 Json::Value j;
1016 j[sfAccount] = "001122334455";
1017 STParsedJSONObject obj("Test", j);
1018 BEAST_EXPECT(!obj.object.has_value());
1019 }
1020
1021 // Invalid hex string for AccountID (too long)
1022 {
1023 Json::Value j;
1024 j[sfAccount] = "000102030405060708090A0B0C0D0E0F101112131415";
1025 STParsedJSONObject obj("Test", j);
1026 BEAST_EXPECT(!obj.object.has_value());
1027 }
1028
1029 // Invalid hex string for AccountID (bad chars)
1030 {
1031 Json::Value j;
1032 j[sfAccount] = "000102030405060708090A0B0C0D0E0F1011121G";
1033 STParsedJSONObject obj("Test", j);
1034 BEAST_EXPECT(!obj.object.has_value());
1035 }
1036
1037 // Empty string for AccountID (should fail)
1038 {
1039 Json::Value j;
1040 j[sfAccount] = "";
1041 STParsedJSONObject obj("Test", j);
1042 BEAST_EXPECT(!obj.object.has_value());
1043 }
1044
1045 // Array value for AccountID (should fail)
1046 {
1047 Json::Value j;
1048 j[sfAccount] = Json::Value(Json::arrayValue);
1049 STParsedJSONObject obj("Test", j);
1050 BEAST_EXPECT(!obj.object.has_value());
1051 }
1052
1053 // Object value for AccountID (should fail)
1054 {
1055 Json::Value j;
1056 j[sfAccount] = Json::Value(Json::objectValue);
1057 STParsedJSONObject obj("Test", j);
1058 BEAST_EXPECT(!obj.object.has_value());
1059 }
1060 }
1061
1062 void
1064 {
1065 testcase("Currency");
1066 // Test with valid ISO code for currency
1067 {
1068 Json::Value j;
1069 j[sfBaseAsset] = "USD";
1070 STParsedJSONObject obj("Test", j);
1071 BEAST_EXPECT(obj.object.has_value());
1072 BEAST_EXPECT(obj.object->isFieldPresent(sfBaseAsset));
1073 auto const& curr = obj.object->getFieldCurrency(sfBaseAsset);
1074 BEAST_EXPECT(curr.currency().size() == 20);
1075 }
1076
1077 // Valid ISO code
1078 {
1079 Json::Value j;
1080 j[sfBaseAsset] = "EUR";
1081 STParsedJSONObject obj("Test", j);
1082 BEAST_EXPECT(obj.object.has_value());
1083 BEAST_EXPECT(obj.object->isFieldPresent(sfBaseAsset));
1084 auto const& curr = obj.object->getFieldCurrency(sfBaseAsset);
1085 BEAST_EXPECT(curr.currency().size() == 20);
1086 }
1087
1088 // Valid hex string for currency
1089 {
1090 Json::Value j;
1091 j[sfBaseAsset] = "0123456789ABCDEF01230123456789ABCDEF0123";
1092 STParsedJSONObject obj("Test", j);
1093 if (BEAST_EXPECT(obj.object.has_value()))
1094 {
1095 BEAST_EXPECT(obj.object->isFieldPresent(sfBaseAsset));
1096 auto const& curr = obj.object->getFieldCurrency(sfBaseAsset);
1097 BEAST_EXPECT(curr.currency().size() == 20);
1098 }
1099 }
1100
1101 // Invalid ISO code (too long)
1102 {
1103 Json::Value j;
1104 j[sfBaseAsset] = "USDD";
1105 STParsedJSONObject obj("Test", j);
1106 BEAST_EXPECT(!obj.object.has_value());
1107 }
1108
1109 // lowercase ISO code
1110 {
1111 Json::Value j;
1112 j[sfBaseAsset] = "usd";
1113 STParsedJSONObject obj("Test", j);
1114 BEAST_EXPECT(obj.object.has_value());
1115 BEAST_EXPECT(obj.object->isFieldPresent(sfBaseAsset));
1116 auto const& curr = obj.object->getFieldCurrency(sfBaseAsset);
1117 BEAST_EXPECT(curr.currency().size() == 20);
1118 }
1119
1120 // Invalid hex string (too short)
1121 {
1122 Json::Value j;
1123 j[sfBaseAsset] = "0123456789AB";
1124 STParsedJSONObject obj("Test", j);
1125 BEAST_EXPECT(!obj.object.has_value());
1126 }
1127
1128 // Invalid hex string (too long)
1129 {
1130 Json::Value j;
1131 j[sfBaseAsset] = "0123456789ABCDEF0123456789";
1132 STParsedJSONObject obj("Test", j);
1133 BEAST_EXPECT(!obj.object.has_value());
1134 }
1135
1136 // Empty string for currency (should fail)
1137 {
1138 Json::Value j;
1139 j[sfBaseAsset] = "";
1140 STParsedJSONObject obj("Test", j);
1141 BEAST_EXPECT(obj.object.has_value());
1142 BEAST_EXPECT(obj.object->isFieldPresent(sfBaseAsset));
1143 auto const& curr = obj.object->getFieldCurrency(sfBaseAsset);
1144 BEAST_EXPECT(curr.currency().size() == 20);
1145 }
1146
1147 // Array value for currency (should fail)
1148 {
1149 Json::Value j;
1150 j[sfBaseAsset] = Json::Value(Json::arrayValue);
1151 STParsedJSONObject obj("Test", j);
1152 BEAST_EXPECT(!obj.object.has_value());
1153 }
1154
1155 // Object value for currency (should fail)
1156 {
1157 Json::Value j;
1158 j[sfBaseAsset] = Json::Value(Json::objectValue);
1159 STParsedJSONObject obj("Test", j);
1160 BEAST_EXPECT(!obj.object.has_value());
1161 }
1162 }
1163
1164 void
1166 {
1167 testcase("Amount");
1168 // Test with string value for Amount
1169 {
1170 Json::Value j;
1171 j[sfAmount] = "100000000000000000";
1172 STParsedJSONObject obj("Test", j);
1173 BEAST_EXPECT(obj.object.has_value());
1174 BEAST_EXPECT(obj.object->isFieldPresent(sfAmount));
1175 BEAST_EXPECT(
1176 obj.object->getFieldAmount(sfAmount) ==
1177 STAmount(100000000000000000ull));
1178 }
1179
1180 // Test with int value for Amount
1181 {
1182 Json::Value j;
1183 j[sfAmount] = 4294967295u;
1184 STParsedJSONObject obj("Test", j);
1185 BEAST_EXPECT(obj.object.has_value());
1186 BEAST_EXPECT(obj.object->isFieldPresent(sfAmount));
1187 BEAST_EXPECT(
1188 obj.object->getFieldAmount(sfAmount) == STAmount(4294967295u));
1189 }
1190
1191 // Test with decimal string for Amount (should fail)
1192 {
1193 Json::Value j;
1194 j[sfAmount] = "123.45";
1195 STParsedJSONObject obj("Test", j);
1196 BEAST_EXPECT(!obj.object.has_value());
1197 }
1198
1199 // Test with empty string for Amount (should fail)
1200 {
1201 Json::Value j;
1202 j[sfAmount] = "";
1203 STParsedJSONObject obj("Test", j);
1204 BEAST_EXPECT(!obj.object.has_value());
1205 }
1206
1207 // Test with non-numeric string for Amount (should fail)
1208 {
1209 Json::Value j;
1210 j[sfAmount] = "notanumber";
1211 STParsedJSONObject obj("Test", j);
1212 BEAST_EXPECT(!obj.object.has_value());
1213 }
1214
1215 // Test with object value for Amount (should fail)
1216 {
1217 Json::Value j;
1218 j[sfAmount] = Json::Value(Json::objectValue);
1219 STParsedJSONObject obj("Test", j);
1220 BEAST_EXPECT(!obj.object.has_value());
1221 }
1222 }
1223
1224 void
1226 {
1227 testcase("PathSet");
1228 // Valid test: single path with single element
1229 {
1230 Json::Value j;
1233 elem["account"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1234 elem["currency"] = "USD";
1235 elem["issuer"] = "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe";
1236 path.append(elem);
1238 pathset.append(path);
1239 j[sfPaths] = pathset;
1240 STParsedJSONObject obj("Test", j);
1241 if (BEAST_EXPECT(obj.object.has_value()))
1242 {
1243 BEAST_EXPECT(obj.object->isFieldPresent(sfPaths));
1244 auto const& ps = obj.object->getFieldPathSet(sfPaths);
1245 BEAST_EXPECT(!ps.empty());
1246 BEAST_EXPECT(ps.size() == 1);
1247 BEAST_EXPECT(ps[0].size() == 1);
1248 BEAST_EXPECT(
1249 ps[0][0].getAccountID() ==
1250 parseBase58<AccountID>(
1251 "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"));
1252 BEAST_EXPECT(to_string(ps[0][0].getCurrency()) == "USD");
1253 BEAST_EXPECT(
1254 ps[0][0].getIssuerID() ==
1255 parseBase58<AccountID>(
1256 "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe"));
1257 }
1258 }
1259
1260 // Valid test: non-standard currency code
1261 {
1262 Json::Value j;
1265 elem["account"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1266 elem["currency"] = "0123456789ABCDEF01230123456789ABCDEF0123";
1267 elem["issuer"] = "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe";
1268 path.append(elem);
1270 pathset.append(path);
1271 j[sfPaths] = pathset;
1272 STParsedJSONObject obj("Test", j);
1273 BEAST_EXPECT(obj.object.has_value());
1274 BEAST_EXPECT(obj.object->isFieldPresent(sfPaths));
1275 auto const& ps = obj.object->getFieldPathSet(sfPaths);
1276 BEAST_EXPECT(!ps.empty());
1277 }
1278
1279 // Test with non-array value for PathSet (should fail)
1280 {
1281 Json::Value j;
1282 j[sfPaths] = "notanarray";
1283 STParsedJSONObject obj("Test", j);
1284 BEAST_EXPECT(!obj.object.has_value());
1285 }
1286
1287 // Test with array containing non-array element (should fail)
1288 {
1289 Json::Value j;
1291 pathset.append("notanarray");
1292 j[sfPaths] = pathset;
1293 STParsedJSONObject obj("Test", j);
1294 BEAST_EXPECT(!obj.object.has_value());
1295 }
1296
1297 // Test with array containing array with non-object element (should
1298 // fail)
1299 {
1300 Json::Value j;
1302 path.append("notanobject");
1304 pathset.append(path);
1305 j[sfPaths] = pathset;
1306 STParsedJSONObject obj("Test", j);
1307 BEAST_EXPECT(!obj.object.has_value());
1308 }
1309
1310 // Test with array containing array with object missing required keys
1311 // (should fail)
1312 {
1313 Json::Value j;
1316 elem["foo"] = "bar"; // not a valid path element key
1317 path.append(elem);
1319 pathset.append(path);
1320 j[sfPaths] = pathset;
1321 STParsedJSONObject obj("Test", j);
1322 BEAST_EXPECT(!obj.object.has_value());
1323 }
1324
1325 // Test with array containing array with object with invalid account
1326 // value (should fail)
1327 {
1328 Json::Value j;
1331 elem["account"] = "notAValidBase58Account";
1332 path.append(elem);
1334 pathset.append(path);
1335 j[sfPaths] = pathset;
1336 STParsedJSONObject obj("Test", j);
1337 BEAST_EXPECT(!obj.object.has_value());
1338 }
1339
1340 // Test with account not string (should fail)
1341 {
1342 Json::Value j;
1345 elem["account"] = 12345;
1346 path.append(elem);
1348 pathset.append(path);
1349 j[sfPaths] = pathset;
1350 STParsedJSONObject obj("Test", j);
1351 BEAST_EXPECT(!obj.object.has_value());
1352 }
1353
1354 // Test with currency not string (should fail)
1355 {
1356 Json::Value j;
1359 elem["currency"] = 12345;
1360 path.append(elem);
1362 pathset.append(path);
1363 j[sfPaths] = pathset;
1364 STParsedJSONObject obj("Test", j);
1365 BEAST_EXPECT(!obj.object.has_value());
1366 }
1367
1368 // Test with non-standard currency not hex (should fail)
1369 {
1370 Json::Value j;
1373 elem["currency"] = "notAValidCurrency";
1374 path.append(elem);
1376 pathset.append(path);
1377 j[sfPaths] = pathset;
1378 STParsedJSONObject obj("Test", j);
1379 BEAST_EXPECT(!obj.object.has_value());
1380 }
1381
1382 // Test with issuer not string (should fail)
1383 {
1384 Json::Value j;
1387 elem["issuer"] = 12345;
1388 path.append(elem);
1390 pathset.append(path);
1391 j[sfPaths] = pathset;
1392 STParsedJSONObject obj("Test", j);
1393 BEAST_EXPECT(!obj.object.has_value());
1394 }
1395
1396 // Test with issuer not base58 (should fail)
1397 {
1398 Json::Value j;
1401 elem["issuer"] = "notAValidBase58Account";
1402 path.append(elem);
1404 pathset.append(path);
1405 j[sfPaths] = pathset;
1406 STParsedJSONObject obj("Test", j);
1407 BEAST_EXPECT(!obj.object.has_value());
1408 }
1409 }
1410
1411 void
1413 {
1414 testcase("Issue");
1415 // Valid Issue: currency and issuer as base58
1416 {
1417 Json::Value j;
1418 Json::Value issueJson(Json::objectValue);
1419 issueJson["currency"] = "USD";
1420 issueJson["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1421 j[sfAsset] = issueJson;
1422 STParsedJSONObject obj("Test", j);
1423 if (BEAST_EXPECT(obj.object.has_value()))
1424 {
1425 BEAST_EXPECT(obj.object->isFieldPresent(sfAsset));
1426 auto const& issueField = (*obj.object)[sfAsset];
1427 auto const issue = issueField.value().get<Issue>();
1428 BEAST_EXPECT(issue.currency.size() == 20);
1429 BEAST_EXPECT(to_string(issue.currency) == "USD");
1430 BEAST_EXPECT(issue.account.size() == 20);
1431 BEAST_EXPECT(
1432 issue.account ==
1433 parseBase58<AccountID>(
1434 "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"));
1435 }
1436 }
1437
1438 // Valid Issue: currency as hex
1439 {
1440 Json::Value j;
1441 Json::Value issueJson(Json::objectValue);
1442 issueJson["currency"] = "0123456789ABCDEF01230123456789ABCDEF0123";
1443 issueJson["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1444 j[sfAsset] = issueJson;
1445 STParsedJSONObject obj("Test", j);
1446 if (BEAST_EXPECT(obj.object.has_value()))
1447 {
1448 BEAST_EXPECT(obj.object->isFieldPresent(sfAsset));
1449 auto const& issueField = (*obj.object)[sfAsset];
1450 auto const issue = issueField.value().get<Issue>();
1451 BEAST_EXPECT(issue.currency.size() == 20);
1452 BEAST_EXPECT(issue.account.size() == 20);
1453 }
1454 }
1455
1456 // Valid Issue: MPTID
1457 {
1458 Json::Value j;
1459 Json::Value issueJson(Json::objectValue);
1460 issueJson["mpt_issuance_id"] =
1461 "0000000000000000000000004D5054494431323334234234";
1462 j[sfAsset] = issueJson;
1463 STParsedJSONObject obj("Test", j);
1464 if (BEAST_EXPECT(obj.object.has_value()))
1465 {
1466 BEAST_EXPECT(obj.object->isFieldPresent(sfAsset));
1467 auto const& issueField = (*obj.object)[sfAsset];
1468 auto const issue = issueField.value().get<MPTIssue>();
1469 BEAST_EXPECT(issue.getMptID().size() == 24);
1470 }
1471 }
1472
1473 // Invalid Issue: missing currency
1474 {
1475 Json::Value j;
1477 issue["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1478 j[sfAsset] = issue;
1479 STParsedJSONObject obj("Test", j);
1480 BEAST_EXPECT(!obj.object.has_value());
1481 }
1482
1483 // Invalid Issue: missing issuer
1484 {
1485 Json::Value j;
1487 issue["currency"] = "USD";
1488 j[sfAsset] = issue;
1489 STParsedJSONObject obj("Test", j);
1490 BEAST_EXPECT(!obj.object.has_value());
1491 }
1492
1493 // Invalid Issue: currency too long
1494 {
1495 Json::Value j;
1497 issue["currency"] = "USDD";
1498 issue["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1499 j[sfAsset] = issue;
1500 STParsedJSONObject obj("Test", j);
1501 BEAST_EXPECT(!obj.object.has_value());
1502 }
1503
1504 // Invalid Issue: issuer not base58 or hex
1505 {
1506 Json::Value j;
1508 issue["currency"] = "USD";
1509 issue["issuer"] = "notAValidIssuer";
1510 j[sfAsset] = issue;
1511 STParsedJSONObject obj("Test", j);
1512 BEAST_EXPECT(!obj.object.has_value());
1513 }
1514
1515 // Invalid Issue: currency not string
1516 {
1517 Json::Value j;
1519 issue["currency"] = Json::Value(Json::arrayValue);
1520 issue["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1521 j[sfAsset] = issue;
1522 STParsedJSONObject obj("Test", j);
1523 BEAST_EXPECT(!obj.object.has_value());
1524 }
1525
1526 // Invalid Issue: issuer not string
1527 {
1528 Json::Value j;
1530 issue["currency"] = "USD";
1531 issue["issuer"] = Json::Value(Json::objectValue);
1532 j[sfAsset] = issue;
1533 STParsedJSONObject obj("Test", j);
1534 BEAST_EXPECT(!obj.object.has_value());
1535 }
1536
1537 // Invalid Issue: not an object
1538 {
1539 Json::Value j;
1540 j[sfAsset] = "notanobject";
1541 STParsedJSONObject obj("Test", j);
1542 BEAST_EXPECT(!obj.object.has_value());
1543 }
1544 }
1545
1546 void
1548 {
1549 testcase("XChainBridge");
1550 // Valid XChainBridge
1551 {
1552 Json::Value j;
1554 Json::Value issuingChainIssue(Json::objectValue);
1555 issuingChainIssue["currency"] = "USD";
1556 issuingChainIssue["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1557 Json::Value lockingChainIssue(Json::objectValue);
1558 lockingChainIssue["currency"] = "EUR";
1559 lockingChainIssue["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1560 bridge["LockingChainIssue"] = lockingChainIssue;
1561 bridge["IssuingChainIssue"] = issuingChainIssue;
1562 bridge["LockingChainDoor"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1563 bridge["IssuingChainDoor"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1564 j[sfXChainBridge] = bridge;
1565 STParsedJSONObject obj("Test", j);
1566 if (BEAST_EXPECT(obj.object.has_value()))
1567 {
1568 BEAST_EXPECT(obj.object->isFieldPresent(sfXChainBridge));
1569 auto const& bridgeField = (*obj.object)[sfXChainBridge];
1570 BEAST_EXPECT(
1571 bridgeField->lockingChainIssue().currency.size() == 20);
1572 BEAST_EXPECT(
1573 bridgeField->issuingChainIssue().currency.size() == 20);
1574 }
1575 }
1576
1577 // Valid XChainBridge: issues as hex currency
1578 {
1579 Json::Value j;
1581 Json::Value issuingChainIssue(Json::objectValue);
1582 issuingChainIssue["currency"] =
1583 "0123456789ABCDEF01230123456789ABCDEF0123";
1584 issuingChainIssue["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1585 Json::Value lockingChainIssue(Json::objectValue);
1586 lockingChainIssue["currency"] =
1587 "0123456789ABCDEF01230123456789ABCDEF0123";
1588 lockingChainIssue["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1589 bridge["LockingChainIssue"] = lockingChainIssue;
1590 bridge["IssuingChainIssue"] = issuingChainIssue;
1591 bridge["LockingChainDoor"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1592 bridge["IssuingChainDoor"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1593 j[sfXChainBridge] = bridge;
1594 STParsedJSONObject obj("Test", j);
1595 if (BEAST_EXPECT(obj.object.has_value()))
1596 {
1597 BEAST_EXPECT(obj.object->isFieldPresent(sfXChainBridge));
1598 auto const& bridgeField = (*obj.object)[sfXChainBridge];
1599 BEAST_EXPECT(
1600 bridgeField->lockingChainIssue().currency.size() == 20);
1601 BEAST_EXPECT(
1602 bridgeField->issuingChainIssue().currency.size() == 20);
1603 }
1604 }
1605
1606 // Invalid XChainBridge: missing LockingChainIssue
1607 {
1608 Json::Value j;
1610 Json::Value issuingChainIssue(Json::objectValue);
1611 issuingChainIssue["currency"] = "USD";
1612 issuingChainIssue["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1613 bridge["IssuingChainIssue"] = issuingChainIssue;
1614 bridge["LockingChainDoor"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1615 bridge["IssuingChainDoor"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1616 j[sfXChainBridge] = bridge;
1617 STParsedJSONObject obj("Test", j);
1618 BEAST_EXPECT(!obj.object.has_value());
1619 }
1620
1621 // Invalid XChainBridge: missing IssuingChainIssue
1622 {
1623 Json::Value j;
1625 Json::Value lockingChainIssue(Json::objectValue);
1626 lockingChainIssue["currency"] = "EUR";
1627 lockingChainIssue["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1628 bridge["LockingChainIssue"] = lockingChainIssue;
1629 bridge["LockingChainDoor"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1630 bridge["IssuingChainDoor"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1631 j[sfXChainBridge] = bridge;
1632 STParsedJSONObject obj("Test", j);
1633 BEAST_EXPECT(!obj.object.has_value());
1634 }
1635
1636 // Invalid XChainBridge: missing LockingChainDoor
1637 {
1638 Json::Value j;
1640 Json::Value issuingChainIssue(Json::objectValue);
1641 issuingChainIssue["currency"] = "USD";
1642 issuingChainIssue["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1643 bridge["IssuingChainIssue"] = issuingChainIssue;
1644 Json::Value lockingChainIssue(Json::objectValue);
1645 lockingChainIssue["currency"] = "EUR";
1646 lockingChainIssue["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1647 bridge["LockingChainIssue"] = lockingChainIssue;
1648 bridge["IssuingChainDoor"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1649 j[sfXChainBridge] = bridge;
1650 STParsedJSONObject obj("Test", j);
1651 BEAST_EXPECT(!obj.object.has_value());
1652 }
1653
1654 // Invalid XChainBridge: missing IssuingChainDoor
1655 {
1656 Json::Value j;
1658 Json::Value issuingChainIssue(Json::objectValue);
1659 issuingChainIssue["currency"] = "USD";
1660 issuingChainIssue["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1661 bridge["IssuingChainIssue"] = issuingChainIssue;
1662 Json::Value lockingChainIssue(Json::objectValue);
1663 lockingChainIssue["currency"] = "EUR";
1664 lockingChainIssue["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1665 bridge["LockingChainIssue"] = lockingChainIssue;
1666 bridge["LockingChainDoor"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1667 j[sfXChainBridge] = bridge;
1668 STParsedJSONObject obj("Test", j);
1669 BEAST_EXPECT(!obj.object.has_value());
1670 }
1671
1672 // Invalid XChainBridge: IssuingChainIssue not an object
1673 {
1674 Json::Value j;
1676 bridge["LockingChainIssue"] = "notanobject";
1677 bridge["IssuingChainIssue"] = "notanobject";
1678 j[sfXChainBridge] = bridge;
1679 STParsedJSONObject obj("Test", j);
1680 BEAST_EXPECT(!obj.object.has_value());
1681 }
1682
1683 // Invalid XChainBridge: IssuingChainIssue missing currency
1684 {
1685 Json::Value j;
1688 asset["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1689 Json::Value lockingChainIssue(Json::objectValue);
1690 lockingChainIssue["currency"] = "EUR";
1691 lockingChainIssue["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1692 bridge["LockingChainIssue"] = lockingChainIssue;
1693 bridge["IssuingChainIssue"] = asset;
1694 j[sfXChainBridge] = bridge;
1695 STParsedJSONObject obj("Test", j);
1696 BEAST_EXPECT(!obj.object.has_value());
1697 }
1698
1699 // Invalid XChainBridge: asset missing issuer
1700 {
1701 Json::Value j;
1704 asset["currency"] = "USD";
1705 Json::Value lockingChainIssue(Json::objectValue);
1706 lockingChainIssue["currency"] = "EUR";
1707 lockingChainIssue["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1708 bridge["LockingChainIssue"] = lockingChainIssue;
1709 bridge["IssuingChainIssue"] = asset;
1710 j[sfXChainBridge] = bridge;
1711 STParsedJSONObject obj("Test", j);
1712 BEAST_EXPECT(!obj.object.has_value());
1713 }
1714
1715 // Invalid XChainBridge: asset issuer not base58
1716 {
1717 Json::Value j;
1720 asset["currency"] = "USD";
1721 asset["issuer"] = "notAValidBase58Account";
1722 Json::Value lockingChainIssue(Json::objectValue);
1723 lockingChainIssue["currency"] = "EUR";
1724 lockingChainIssue["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
1725 bridge["LockingChainIssue"] = lockingChainIssue;
1726 bridge["IssuingChainIssue"] = asset;
1727 j[sfXChainBridge] = bridge;
1728 STParsedJSONObject obj("Test", j);
1729 BEAST_EXPECT(!obj.object.has_value());
1730 }
1731
1732 // Invalid XChainBridge: not an object
1733 {
1734 Json::Value j;
1735 j[sfXChainBridge] = "notanobject";
1736 STParsedJSONObject obj("Test", j);
1737 BEAST_EXPECT(!obj.object.has_value());
1738 }
1739 }
1740
1741 void
1743 {
1744 testcase("Number");
1745 // Valid integer value for STNumber
1746 {
1747 Json::Value j;
1748 j[sfNumber] = 12345;
1749 STParsedJSONObject obj("Test", j);
1750 BEAST_EXPECT(obj.object.has_value());
1751 BEAST_EXPECT(obj.object->isFieldPresent(sfNumber));
1752 BEAST_EXPECT(
1753 obj.object->getFieldNumber(sfNumber).value() ==
1754 Number(12345, 0));
1755 }
1756
1757 // Valid uint value for STNumber
1758 {
1759 Json::Value j;
1760 j[sfNumber] = 12345u;
1761 STParsedJSONObject obj("Test", j);
1762 BEAST_EXPECT(obj.object.has_value());
1763 BEAST_EXPECT(obj.object->isFieldPresent(sfNumber));
1764 BEAST_EXPECT(
1765 obj.object->getFieldNumber(sfNumber).value() ==
1766 Number(12345, 0));
1767 }
1768
1769 // Valid string integer value for STNumber
1770 {
1771 Json::Value j;
1772 j[sfNumber] = "67890";
1773 STParsedJSONObject obj("Test", j);
1774 BEAST_EXPECT(obj.object.has_value());
1775 BEAST_EXPECT(obj.object->isFieldPresent(sfNumber));
1776 BEAST_EXPECT(
1777 obj.object->getFieldNumber(sfNumber).value() ==
1778 Number(67890, 0));
1779 }
1780
1781 // Valid negative integer value for STNumber
1782 {
1783 Json::Value j;
1784 j[sfNumber] = -42;
1785 STParsedJSONObject obj("Test", j);
1786 BEAST_EXPECT(obj.object.has_value());
1787 BEAST_EXPECT(obj.object->isFieldPresent(sfNumber));
1788 BEAST_EXPECT(
1789 obj.object->getFieldNumber(sfNumber).value() == Number(-42, 0));
1790 }
1791
1792 // Valid string negative integer value for STNumber
1793 {
1794 Json::Value j;
1795 j[sfNumber] = "-123";
1796 STParsedJSONObject obj("Test", j);
1797 BEAST_EXPECT(obj.object.has_value());
1798 BEAST_EXPECT(obj.object->isFieldPresent(sfNumber));
1799 BEAST_EXPECT(
1800 obj.object->getFieldNumber(sfNumber).value() ==
1801 Number(-123, 0));
1802 }
1803
1804 // Valid floating point value for STNumber
1805 {
1806 Json::Value j;
1807 j[sfNumber] = "3.14159";
1808 STParsedJSONObject obj("Test", j);
1809 if (BEAST_EXPECT(obj.object.has_value()))
1810 {
1811 BEAST_EXPECT(obj.object->isFieldPresent(sfNumber));
1812 BEAST_EXPECT(
1813 obj.object->getFieldNumber(sfNumber).value() ==
1814 Number(314159, -5));
1815 }
1816 }
1817
1818 // Invalid string value for STNumber (not a number)
1819 {
1820 Json::Value j;
1821 j[sfNumber] = "notanumber";
1822 STParsedJSONObject obj("Test", j);
1823 BEAST_EXPECT(!obj.object.has_value());
1824 }
1825
1826 // Invalid array value for STNumber
1827 {
1828 Json::Value j;
1829 j[sfNumber] = Json::Value(Json::arrayValue);
1830 STParsedJSONObject obj("Test", j);
1831 BEAST_EXPECT(!obj.object.has_value());
1832 }
1833
1834 // Invalid object value for STNumber
1835 {
1836 Json::Value j;
1837 j[sfNumber] = Json::Value(Json::objectValue);
1838 STParsedJSONObject obj("Test", j);
1839 BEAST_EXPECT(!obj.object.has_value());
1840 }
1841
1842 // Empty string for STNumber (should fail)
1843 {
1844 Json::Value j;
1845 j[sfNumber] = "";
1846 STParsedJSONObject obj("Test", j);
1847 BEAST_EXPECT(!obj.object.has_value());
1848 }
1849 }
1850
1851 void
1853 {
1854 testcase("Object");
1855 // Test with valid object for Object
1856 {
1857 Json::Value j;
1859 objVal[sfTransactionResult] = 1;
1860 j[sfTransactionMetaData] = objVal;
1861 STParsedJSONObject obj("Test", j);
1862 BEAST_EXPECT(obj.object.has_value());
1863 BEAST_EXPECT(obj.object->isFieldPresent(sfTransactionMetaData));
1864 auto const& result =
1865 obj.object->peekFieldObject(sfTransactionMetaData);
1866 BEAST_EXPECT(result.getFieldU8(sfTransactionResult) == 1);
1867 }
1868
1869 // Test with non-object value for Object (should fail)
1870 {
1871 Json::Value j;
1872 j[sfTransactionMetaData] = "notanobject";
1873 STParsedJSONObject obj("Test", j);
1874 BEAST_EXPECT(!obj.object.has_value());
1875 }
1876
1877 // Test with array value for Object (should fail)
1878 {
1879 Json::Value j;
1881 arr.append(1);
1882 j[sfTransactionMetaData] = arr;
1883 STParsedJSONObject obj("Test", j);
1884 BEAST_EXPECT(!obj.object.has_value());
1885 }
1886
1887 // Test with null value for Object (should fail)
1888 {
1889 Json::Value j;
1890 j[sfTransactionMetaData] = Json::Value(Json::nullValue);
1891 STParsedJSONObject obj("Test", j);
1892 BEAST_EXPECT(!obj.object.has_value());
1893 }
1894
1895 // Test with max depth (should succeed)
1896 // max depth is 64
1897 {
1898 Json::Value j;
1900 Json::Value* current = &obj;
1901 for (int i = 0; i < 63; ++i)
1902 {
1904 (*current)[sfTransactionMetaData] = next;
1905 current = &((*current)[sfTransactionMetaData]);
1906 }
1907 (*current)[sfTransactionResult.getJsonName()] = 1;
1908 j[sfTransactionMetaData] = obj;
1909 STParsedJSONObject parsed("Test", j);
1910 BEAST_EXPECT(parsed.object.has_value());
1911 BEAST_EXPECT(parsed.object->isFieldPresent(sfTransactionMetaData));
1912 }
1913
1914 // Test with depth exceeding maxDepth (should fail)
1915 {
1916 Json::Value j;
1918 Json::Value* current = &obj;
1919 for (int i = 0; i < 64; ++i)
1920 {
1922 (*current)[sfTransactionMetaData] = next;
1923 current = &((*current)[sfTransactionMetaData]);
1924 }
1925 (*current)[sfTransactionResult.getJsonName()] = 1;
1926 j[sfTransactionMetaData] = obj;
1927 STParsedJSONObject parsed("Test", j);
1928 BEAST_EXPECT(!parsed.object.has_value());
1929 }
1930 }
1931
1932 void
1934 {
1935 testcase("Array");
1936 // Test with valid array for Array
1937 {
1938 Json::Value j;
1941 elem[sfTransactionResult] = 2;
1943 elem2[sfTransactionMetaData] = elem;
1944 arr.append(elem2);
1945 j[sfSignerEntries] = arr;
1946 STParsedJSONObject obj("Test", j);
1947 BEAST_EXPECT(obj.object.has_value());
1948 BEAST_EXPECT(obj.object->isFieldPresent(sfSignerEntries));
1949 auto const& result = obj.object->getFieldArray(sfSignerEntries);
1950 if (BEAST_EXPECT(result.size() == 1))
1951 {
1952 BEAST_EXPECT(result[0].getFName() == sfTransactionMetaData);
1953 BEAST_EXPECT(result[0].getJson(0) == elem);
1954 }
1955 }
1956
1957 // Test with array containing non-object element (should fail)
1958 {
1959 Json::Value j;
1961 arr.append("notanobject");
1962 j[sfSignerEntries] = arr;
1963 STParsedJSONObject obj("Test", j);
1964 BEAST_EXPECT(!obj.object.has_value());
1965 }
1966
1967 // Test with array containing object with invalid field (should fail)
1968 {
1969 Json::Value j;
1972 elem["invalidField"] = 1;
1973 arr.append(elem);
1974 j[sfSignerEntries] = arr;
1975 STParsedJSONObject obj("Test", j);
1976 BEAST_EXPECT(!obj.object.has_value());
1977 }
1978
1979 // Test with array containing object with multiple keys (should fail)
1980 {
1981 Json::Value j;
1984 elem[sfTransactionResult] = 2;
1985 elem[sfNetworkID] = 3;
1986 arr.append(elem);
1987 j[sfSignerEntries] = arr;
1988 STParsedJSONObject obj("Test", j);
1989 BEAST_EXPECT(!obj.object.has_value());
1990 }
1991
1992 // Test with non-array value for Array (should fail)
1993 {
1994 Json::Value j;
1995 j[sfSignerEntries] = "notanarray";
1996 STParsedJSONObject obj("Test", j);
1997 BEAST_EXPECT(!obj.object.has_value());
1998 }
1999
2000 // Test with array containing object with valid field but invalid value
2001 // (should fail)
2002 {
2003 Json::Value j;
2006 elem[sfTransactionResult] = "notanint";
2007 arr.append(elem);
2008 j[sfSignerEntries] = arr;
2009 STParsedJSONObject obj("Test", j);
2010 BEAST_EXPECT(!obj.object.has_value());
2011 }
2012
2013 // Test with empty array for Array (should be valid)
2014 {
2015 Json::Value j;
2017 j[sfSignerEntries] = arr;
2018 STParsedJSONObject obj("Test", j);
2019 BEAST_EXPECT(obj.object.has_value());
2020 BEAST_EXPECT(obj.object->isFieldPresent(sfSignerEntries));
2021 }
2022
2023 // Test with object provided but not object SField
2024 {
2025 Json::Value j;
2028 obj[0u][sfTransactionResult] = 1;
2029 j[sfSignerEntries] = obj;
2030 STParsedJSONObject parsed("Test", j);
2031 BEAST_EXPECT(!parsed.object.has_value());
2032 }
2033
2034 // Test invalid children
2035 {
2036 try
2037 {
2038 /*
2039
2040 STArray/STObject constructs don't really map perfectly to json
2041 arrays/objects.
2042
2043 STObject is an associative container, mapping fields to value,
2044 but an STObject may also have a Field as its name, stored
2045 outside the associative structure. The name is important, so to
2046 maintain fidelity, it will take TWO json objects to represent
2047 them.
2048
2049 */
2050 std::string faulty(
2051 "{\"Template\":[{"
2052 "\"ModifiedNode\":{\"Sequence\":1}, "
2053 "\"DeletedNode\":{\"Sequence\":1}"
2054 "}]}");
2055
2057 Json::Value faultyJson;
2058 bool parsedOK(parseJSONString(faulty, faultyJson));
2059 unexpected(!parsedOK, "failed to parse");
2060 STParsedJSONObject parsed("test", faultyJson);
2061 BEAST_EXPECT(!parsed.object);
2062 }
2063 catch (std::runtime_error& e)
2064 {
2065 std::string what(e.what());
2066 unexpected(
2067 what.find("First level children of `Template`") != 0);
2068 }
2069 }
2070 }
2071
2072 void
2074 {
2075 testcase("General Invalid Cases");
2076
2077 {
2078 Json::Value j;
2079 j[sfLedgerEntry] = 1; // not a valid SField for STParsedJSON
2080 }
2081
2082 {
2083 std::string const goodJson(R"({"CloseResolution":19,"Method":250,)"
2084 R"("TransactionResult":"tecFROZEN"})");
2085
2086 Json::Value jv;
2087 if (BEAST_EXPECT(parseJSONString(goodJson, jv)))
2088 {
2089 STParsedJSONObject parsed("test", jv);
2090 if (BEAST_EXPECT(parsed.object))
2091 {
2092 std::string const& serialized(
2093 to_string(parsed.object->getJson(JsonOptions::none)));
2094 BEAST_EXPECT(serialized == goodJson);
2095 }
2096 }
2097 }
2098
2099 {
2100 std::string const goodJson(
2101 R"({"CloseResolution":19,"Method":"250",)"
2102 R"("TransactionResult":"tecFROZEN"})");
2103 std::string const expectedJson(
2104 R"({"CloseResolution":19,"Method":250,)"
2105 R"("TransactionResult":"tecFROZEN"})");
2106
2107 Json::Value jv;
2108 if (BEAST_EXPECT(parseJSONString(goodJson, jv)))
2109 {
2110 // Integer values are always parsed as int,
2111 // unless they're too big. We want a small uint.
2112 jv["CloseResolution"] = Json::UInt(19);
2113 STParsedJSONObject parsed("test", jv);
2114 if (BEAST_EXPECT(parsed.object))
2115 {
2116 std::string const& serialized(
2117 to_string(parsed.object->getJson(JsonOptions::none)));
2118 BEAST_EXPECT(serialized == expectedJson);
2119 }
2120 }
2121 }
2122
2123 {
2124 std::string const goodJson(
2125 R"({"CloseResolution":"19","Method":"250",)"
2126 R"("TransactionResult":"tecFROZEN"})");
2127 std::string const expectedJson(
2128 R"({"CloseResolution":19,"Method":250,)"
2129 R"("TransactionResult":"tecFROZEN"})");
2130
2131 Json::Value jv;
2132 if (BEAST_EXPECT(parseJSONString(goodJson, jv)))
2133 {
2134 // Integer values are always parsed as int,
2135 // unless they're too big. We want a small uint.
2136 jv["CloseResolution"] = Json::UInt(19);
2137 STParsedJSONObject parsed("test", jv);
2138 if (BEAST_EXPECT(parsed.object))
2139 {
2140 std::string const& serialized(
2141 to_string(parsed.object->getJson(JsonOptions::none)));
2142 BEAST_EXPECT(serialized == expectedJson);
2143 }
2144 }
2145 }
2146
2147 {
2148 std::string const json(R"({"CloseResolution":19,"Method":250,)"
2149 R"("TransactionResult":"terQUEUED"})");
2150
2151 Json::Value jv;
2152 if (BEAST_EXPECT(parseJSONString(json, jv)))
2153 {
2154 STParsedJSONObject parsed("test", jv);
2155 BEAST_EXPECT(!parsed.object);
2156 BEAST_EXPECT(parsed.error);
2157 BEAST_EXPECT(parsed.error[jss::error] == "invalidParams");
2158 BEAST_EXPECT(
2159 parsed.error[jss::error_message] ==
2160 "Field 'test.TransactionResult' is out of range.");
2161 }
2162 }
2163
2164 {
2165 std::string const json(R"({"CloseResolution":19,"Method":"pony",)"
2166 R"("TransactionResult":"tesSUCCESS"})");
2167
2168 Json::Value jv;
2169 if (BEAST_EXPECT(parseJSONString(json, jv)))
2170 {
2171 STParsedJSONObject parsed("test", jv);
2172 BEAST_EXPECT(!parsed.object);
2173 BEAST_EXPECT(parsed.error);
2174 BEAST_EXPECT(parsed.error[jss::error] == "invalidParams");
2175 BEAST_EXPECT(
2176 parsed.error[jss::error_message] ==
2177 "Field 'test.Method' has bad type.");
2178 }
2179 }
2180
2181 {
2182 std::string const json(
2183 R"({"CloseResolution":19,"Method":3294967296,)"
2184 R"("TransactionResult":"tesSUCCESS"})");
2185
2186 Json::Value jv;
2187 if (BEAST_EXPECT(parseJSONString(json, jv)))
2188 {
2189 STParsedJSONObject parsed("test", jv);
2190 BEAST_EXPECT(!parsed.object);
2191 BEAST_EXPECT(parsed.error);
2192 BEAST_EXPECT(parsed.error[jss::error] == "invalidParams");
2193 BEAST_EXPECT(
2194 parsed.error[jss::error_message] ==
2195 "Field 'test.Method' is out of range.");
2196 }
2197 }
2198
2199 {
2200 std::string const json(R"({"CloseResolution":-10,"Method":42,)"
2201 R"("TransactionResult":"tesSUCCESS"})");
2202
2203 Json::Value jv;
2204 if (BEAST_EXPECT(parseJSONString(json, jv)))
2205 {
2206 STParsedJSONObject parsed("test", jv);
2207 BEAST_EXPECT(!parsed.object);
2208 BEAST_EXPECT(parsed.error);
2209 BEAST_EXPECT(parsed.error[jss::error] == "invalidParams");
2210 BEAST_EXPECT(
2211 parsed.error[jss::error_message] ==
2212 "Field 'test.CloseResolution' is out of range.");
2213 }
2214 }
2215
2216 {
2217 std::string const json(
2218 R"({"CloseResolution":19,"Method":3.141592653,)"
2219 R"("TransactionResult":"tesSUCCESS"})");
2220
2221 Json::Value jv;
2222 if (BEAST_EXPECT(parseJSONString(json, jv)))
2223 {
2224 STParsedJSONObject parsed("test", jv);
2225 BEAST_EXPECT(!parsed.object);
2226 BEAST_EXPECT(parsed.error);
2227 BEAST_EXPECT(parsed.error[jss::error] == "invalidParams");
2228 BEAST_EXPECT(
2229 parsed.error[jss::error_message] ==
2230 "Field 'test.Method' has bad type.");
2231 }
2232 }
2233
2234 {
2235 std::string const goodJson(R"({"CloseResolution":19,"Method":250,)"
2236 R"("TransferFee":"65535"})");
2237 std::string const expectedJson(
2238 R"({"CloseResolution":19,"Method":250,)"
2239 R"("TransferFee":65535})");
2240
2241 Json::Value jv;
2242 if (BEAST_EXPECT(parseJSONString(goodJson, jv)))
2243 {
2244 STParsedJSONObject parsed("test", jv);
2245 if (BEAST_EXPECT(parsed.object))
2246 {
2247 std::string const& serialized(
2248 to_string(parsed.object->getJson(JsonOptions::none)));
2249 BEAST_EXPECT(serialized == expectedJson);
2250 }
2251 }
2252 }
2253
2254 {
2255 std::string const json(R"({"CloseResolution":19,"Method":250,)"
2256 R"("TransferFee":"65536"})");
2257
2258 Json::Value jv;
2259 if (BEAST_EXPECT(parseJSONString(json, jv)))
2260 {
2261 STParsedJSONObject parsed("test", jv);
2262 BEAST_EXPECT(!parsed.object);
2263 BEAST_EXPECT(parsed.error);
2264 BEAST_EXPECT(parsed.error[jss::error] == "invalidParams");
2265 BEAST_EXPECT(
2266 parsed.error[jss::error_message] ==
2267 "Field 'test.TransferFee' has invalid data.");
2268 }
2269 }
2270
2271 {
2272 std::string const json(R"({"CloseResolution":19,"Method":250,)"
2273 R"("TransferFee":"Payment"})");
2274
2275 Json::Value jv;
2276 if (BEAST_EXPECT(parseJSONString(json, jv)))
2277 {
2278 STParsedJSONObject parsed("test", jv);
2279 BEAST_EXPECT(!parsed.object);
2280 BEAST_EXPECT(parsed.error);
2281 BEAST_EXPECT(parsed.error[jss::error] == "invalidParams");
2282 BEAST_EXPECT(
2283 parsed.error[jss::error_message] ==
2284 "Field 'test.TransferFee' has invalid data.");
2285 }
2286 }
2287
2288 {
2289 std::string const json(R"({"CloseResolution":19,"Method":250,)"
2290 R"("TransferFee":true})");
2291
2292 Json::Value jv;
2293 if (BEAST_EXPECT(parseJSONString(json, jv)))
2294 {
2295 STParsedJSONObject parsed("test", jv);
2296 BEAST_EXPECT(!parsed.object);
2297 BEAST_EXPECT(parsed.error);
2298 BEAST_EXPECT(parsed.error[jss::error] == "invalidParams");
2299 BEAST_EXPECT(
2300 parsed.error[jss::error_message] ==
2301 "Field 'test.TransferFee' has bad type.");
2302 }
2303 }
2304 }
2305
2306 void
2307 run() override
2308 {
2309 // Instantiate a jtx::Env so debugLog writes are exercised.
2310 test::jtx::Env env(*this);
2311 testUInt8();
2312 testUInt16();
2313 testUInt32();
2314 testUInt64();
2315 testUInt128();
2316 testUInt160();
2317 testUInt192();
2318 testUInt256();
2319 testInt32();
2320 testBlob();
2321 testVector256();
2322 testAccount();
2323 testCurrency();
2324 testAmount();
2325 testPathSet();
2326 testIssue();
2328 testNumber();
2329 testObject();
2330 testArray();
2331 testEdgeCases();
2332 }
2333};
2334
2335BEAST_DEFINE_TESTSUITE(STParsedJSON, protocol, ripple);
2336
2337} // namespace ripple
T all_of(T... args)
Unserialize a JSON document into a Value.
Definition json_reader.h:20
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
Represents a JSON value.
Definition json_value.h:130
Value & append(Value const &value)
Append value to array at the end.
bool isObject() const
A testsuite class.
Definition suite.h:52
bool unexpected(Condition shouldBeFalse, String const &reason)
Definition suite.h:496
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:152
A currency issued by an account.
Definition Issue.h:14
Holds the serialized result of parsing an input JSON object.
std::optional< STObject > object
The STObject if the parse was successful.
Json::Value error
On failure, an appropriate set of error values.
bool parseJSONString(std::string const &json, Json::Value &to)
void run() override
Runs the suite.
Integers of any length that is a multiple of 32-bits.
Definition base_uint.h:67
A transaction testing environment.
Definition Env.h:102
T find(T... args)
@ nullValue
'null' value
Definition json_value.h:19
@ arrayValue
array value (ordered list)
Definition json_value.h:25
@ objectValue
object value (collection of name/value pairs).
Definition json_value.h:26
unsigned int UInt
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition AccountID.cpp:95
@ current
This was a new validation and was added.
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.
T to_string(T... args)
T what(T... args)