From 5a2e698f79cb4968ae0d07e855519e482a1a873e Mon Sep 17 00:00:00 2001 From: bthomee Date: Thu, 15 Jan 2026 05:39:24 -0800 Subject: [PATCH] deploy: ec44347ffc23db2dba3332c730a94e73e22054a6 --- Batch__test_8cpp_source.html | 8180 +++++++++-------- RangeSet_8cpp_source.html | 201 +- Slice_8cpp_source.html | 143 +- Value_8cpp_source.html | 2705 +++--- Vault__test_8cpp_source.html | 2 +- annotated.html | 2 +- basics_2main_8cpp_source.html | 10 +- ...rs.html => classWriterFixture-members.html | 14 +- ...terFixture.html => classWriterFixture.html | 115 +- ...map => classWriterFixture__coll__graph.map | 46 +- classWriterFixture__coll__graph.md5 | 1 + classWriterFixture__coll__graph.png | Bin 0 -> 52681 bytes classWriterFixture__inherit__graph.map | 5 + classWriterFixture__inherit__graph.md5 | 1 + classWriterFixture__inherit__graph.png | Bin 0 -> 3396 bytes classes.html | 2 +- classxrpl_1_1test_1_1Batch__test.html | 62 +- crypto_2main_8cpp_source.html | 10 +- functions_c.html | 2 +- functions_e.html | 2 +- functions_func_c.html | 2 +- functions_func_e.html | 2 +- functions_func_r.html | 4 +- functions_func_s.html | 23 +- functions_func_u.html | 2 +- functions_func_w.html | 1 - functions_o.html | 2 +- functions_r.html | 4 +- functions_s.html | 65 +- functions_t.html | 8 +- functions_u.html | 2 +- functions_v.html | 9 +- functions_vars_o.html | 2 +- functions_vars_w.html | 2 +- functions_w.html | 9 +- hierarchy.html | 587 +- inherit_graph_1013.map | 2 +- inherit_graph_1013.md5 | 2 +- inherit_graph_1052.map | 4 +- inherit_graph_1052.md5 | 2 +- inherit_graph_1054.map | 2 +- inherit_graph_1054.md5 | 2 +- inherit_graph_1055.map | 2 +- inherit_graph_1055.md5 | 2 +- inherit_graph_1057.map | 2 +- inherit_graph_1057.md5 | 2 +- inherit_graph_1058.map | 2 +- inherit_graph_1058.md5 | 2 +- inherit_graph_184.map | 8 +- inherit_graph_184.md5 | 2 +- inherit_graph_184.png | Bin 8524 -> 2988 bytes inherit_graph_185.map | 6 +- inherit_graph_185.md5 | 2 +- inherit_graph_185.png | Bin 1376 -> 8524 bytes inherit_graph_186.map | 2 +- inherit_graph_186.md5 | 2 +- inherit_graph_187.map | 2 +- inherit_graph_187.md5 | 2 +- inherit_graph_192.map | 2 +- inherit_graph_192.md5 | 2 +- inherit_graph_204.map | 6 +- inherit_graph_204.md5 | 2 +- inherit_graph_205.map | 4 +- inherit_graph_205.md5 | 2 +- inherit_graph_218.map | 2 +- inherit_graph_218.md5 | 2 +- inherit_graph_238.map | 2 +- inherit_graph_238.md5 | 2 +- inherit_graph_255.map | 2 +- inherit_graph_255.md5 | 2 +- inherit_graph_256.map | 2 +- inherit_graph_256.md5 | 2 +- inherit_graph_257.map | 2 +- inherit_graph_257.md5 | 2 +- inherit_graph_258.map | 2 +- inherit_graph_258.md5 | 2 +- inherit_graph_259.map | 2 +- inherit_graph_259.md5 | 2 +- inherit_graph_260.map | 2 +- inherit_graph_260.md5 | 2 +- inherit_graph_261.map | 30 +- inherit_graph_261.md5 | 2 +- inherit_graph_262.map | 8 +- inherit_graph_262.md5 | 2 +- inherit_graph_263.map | 8 +- inherit_graph_263.md5 | 2 +- inherit_graph_264.map | 2 +- inherit_graph_264.md5 | 2 +- inherit_graph_265.map | 32 +- inherit_graph_265.md5 | 2 +- inherit_graph_266.map | 2 +- inherit_graph_266.md5 | 2 +- inherit_graph_267.map | 2 +- inherit_graph_267.md5 | 2 +- inherit_graph_268.map | 2 +- inherit_graph_268.md5 | 2 +- inherit_graph_270.map | 2 +- inherit_graph_270.md5 | 2 +- inherit_graph_271.map | 8 +- inherit_graph_271.md5 | 2 +- inherit_graph_272.map | 2 +- inherit_graph_272.md5 | 2 +- inherit_graph_273.map | 20 +- inherit_graph_273.md5 | 2 +- inherit_graph_274.map | 2 +- inherit_graph_274.md5 | 2 +- inherit_graph_275.map | 2 +- inherit_graph_275.md5 | 2 +- inherit_graph_276.map | 64 +- inherit_graph_276.md5 | 2 +- inherit_graph_277.map | 2 +- inherit_graph_277.md5 | 2 +- inherit_graph_278.map | 2 +- inherit_graph_278.md5 | 2 +- inherit_graph_279.map | 4 +- inherit_graph_279.md5 | 2 +- inherit_graph_285.map | 2 +- inherit_graph_285.md5 | 2 +- inherit_graph_287.map | 2 +- inherit_graph_287.md5 | 2 +- inherit_graph_312.map | 6 +- inherit_graph_312.md5 | 2 +- inherit_graph_314.map | 4 +- inherit_graph_314.md5 | 2 +- inherit_graph_318.map | 2 +- inherit_graph_318.md5 | 2 +- inherit_graph_320.map | 8 +- inherit_graph_320.md5 | 2 +- inherit_graph_323.map | 2 +- inherit_graph_323.md5 | 2 +- inherit_graph_329.map | 2 +- inherit_graph_329.md5 | 2 +- inherit_graph_333.map | 2 +- inherit_graph_333.md5 | 2 +- inherit_graph_335.map | 2 +- inherit_graph_335.md5 | 2 +- inherit_graph_336.map | 2 +- inherit_graph_336.md5 | 2 +- inherit_graph_354.map | 4 +- inherit_graph_354.md5 | 2 +- inherit_graph_357.map | 2 +- inherit_graph_357.md5 | 2 +- inherit_graph_361.map | 2 +- inherit_graph_361.md5 | 2 +- inherit_graph_366.map | 4 +- inherit_graph_366.md5 | 2 +- inherit_graph_367.map | 2 +- inherit_graph_367.md5 | 2 +- inherit_graph_369.map | 4 +- inherit_graph_369.md5 | 2 +- inherit_graph_388.map | 2 +- inherit_graph_388.md5 | 2 +- inherit_graph_391.map | 2 +- inherit_graph_391.md5 | 2 +- inherit_graph_392.map | 2 +- inherit_graph_392.md5 | 2 +- inherit_graph_420.map | 2 +- inherit_graph_420.md5 | 2 +- inherit_graph_423.map | 6 +- inherit_graph_423.md5 | 2 +- inherit_graph_453.map | 2 +- inherit_graph_453.md5 | 2 +- inherit_graph_455.map | 6 +- inherit_graph_455.md5 | 2 +- inherit_graph_458.map | 6 +- inherit_graph_458.md5 | 2 +- inherit_graph_461.map | 6 +- inherit_graph_461.md5 | 2 +- inherit_graph_464.map | 2 +- inherit_graph_464.md5 | 2 +- inherit_graph_467.map | 4 +- inherit_graph_467.md5 | 2 +- inherit_graph_469.map | 2 +- inherit_graph_469.md5 | 2 +- inherit_graph_494.map | 24 +- inherit_graph_494.md5 | 2 +- inherit_graph_526.map | 2 +- inherit_graph_526.md5 | 2 +- inherit_graph_538.map | 2 +- inherit_graph_538.md5 | 2 +- inherit_graph_541.map | 4 +- inherit_graph_541.md5 | 2 +- inherit_graph_543.map | 4 +- inherit_graph_543.md5 | 2 +- inherit_graph_549.map | 6 +- inherit_graph_549.md5 | 2 +- inherit_graph_550.map | 4 +- inherit_graph_550.md5 | 2 +- inherit_graph_555.map | 4 +- inherit_graph_555.md5 | 2 +- inherit_graph_597.map | 4 +- inherit_graph_597.md5 | 2 +- inherit_graph_618.map | 4 +- inherit_graph_618.md5 | 2 +- inherit_graph_652.map | 2 +- inherit_graph_652.md5 | 2 +- inherit_graph_657.map | 2 +- inherit_graph_657.md5 | 2 +- inherit_graph_664.map | 2 +- inherit_graph_664.md5 | 2 +- inherit_graph_666.map | 8 +- inherit_graph_666.md5 | 2 +- inherit_graph_673.map | 4 +- inherit_graph_673.md5 | 2 +- inherit_graph_674.map | 12 +- inherit_graph_674.md5 | 2 +- inherit_graph_695.map | 4 +- inherit_graph_695.md5 | 2 +- inherit_graph_718.map | 6 +- inherit_graph_718.md5 | 2 +- inherit_graph_738.map | 2 +- inherit_graph_738.md5 | 2 +- inherit_graph_815.map | 2 +- inherit_graph_815.md5 | 2 +- inherit_graph_850.map | 2 +- inherit_graph_850.md5 | 2 +- inherit_graph_851.map | 2 +- inherit_graph_851.md5 | 2 +- inherit_graph_852.map | 2 +- inherit_graph_852.md5 | 2 +- inherit_graph_853.map | 2 +- inherit_graph_853.md5 | 2 +- inherit_graph_854.map | 2 +- inherit_graph_854.md5 | 2 +- inherit_graph_857.map | 2 +- inherit_graph_857.md5 | 2 +- inherit_graph_971.map | 2 +- inherit_graph_971.md5 | 2 +- inherit_graph_972.map | 2 +- inherit_graph_972.md5 | 2 +- inherit_graph_981.map | 6 +- inherit_graph_981.md5 | 2 +- inherit_graph_982.map | 2 +- inherit_graph_982.md5 | 2 +- inherit_graph_983.map | 2 +- inherit_graph_983.md5 | 2 +- inherit_graph_992.map | 146 +- inherit_graph_992.md5 | 2 +- inherits.html | 14 +- json_2main_8cpp_source.html | 10 +- md_tests_2README.html | 2 +- namespacemembers_func_t.html | 6 +- namespacemembers_s.html | 2 +- namespacemembers_t.html | 4 +- namespacexrpl.html | 475 +- net_2main_8cpp_source.html | 10 +- scope_8cpp_source.html | 45 +- search/all_10.js | 2 +- search/all_13.js | 4 +- search/all_16.js | 4 +- search/all_17.js | 4 +- search/all_19.js | 4 +- search/all_1a.js | 72 +- search/all_1b.js | 4045 ++++---- search/all_1c.js | 2 +- search/all_1d.js | 8 +- search/all_1e.js | 32 +- search/all_8.js | 6 +- search/all_a.js | 6 +- search/all_b.js | 2 +- search/all_c.js | 6 +- search/all_d.js | 2 +- search/classes_16.js | 2 +- search/enums_4.js | 2 +- search/enumvalues_1.js | 2 +- search/enumvalues_13.js | 2 +- search/enumvalues_6.js | 2 +- search/enumvalues_9.js | 2 +- search/enumvalues_f.js | 2 +- search/functions_12.js | 4 +- search/functions_13.js | 44 +- search/functions_14.js | 3103 ++++--- search/functions_15.js | 2 +- search/functions_17.js | 55 +- search/functions_3.js | 2 +- search/functions_5.js | 2 +- search/variables_13.js | 4 +- search/variables_16.js | 4 +- search/variables_e.js | 2 +- structWriterFixture__coll__graph.md5 | 1 - structWriterFixture__coll__graph.png | Bin 49521 -> 0 bytes tagged__integer_8cpp_source.html | 245 +- ..._2libxrpl_2basics_2base64_8cpp_source.html | 11 +- ...libxrpl_2basics_2contract_8cpp_source.html | 14 +- ..._2libxrpl_2basics_2mulDiv_8cpp_source.html | 39 +- ..._2libxrpl_2crypto_2csprng_8cpp_source.html | 9 +- tests_2libxrpl_2json_2Output_8cpp_source.html | 57 +- tests_2libxrpl_2json_2Writer_8cpp_source.html | 121 +- ...2libxrpl_2net_2HTTPClient_8cpp_source.html | 44 +- 289 files changed, 10887 insertions(+), 10706 deletions(-) rename structWriterFixture-members.html => classWriterFixture-members.html (62%) rename structWriterFixture.html => classWriterFixture.html (73%) rename structWriterFixture__coll__graph.map => classWriterFixture__coll__graph.map (61%) create mode 100644 classWriterFixture__coll__graph.md5 create mode 100644 classWriterFixture__coll__graph.png create mode 100644 classWriterFixture__inherit__graph.map create mode 100644 classWriterFixture__inherit__graph.md5 create mode 100644 classWriterFixture__inherit__graph.png delete mode 100644 structWriterFixture__coll__graph.md5 delete mode 100644 structWriterFixture__coll__graph.png diff --git a/Batch__test_8cpp_source.html b/Batch__test_8cpp_source.html index 6426a6f260..2b4d96b655 100644 --- a/Batch__test_8cpp_source.html +++ b/Batch__test_8cpp_source.html @@ -534,968 +534,968 @@ $(document).ready(function() { init_codefold(0); });
427 auto const batchFee = batch::calcBatchFee(env, 0, 2);
428 auto tx1 = batch::inner(pay(alice, bob, XRP(1)), seq + 1);
429 tx1[jss::Fee] = "1.5";
-
430 try
-
431 {
-
432 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
433 tx1,
-
434 batch::inner(pay(alice, bob, XRP(2)), seq + 2));
-
435 fail("Expected parse_error for fractional fee");
-
436 }
-
437 catch (jtx::parse_error const&)
-
438 {
-
439 BEAST_EXPECT(true);
-
440 }
-
441 }
-
442
-
443 // temSEQ_AND_TICKET: Batch: inner txn cannot have both Sequence
-
444 // and TicketSequence.
-
445 {
-
446 auto const seq = env.seq(alice);
-
447 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
448 auto tx1 = batch::inner(pay(alice, bob, XRP(1)), 0, 1);
-
449 tx1[jss::Sequence] = seq + 1;
-
450 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
451 tx1,
-
452 batch::inner(pay(alice, bob, XRP(2)), seq + 2),
-
453 ter(temSEQ_AND_TICKET));
-
454 env.close();
-
455 }
-
456
-
457 // temSEQ_AND_TICKET: Batch: inner txn must have either Sequence or
-
458 // TicketSequence.
-
459 {
-
460 auto const seq = env.seq(alice);
-
461 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
462 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
463 batch::inner(pay(alice, bob, XRP(1)), 0),
-
464 batch::inner(pay(alice, bob, XRP(2)), seq + 2),
-
465 ter(temSEQ_AND_TICKET));
-
466 env.close();
-
467 }
-
468
-
469 // temREDUNDANT: Batch: duplicate sequence found:
-
470 {
-
471 auto const seq = env.seq(alice);
-
472 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
473 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
474 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
475 batch::inner(pay(alice, bob, XRP(2)), seq + 1),
-
476 ter(temREDUNDANT));
-
477 env.close();
-
478 }
-
479
-
480 // temREDUNDANT: Batch: duplicate ticket found:
-
481 {
-
482 auto const seq = env.seq(alice);
-
483 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
484 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
485 batch::inner(pay(alice, bob, XRP(1)), 0, seq + 1),
-
486 batch::inner(pay(alice, bob, XRP(2)), 0, seq + 1),
-
487 ter(temREDUNDANT));
-
488 env.close();
-
489 }
-
490
-
491 // temREDUNDANT: Batch: duplicate ticket & sequence found:
-
492 {
-
493 auto const seq = env.seq(alice);
-
494 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
495 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
496 batch::inner(pay(alice, bob, XRP(1)), 0, seq + 1),
-
497 batch::inner(pay(alice, bob, XRP(2)), seq + 1),
-
498 ter(temREDUNDANT));
-
499 env.close();
-
500 }
-
501
-
502 // DEFENSIVE: temARRAY_TOO_LARGE: Batch: signers array exceeds 8
-
503 // entries.
-
504 // ACTUAL: telENV_RPC_FAILED: isRawTransactionOkay()
-
505 {
-
506 auto const seq = env.seq(alice);
-
507 auto const batchFee = batch::calcBatchFee(env, 9, 2);
-
508 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
509 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
-
510 batch::inner(pay(alice, bob, XRP(5)), seq + 2),
-
511 batch::sig(
-
512 bob,
-
513 carol,
-
514 alice,
-
515 bob,
-
516 carol,
-
517 alice,
-
518 bob,
-
519 carol,
-
520 alice,
-
521 alice),
-
522 ter(telENV_RPC_FAILED));
-
523 env.close();
-
524 }
-
525
-
526 // temBAD_SIGNER: Batch: signer cannot be the outer account
-
527 {
-
528 auto const seq = env.seq(alice);
-
529 auto const batchFee = batch::calcBatchFee(env, 2, 2);
-
530 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
531 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
-
532 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
-
533 batch::sig(alice, bob),
-
534 ter(temBAD_SIGNER));
-
535 env.close();
-
536 }
-
537
-
538 // temREDUNDANT: Batch: duplicate signer found
-
539 {
-
540 auto const seq = env.seq(alice);
-
541 auto const batchFee = batch::calcBatchFee(env, 2, 2);
-
542 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
543 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
-
544 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
-
545 batch::sig(bob, bob),
-
546 ter(temREDUNDANT));
-
547 env.close();
-
548 }
-
549
-
550 // temBAD_SIGNER: Batch: no account signature for inner txn.
-
551 // Note: Extra signature by bob
-
552 {
-
553 auto const seq = env.seq(alice);
-
554 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
555 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
556 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
-
557 batch::inner(pay(alice, bob, XRP(5)), seq + 2),
-
558 batch::sig(bob),
-
559 ter(temBAD_SIGNER));
-
560 env.close();
-
561 }
-
562
-
563 // temBAD_SIGNER: Batch: no account signature for inner txn.
-
564 {
-
565 auto const seq = env.seq(alice);
-
566 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
567 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
568 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
-
569 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
-
570 batch::sig(carol),
-
571 ter(temBAD_SIGNER));
-
572 env.close();
-
573 }
-
574
-
575 // temBAD_SIGNATURE: Batch: invalid batch txn signature.
-
576 {
-
577 auto const seq = env.seq(alice);
-
578 auto const bobSeq = env.seq(bob);
-
579 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
580 auto jt = env.jtnofill(
-
581 batch::outer(alice, env.seq(alice), batchFee, tfAllOrNothing),
-
582 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
-
583 batch::inner(pay(bob, alice, XRP(5)), bobSeq));
-
584
-
585 Serializer msg;
-
586 serializeBatch(
-
587 msg, tfAllOrNothing, jt.stx->getBatchTransactionIDs());
-
588 auto const sig = xrpl::sign(bob.pk(), bob.sk(), msg.slice());
-
589 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName]
-
590 [sfAccount.jsonName] = bob.human();
+
430 env.set_parse_failure_expected(true);
+
431 try
+
432 {
+
433 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
434 tx1,
+
435 batch::inner(pay(alice, bob, XRP(2)), seq + 2));
+
436 fail("Expected parse_error for fractional fee");
+
437 }
+
438 catch (jtx::parse_error const&)
+
439 {
+
440 BEAST_EXPECT(true);
+
441 }
+
442 env.set_parse_failure_expected(false);
+
443 }
+
444
+
445 // temSEQ_AND_TICKET: Batch: inner txn cannot have both Sequence
+
446 // and TicketSequence.
+
447 {
+
448 auto const seq = env.seq(alice);
+
449 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
450 auto tx1 = batch::inner(pay(alice, bob, XRP(1)), 0, 1);
+
451 tx1[jss::Sequence] = seq + 1;
+
452 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
453 tx1,
+
454 batch::inner(pay(alice, bob, XRP(2)), seq + 2),
+
455 ter(temSEQ_AND_TICKET));
+
456 env.close();
+
457 }
+
458
+
459 // temSEQ_AND_TICKET: Batch: inner txn must have either Sequence or
+
460 // TicketSequence.
+
461 {
+
462 auto const seq = env.seq(alice);
+
463 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
464 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
465 batch::inner(pay(alice, bob, XRP(1)), 0),
+
466 batch::inner(pay(alice, bob, XRP(2)), seq + 2),
+
467 ter(temSEQ_AND_TICKET));
+
468 env.close();
+
469 }
+
470
+
471 // temREDUNDANT: Batch: duplicate sequence found:
+
472 {
+
473 auto const seq = env.seq(alice);
+
474 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
475 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
476 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
477 batch::inner(pay(alice, bob, XRP(2)), seq + 1),
+
478 ter(temREDUNDANT));
+
479 env.close();
+
480 }
+
481
+
482 // temREDUNDANT: Batch: duplicate ticket found:
+
483 {
+
484 auto const seq = env.seq(alice);
+
485 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
486 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
487 batch::inner(pay(alice, bob, XRP(1)), 0, seq + 1),
+
488 batch::inner(pay(alice, bob, XRP(2)), 0, seq + 1),
+
489 ter(temREDUNDANT));
+
490 env.close();
+
491 }
+
492
+
493 // temREDUNDANT: Batch: duplicate ticket & sequence found:
+
494 {
+
495 auto const seq = env.seq(alice);
+
496 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
497 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
498 batch::inner(pay(alice, bob, XRP(1)), 0, seq + 1),
+
499 batch::inner(pay(alice, bob, XRP(2)), seq + 1),
+
500 ter(temREDUNDANT));
+
501 env.close();
+
502 }
+
503
+
504 // DEFENSIVE: temARRAY_TOO_LARGE: Batch: signers array exceeds 8
+
505 // entries.
+
506 // ACTUAL: telENV_RPC_FAILED: isRawTransactionOkay()
+
507 {
+
508 auto const seq = env.seq(alice);
+
509 auto const batchFee = batch::calcBatchFee(env, 9, 2);
+
510 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
511 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
+
512 batch::inner(pay(alice, bob, XRP(5)), seq + 2),
+
513 batch::sig(
+
514 bob,
+
515 carol,
+
516 alice,
+
517 bob,
+
518 carol,
+
519 alice,
+
520 bob,
+
521 carol,
+
522 alice,
+
523 alice),
+
524 ter(telENV_RPC_FAILED));
+
525 env.close();
+
526 }
+
527
+
528 // temBAD_SIGNER: Batch: signer cannot be the outer account
+
529 {
+
530 auto const seq = env.seq(alice);
+
531 auto const batchFee = batch::calcBatchFee(env, 2, 2);
+
532 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
533 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
+
534 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
+
535 batch::sig(alice, bob),
+
536 ter(temBAD_SIGNER));
+
537 env.close();
+
538 }
+
539
+
540 // temREDUNDANT: Batch: duplicate signer found
+
541 {
+
542 auto const seq = env.seq(alice);
+
543 auto const batchFee = batch::calcBatchFee(env, 2, 2);
+
544 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
545 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
+
546 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
+
547 batch::sig(bob, bob),
+
548 ter(temREDUNDANT));
+
549 env.close();
+
550 }
+
551
+
552 // temBAD_SIGNER: Batch: no account signature for inner txn.
+
553 // Note: Extra signature by bob
+
554 {
+
555 auto const seq = env.seq(alice);
+
556 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
557 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
558 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
+
559 batch::inner(pay(alice, bob, XRP(5)), seq + 2),
+
560 batch::sig(bob),
+
561 ter(temBAD_SIGNER));
+
562 env.close();
+
563 }
+
564
+
565 // temBAD_SIGNER: Batch: no account signature for inner txn.
+
566 {
+
567 auto const seq = env.seq(alice);
+
568 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
569 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
570 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
+
571 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
+
572 batch::sig(carol),
+
573 ter(temBAD_SIGNER));
+
574 env.close();
+
575 }
+
576
+
577 // temBAD_SIGNATURE: Batch: invalid batch txn signature.
+
578 {
+
579 auto const seq = env.seq(alice);
+
580 auto const bobSeq = env.seq(bob);
+
581 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
582 auto jt = env.jtnofill(
+
583 batch::outer(alice, env.seq(alice), batchFee, tfAllOrNothing),
+
584 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
+
585 batch::inner(pay(bob, alice, XRP(5)), bobSeq));
+
586
+
587 Serializer msg;
+
588 serializeBatch(
+
589 msg, tfAllOrNothing, jt.stx->getBatchTransactionIDs());
+
590 auto const sig = xrpl::sign(bob.pk(), bob.sk(), msg.slice());
591 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName]
-
592 [sfSigningPubKey.jsonName] = strHex(alice.pk());
+
592 [sfAccount.jsonName] = bob.human();
593 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName]
-
594 [sfTxnSignature.jsonName] =
-
595 strHex(Slice{sig.data(), sig.size()});
-
596
-
597 env(jt.jv, ter(temBAD_SIGNATURE));
-
598 env.close();
-
599 }
-
600
-
601 // temBAD_SIGNER: Batch: invalid batch signers.
-
602 {
-
603 auto const seq = env.seq(alice);
-
604 auto const batchFee = batch::calcBatchFee(env, 2, 2);
-
605 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
606 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
-
607 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
-
608 batch::inner(pay(carol, alice, XRP(5)), env.seq(carol)),
-
609 batch::sig(bob),
-
610 ter(temBAD_SIGNER));
-
611 env.close();
-
612 }
-
613 }
+
594 [sfSigningPubKey.jsonName] = strHex(alice.pk());
+
595 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName]
+
596 [sfTxnSignature.jsonName] =
+
597 strHex(Slice{sig.data(), sig.size()});
+
598
+
599 env(jt.jv, ter(temBAD_SIGNATURE));
+
600 env.close();
+
601 }
+
602
+
603 // temBAD_SIGNER: Batch: invalid batch signers.
+
604 {
+
605 auto const seq = env.seq(alice);
+
606 auto const batchFee = batch::calcBatchFee(env, 2, 2);
+
607 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
608 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
+
609 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
+
610 batch::inner(pay(carol, alice, XRP(5)), env.seq(carol)),
+
611 batch::sig(bob),
+
612 ter(temBAD_SIGNER));
+
613 env.close();
+
614 }
+
615 }
-
614
-
615 void
-
- -
617 {
-
618 testcase("preclaim");
-
619
-
620 using namespace test::jtx;
-
621 using namespace std::literals;
-
622
-
623 //----------------------------------------------------------------------
-
624 // preclaim
-
625
-
626 test::jtx::Env env{*this, features};
+
616
+
617 void
+
+ +
619 {
+
620 testcase("preclaim");
+
621
+
622 using namespace test::jtx;
+
623 using namespace std::literals;
+
624
+
625 //----------------------------------------------------------------------
+
626 // preclaim
627
-
628 auto const alice = Account("alice");
-
629 auto const bob = Account("bob");
-
630 auto const carol = Account("carol");
-
631 auto const dave = Account("dave");
-
632 auto const elsa = Account("elsa");
-
633 auto const frank = Account("frank");
-
634 auto const phantom = Account("phantom");
-
635 env.memoize(phantom);
-
636
-
637 env.fund(XRP(10000), alice, bob, carol, dave, elsa, frank);
-
638 env.close();
-
639
-
640 //----------------------------------------------------------------------
-
641 // checkSign.checkSingleSign
-
642
-
643 // tefBAD_AUTH: Bob is not authorized to sign for Alice
-
644 {
-
645 auto const seq = env.seq(alice);
-
646 auto const batchFee = batch::calcBatchFee(env, 3, 2);
-
647 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
648 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
-
649 batch::inner(pay(alice, bob, XRP(20)), seq + 2),
-
650 sig(bob),
- -
652 env.close();
-
653 }
-
654
-
655 //----------------------------------------------------------------------
-
656 // checkBatchSign.checkMultiSign
-
657
-
658 // tefNOT_MULTI_SIGNING: SignersList not enabled
-
659 {
-
660 auto const seq = env.seq(alice);
-
661 auto const batchFee = batch::calcBatchFee(env, 3, 2);
-
662 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
663 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
-
664 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
-
665 batch::msig(bob, {dave, carol}),
- -
667 env.close();
-
668 }
-
669
-
670 env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
-
671 env.close();
-
672
-
673 env(signers(bob, 2, {{carol, 1}, {dave, 1}, {elsa, 1}}));
-
674 env.close();
-
675
-
676 // tefBAD_SIGNATURE: Account not in SignersList
-
677 {
-
678 auto const seq = env.seq(alice);
-
679 auto const batchFee = batch::calcBatchFee(env, 3, 2);
-
680 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
681 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
-
682 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
-
683 batch::msig(bob, {carol, frank}),
- -
685 env.close();
-
686 }
-
687
-
688 // tefBAD_SIGNATURE: Wrong publicKey type
-
689 {
-
690 auto const seq = env.seq(alice);
-
691 auto const batchFee = batch::calcBatchFee(env, 3, 2);
-
692 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
693 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
-
694 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
-
695 batch::msig(bob, {carol, Account("dave", KeyType::ed25519)}),
- -
697 env.close();
-
698 }
-
699
-
700 // tefMASTER_DISABLED: Master key disabled
-
701 {
-
702 env(regkey(elsa, frank));
-
703 env(fset(elsa, asfDisableMaster), sig(elsa));
-
704 auto const seq = env.seq(alice);
-
705 auto const batchFee = batch::calcBatchFee(env, 3, 2);
-
706 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
707 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
-
708 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
-
709 batch::msig(bob, {carol, elsa}),
- -
711 env.close();
-
712 }
-
713
-
714 // tefBAD_SIGNATURE: Signer does not exist
-
715 {
-
716 auto const seq = env.seq(alice);
-
717 auto const batchFee = batch::calcBatchFee(env, 3, 2);
-
718 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
719 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
-
720 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
-
721 batch::msig(bob, {carol, phantom}),
- -
723 env.close();
-
724 }
-
725
-
726 // tefBAD_SIGNATURE: Signer has not enabled RegularKey
-
727 {
-
728 auto const seq = env.seq(alice);
-
729 auto const batchFee = batch::calcBatchFee(env, 3, 2);
-
730 Account const davo{"davo", KeyType::ed25519};
-
731 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
732 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
-
733 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
-
734 batch::msig(bob, {carol, Reg{dave, davo}}),
- -
736 env.close();
-
737 }
-
738
-
739 // tefBAD_SIGNATURE: Wrong RegularKey Set
-
740 {
-
741 env(regkey(dave, frank));
-
742 auto const seq = env.seq(alice);
-
743 auto const batchFee = batch::calcBatchFee(env, 3, 2);
-
744 Account const davo{"davo", KeyType::ed25519};
-
745 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
746 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
-
747 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
-
748 batch::msig(bob, {carol, Reg{dave, davo}}),
-
749 ter(tefBAD_SIGNATURE));
-
750 env.close();
-
751 }
-
752
-
753 // tefBAD_QUORUM
-
754 {
-
755 auto const seq = env.seq(alice);
-
756 auto const batchFee = batch::calcBatchFee(env, 2, 2);
-
757 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
758 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
-
759 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
-
760 batch::msig(bob, {carol}),
-
761 ter(tefBAD_QUORUM));
-
762 env.close();
-
763 }
-
764
-
765 // tesSUCCESS: BatchSigners.Signers
-
766 {
-
767 auto const seq = env.seq(alice);
-
768 auto const batchFee = batch::calcBatchFee(env, 3, 2);
-
769 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
770 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
-
771 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
-
772 batch::msig(bob, {carol, dave}),
-
773 ter(tesSUCCESS));
-
774 env.close();
-
775 }
-
776
-
777 // tesSUCCESS: Multisign + BatchSigners.Signers
-
778 {
-
779 auto const seq = env.seq(alice);
-
780 auto const batchFee = batch::calcBatchFee(env, 4, 2);
-
781 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
782 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
-
783 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
-
784 batch::msig(bob, {carol, dave}),
-
785 msig(bob, carol),
-
786 ter(tesSUCCESS));
-
787 env.close();
-
788 }
-
789
-
790 //----------------------------------------------------------------------
-
791 // checkBatchSign.checkSingleSign
-
792
-
793 // tefBAD_AUTH: Inner Account is not signer
-
794 {
-
795 auto const ledSeq = env.current()->seq();
-
796 auto const seq = env.seq(alice);
-
797 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
798 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
799 batch::inner(pay(alice, phantom, XRP(1000)), seq + 1),
-
800 batch::inner(noop(phantom), ledSeq),
-
801 batch::sig(Reg{phantom, carol}),
-
802 ter(tefBAD_AUTH));
-
803 env.close();
-
804 }
-
805
-
806 // tefBAD_AUTH: Account is not signer
-
807 {
-
808 auto const ledSeq = env.current()->seq();
-
809 auto const seq = env.seq(alice);
-
810 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
811 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
812 batch::inner(pay(alice, bob, XRP(1000)), seq + 1),
-
813 batch::inner(noop(bob), ledSeq),
-
814 batch::sig(Reg{bob, carol}),
-
815 ter(tefBAD_AUTH));
-
816 env.close();
-
817 }
-
818
-
819 // tesSUCCESS: Signed With Regular Key
-
820 {
-
821 env(regkey(bob, carol));
-
822 auto const seq = env.seq(alice);
-
823 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
824 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
825 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
826 batch::inner(pay(bob, alice, XRP(2)), env.seq(bob)),
-
827 batch::sig(Reg{bob, carol}),
-
828 ter(tesSUCCESS));
-
829 env.close();
-
830 }
-
831
-
832 // tesSUCCESS: Signed With Master Key
-
833 {
-
834 auto const seq = env.seq(alice);
-
835 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
836 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
837 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
838 batch::inner(pay(bob, alice, XRP(2)), env.seq(bob)),
-
839 batch::sig(bob),
-
840 ter(tesSUCCESS));
-
841 env.close();
-
842 }
-
843
-
844 // tefMASTER_DISABLED: Signed With Master Key Disabled
-
845 {
-
846 env(regkey(bob, carol));
-
847 env(fset(bob, asfDisableMaster), sig(bob));
-
848 auto const seq = env.seq(alice);
-
849 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
850 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
851 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
852 batch::inner(pay(bob, alice, XRP(2)), env.seq(bob)),
-
853 batch::sig(bob),
-
854 ter(tefMASTER_DISABLED));
-
855 env.close();
-
856 }
-
857 }
+
628 test::jtx::Env env{*this, features};
+
629
+
630 auto const alice = Account("alice");
+
631 auto const bob = Account("bob");
+
632 auto const carol = Account("carol");
+
633 auto const dave = Account("dave");
+
634 auto const elsa = Account("elsa");
+
635 auto const frank = Account("frank");
+
636 auto const phantom = Account("phantom");
+
637 env.memoize(phantom);
+
638
+
639 env.fund(XRP(10000), alice, bob, carol, dave, elsa, frank);
+
640 env.close();
+
641
+
642 //----------------------------------------------------------------------
+
643 // checkSign.checkSingleSign
+
644
+
645 // tefBAD_AUTH: Bob is not authorized to sign for Alice
+
646 {
+
647 auto const seq = env.seq(alice);
+
648 auto const batchFee = batch::calcBatchFee(env, 3, 2);
+
649 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
650 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
+
651 batch::inner(pay(alice, bob, XRP(20)), seq + 2),
+
652 sig(bob),
+ +
654 env.close();
+
655 }
+
656
+
657 //----------------------------------------------------------------------
+
658 // checkBatchSign.checkMultiSign
+
659
+
660 // tefNOT_MULTI_SIGNING: SignersList not enabled
+
661 {
+
662 auto const seq = env.seq(alice);
+
663 auto const batchFee = batch::calcBatchFee(env, 3, 2);
+
664 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
665 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
+
666 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
+
667 batch::msig(bob, {dave, carol}),
+ +
669 env.close();
+
670 }
+
671
+
672 env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
+
673 env.close();
+
674
+
675 env(signers(bob, 2, {{carol, 1}, {dave, 1}, {elsa, 1}}));
+
676 env.close();
+
677
+
678 // tefBAD_SIGNATURE: Account not in SignersList
+
679 {
+
680 auto const seq = env.seq(alice);
+
681 auto const batchFee = batch::calcBatchFee(env, 3, 2);
+
682 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
683 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
+
684 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
+
685 batch::msig(bob, {carol, frank}),
+ +
687 env.close();
+
688 }
+
689
+
690 // tefBAD_SIGNATURE: Wrong publicKey type
+
691 {
+
692 auto const seq = env.seq(alice);
+
693 auto const batchFee = batch::calcBatchFee(env, 3, 2);
+
694 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
695 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
+
696 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
+
697 batch::msig(bob, {carol, Account("dave", KeyType::ed25519)}),
+ +
699 env.close();
+
700 }
+
701
+
702 // tefMASTER_DISABLED: Master key disabled
+
703 {
+
704 env(regkey(elsa, frank));
+
705 env(fset(elsa, asfDisableMaster), sig(elsa));
+
706 auto const seq = env.seq(alice);
+
707 auto const batchFee = batch::calcBatchFee(env, 3, 2);
+
708 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
709 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
+
710 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
+
711 batch::msig(bob, {carol, elsa}),
+ +
713 env.close();
+
714 }
+
715
+
716 // tefBAD_SIGNATURE: Signer does not exist
+
717 {
+
718 auto const seq = env.seq(alice);
+
719 auto const batchFee = batch::calcBatchFee(env, 3, 2);
+
720 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
721 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
+
722 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
+
723 batch::msig(bob, {carol, phantom}),
+ +
725 env.close();
+
726 }
+
727
+
728 // tefBAD_SIGNATURE: Signer has not enabled RegularKey
+
729 {
+
730 auto const seq = env.seq(alice);
+
731 auto const batchFee = batch::calcBatchFee(env, 3, 2);
+
732 Account const davo{"davo", KeyType::ed25519};
+
733 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
734 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
+
735 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
+
736 batch::msig(bob, {carol, Reg{dave, davo}}),
+ +
738 env.close();
+
739 }
+
740
+
741 // tefBAD_SIGNATURE: Wrong RegularKey Set
+
742 {
+
743 env(regkey(dave, frank));
+
744 auto const seq = env.seq(alice);
+
745 auto const batchFee = batch::calcBatchFee(env, 3, 2);
+
746 Account const davo{"davo", KeyType::ed25519};
+
747 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
748 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
+
749 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
+
750 batch::msig(bob, {carol, Reg{dave, davo}}),
+
751 ter(tefBAD_SIGNATURE));
+
752 env.close();
+
753 }
+
754
+
755 // tefBAD_QUORUM
+
756 {
+
757 auto const seq = env.seq(alice);
+
758 auto const batchFee = batch::calcBatchFee(env, 2, 2);
+
759 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
760 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
+
761 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
+
762 batch::msig(bob, {carol}),
+
763 ter(tefBAD_QUORUM));
+
764 env.close();
+
765 }
+
766
+
767 // tesSUCCESS: BatchSigners.Signers
+
768 {
+
769 auto const seq = env.seq(alice);
+
770 auto const batchFee = batch::calcBatchFee(env, 3, 2);
+
771 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
772 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
+
773 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
+
774 batch::msig(bob, {carol, dave}),
+
775 ter(tesSUCCESS));
+
776 env.close();
+
777 }
+
778
+
779 // tesSUCCESS: Multisign + BatchSigners.Signers
+
780 {
+
781 auto const seq = env.seq(alice);
+
782 auto const batchFee = batch::calcBatchFee(env, 4, 2);
+
783 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
784 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
+
785 batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
+
786 batch::msig(bob, {carol, dave}),
+
787 msig(bob, carol),
+
788 ter(tesSUCCESS));
+
789 env.close();
+
790 }
+
791
+
792 //----------------------------------------------------------------------
+
793 // checkBatchSign.checkSingleSign
+
794
+
795 // tefBAD_AUTH: Inner Account is not signer
+
796 {
+
797 auto const ledSeq = env.current()->seq();
+
798 auto const seq = env.seq(alice);
+
799 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
800 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
801 batch::inner(pay(alice, phantom, XRP(1000)), seq + 1),
+
802 batch::inner(noop(phantom), ledSeq),
+
803 batch::sig(Reg{phantom, carol}),
+
804 ter(tefBAD_AUTH));
+
805 env.close();
+
806 }
+
807
+
808 // tefBAD_AUTH: Account is not signer
+
809 {
+
810 auto const ledSeq = env.current()->seq();
+
811 auto const seq = env.seq(alice);
+
812 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
813 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
814 batch::inner(pay(alice, bob, XRP(1000)), seq + 1),
+
815 batch::inner(noop(bob), ledSeq),
+
816 batch::sig(Reg{bob, carol}),
+
817 ter(tefBAD_AUTH));
+
818 env.close();
+
819 }
+
820
+
821 // tesSUCCESS: Signed With Regular Key
+
822 {
+
823 env(regkey(bob, carol));
+
824 auto const seq = env.seq(alice);
+
825 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
826 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
827 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
828 batch::inner(pay(bob, alice, XRP(2)), env.seq(bob)),
+
829 batch::sig(Reg{bob, carol}),
+
830 ter(tesSUCCESS));
+
831 env.close();
+
832 }
+
833
+
834 // tesSUCCESS: Signed With Master Key
+
835 {
+
836 auto const seq = env.seq(alice);
+
837 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
838 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
839 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
840 batch::inner(pay(bob, alice, XRP(2)), env.seq(bob)),
+
841 batch::sig(bob),
+
842 ter(tesSUCCESS));
+
843 env.close();
+
844 }
+
845
+
846 // tefMASTER_DISABLED: Signed With Master Key Disabled
+
847 {
+
848 env(regkey(bob, carol));
+
849 env(fset(bob, asfDisableMaster), sig(bob));
+
850 auto const seq = env.seq(alice);
+
851 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
852 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
853 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
854 batch::inner(pay(bob, alice, XRP(2)), env.seq(bob)),
+
855 batch::sig(bob),
+
856 ter(tefMASTER_DISABLED));
+
857 env.close();
+
858 }
+
859 }
-
858
-
859 void
-
- -
861 {
-
862 testcase("bad raw txn");
-
863
-
864 using namespace test::jtx;
-
865 using namespace std::literals;
-
866
-
867 test::jtx::Env env{*this, features};
+
860
+
861 void
+
+ +
863 {
+
864 testcase("bad raw txn");
+
865
+
866 using namespace test::jtx;
+
867 using namespace std::literals;
868
-
869 auto const alice = Account("alice");
-
870 auto const bob = Account("bob");
-
871
-
872 env.fund(XRP(10000), alice, bob);
+
869 test::jtx::Env env{*this, features};
+
870
+
871 auto const alice = Account("alice");
+
872 auto const bob = Account("bob");
873
-
874 // Invalid: sfTransactionType
-
875 {
-
876 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
877 auto const seq = env.seq(alice);
-
878 auto tx1 = batch::inner(pay(alice, bob, XRP(10)), seq + 1);
-
879 tx1.removeMember(jss::TransactionType);
-
880 auto jt = env.jtnofill(
-
881 batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
882 tx1,
-
883 batch::inner(pay(alice, bob, XRP(10)), seq + 2));
-
884
-
885 env(jt.jv, batch::sig(bob), ter(telENV_RPC_FAILED));
-
886 env.close();
-
887 }
-
888
-
889 // Invalid: sfAccount
-
890 {
-
891 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
892 auto const seq = env.seq(alice);
-
893 auto tx1 = batch::inner(pay(alice, bob, XRP(10)), seq + 1);
-
894 tx1.removeMember(jss::Account);
-
895 auto jt = env.jtnofill(
-
896 batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
897 tx1,
-
898 batch::inner(pay(alice, bob, XRP(10)), seq + 2));
-
899
-
900 env(jt.jv, batch::sig(bob), ter(telENV_RPC_FAILED));
-
901 env.close();
-
902 }
-
903
-
904 // Invalid: sfSequence
-
905 {
-
906 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
907 auto const seq = env.seq(alice);
-
908 auto tx1 = batch::inner(pay(alice, bob, XRP(10)), seq + 1);
-
909 tx1.removeMember(jss::Sequence);
-
910 auto jt = env.jtnofill(
-
911 batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
912 tx1,
-
913 batch::inner(pay(alice, bob, XRP(10)), seq + 2));
-
914
-
915 env(jt.jv, batch::sig(bob), ter(telENV_RPC_FAILED));
-
916 env.close();
-
917 }
-
918
-
919 // Invalid: sfFee
-
920 {
-
921 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
922 auto const seq = env.seq(alice);
-
923 auto tx1 = batch::inner(pay(alice, bob, XRP(10)), seq + 1);
-
924 tx1.removeMember(jss::Fee);
-
925 auto jt = env.jtnofill(
-
926 batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
927 tx1,
-
928 batch::inner(pay(alice, bob, XRP(10)), seq + 2));
-
929
-
930 env(jt.jv, batch::sig(bob), ter(telENV_RPC_FAILED));
-
931 env.close();
-
932 }
-
933
-
934 // Invalid: sfSigningPubKey
-
935 {
-
936 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
937 auto const seq = env.seq(alice);
-
938 auto tx1 = batch::inner(pay(alice, bob, XRP(10)), seq + 1);
-
939 tx1.removeMember(jss::SigningPubKey);
-
940 auto jt = env.jtnofill(
-
941 batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
942 tx1,
-
943 batch::inner(pay(alice, bob, XRP(10)), seq + 2));
-
944
-
945 env(jt.jv, batch::sig(bob), ter(telENV_RPC_FAILED));
-
946 env.close();
-
947 }
-
948 }
+
874 env.fund(XRP(10000), alice, bob);
+
875
+
876 // Invalid: sfTransactionType
+
877 {
+
878 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
879 auto const seq = env.seq(alice);
+
880 auto tx1 = batch::inner(pay(alice, bob, XRP(10)), seq + 1);
+
881 tx1.removeMember(jss::TransactionType);
+
882 auto jt = env.jtnofill(
+
883 batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
884 tx1,
+
885 batch::inner(pay(alice, bob, XRP(10)), seq + 2));
+
886
+
887 env(jt.jv, batch::sig(bob), ter(telENV_RPC_FAILED));
+
888 env.close();
+
889 }
+
890
+
891 // Invalid: sfAccount
+
892 {
+
893 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
894 auto const seq = env.seq(alice);
+
895 auto tx1 = batch::inner(pay(alice, bob, XRP(10)), seq + 1);
+
896 tx1.removeMember(jss::Account);
+
897 auto jt = env.jtnofill(
+
898 batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
899 tx1,
+
900 batch::inner(pay(alice, bob, XRP(10)), seq + 2));
+
901
+
902 env(jt.jv, batch::sig(bob), ter(telENV_RPC_FAILED));
+
903 env.close();
+
904 }
+
905
+
906 // Invalid: sfSequence
+
907 {
+
908 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
909 auto const seq = env.seq(alice);
+
910 auto tx1 = batch::inner(pay(alice, bob, XRP(10)), seq + 1);
+
911 tx1.removeMember(jss::Sequence);
+
912 auto jt = env.jtnofill(
+
913 batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
914 tx1,
+
915 batch::inner(pay(alice, bob, XRP(10)), seq + 2));
+
916
+
917 env(jt.jv, batch::sig(bob), ter(telENV_RPC_FAILED));
+
918 env.close();
+
919 }
+
920
+
921 // Invalid: sfFee
+
922 {
+
923 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
924 auto const seq = env.seq(alice);
+
925 auto tx1 = batch::inner(pay(alice, bob, XRP(10)), seq + 1);
+
926 tx1.removeMember(jss::Fee);
+
927 auto jt = env.jtnofill(
+
928 batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
929 tx1,
+
930 batch::inner(pay(alice, bob, XRP(10)), seq + 2));
+
931
+
932 env(jt.jv, batch::sig(bob), ter(telENV_RPC_FAILED));
+
933 env.close();
+
934 }
+
935
+
936 // Invalid: sfSigningPubKey
+
937 {
+
938 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
939 auto const seq = env.seq(alice);
+
940 auto tx1 = batch::inner(pay(alice, bob, XRP(10)), seq + 1);
+
941 tx1.removeMember(jss::SigningPubKey);
+
942 auto jt = env.jtnofill(
+
943 batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
944 tx1,
+
945 batch::inner(pay(alice, bob, XRP(10)), seq + 2));
+
946
+
947 env(jt.jv, batch::sig(bob), ter(telENV_RPC_FAILED));
+
948 env.close();
+
949 }
+
950 }
-
949
-
950 void
-
- -
952 {
-
953 testcase("bad sequence");
-
954
-
955 using namespace test::jtx;
-
956 using namespace std::literals;
-
957
-
958 test::jtx::Env env{*this, features};
+
951
+
952 void
+
+ +
954 {
+
955 testcase("bad sequence");
+
956
+
957 using namespace test::jtx;
+
958 using namespace std::literals;
959
-
960 auto const alice = Account("alice");
-
961 auto const bob = Account("bob");
-
962 auto const gw = Account("gw");
-
963 auto const USD = gw["USD"];
-
964
-
965 env.fund(XRP(10000), alice, bob, gw);
-
966 env.close();
-
967 env.trust(USD(1000), alice, bob);
-
968 env(pay(gw, alice, USD(100)));
-
969 env(pay(gw, bob, USD(100)));
-
970 env.close();
-
971
-
972 env(noop(bob), ter(tesSUCCESS));
-
973 env.close();
-
974
-
975 // Invalid: Alice Sequence is a past sequence
-
976 {
-
977 auto const preAliceSeq = env.seq(alice);
-
978 auto const preAlice = env.balance(alice);
-
979 auto const preAliceUSD = env.balance(alice, USD.issue());
-
980 auto const preBobSeq = env.seq(bob);
-
981 auto const preBob = env.balance(bob);
-
982 auto const preBobUSD = env.balance(bob, USD.issue());
-
983
-
984 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
985 auto const [txIDs, batchID] = submitBatch(
-
986 env,
- -
988 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
-
989 batch::inner(pay(alice, bob, XRP(10)), preAliceSeq - 10),
-
990 batch::inner(pay(bob, alice, XRP(5)), preBobSeq),
-
991 batch::sig(bob));
-
992
-
993 env.close();
-
994 {
-
995 std::vector<TestLedgerData> testCases = {
-
996 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
997 };
-
998 validateClosedLedger(env, testCases);
-
999 }
-
1000
-
1001 env.close();
-
1002 {
-
1003 // next ledger is empty
-
1004 std::vector<TestLedgerData> testCases = {};
-
1005 validateClosedLedger(env, testCases);
-
1006 }
-
1007
-
1008 // Alice pays fee & Bob should not be affected.
-
1009 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
-
1010 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
-
1011 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
-
1012 BEAST_EXPECT(env.seq(bob) == preBobSeq);
-
1013 BEAST_EXPECT(env.balance(bob) == preBob);
-
1014 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
-
1015 }
-
1016
-
1017 // Invalid: Alice Sequence is a future sequence
-
1018 {
-
1019 auto const preAliceSeq = env.seq(alice);
-
1020 auto const preAlice = env.balance(alice);
-
1021 auto const preAliceUSD = env.balance(alice, USD.issue());
-
1022 auto const preBobSeq = env.seq(bob);
-
1023 auto const preBob = env.balance(bob);
-
1024 auto const preBobUSD = env.balance(bob, USD.issue());
-
1025
-
1026 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
1027 auto const [txIDs, batchID] = submitBatch(
-
1028 env,
-
1029 tesSUCCESS,
-
1030 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
-
1031 batch::inner(pay(alice, bob, XRP(10)), preAliceSeq + 10),
-
1032 batch::inner(pay(bob, alice, XRP(5)), preBobSeq),
-
1033 batch::sig(bob));
-
1034
-
1035 env.close();
-
1036 {
-
1037 std::vector<TestLedgerData> testCases = {
-
1038 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
1039 };
-
1040 validateClosedLedger(env, testCases);
-
1041 }
-
1042
-
1043 env.close();
-
1044 {
-
1045 // next ledger is empty
-
1046 std::vector<TestLedgerData> testCases = {};
-
1047 validateClosedLedger(env, testCases);
-
1048 }
-
1049
-
1050 // Alice pays fee & Bob should not be affected.
-
1051 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
-
1052 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
-
1053 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
-
1054 BEAST_EXPECT(env.seq(bob) == preBobSeq);
-
1055 BEAST_EXPECT(env.balance(bob) == preBob);
-
1056 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
-
1057 }
-
1058
-
1059 // Invalid: Bob Sequence is a past sequence
-
1060 {
-
1061 auto const preAliceSeq = env.seq(alice);
-
1062 auto const preAlice = env.balance(alice);
-
1063 auto const preAliceUSD = env.balance(alice, USD.issue());
-
1064 auto const preBobSeq = env.seq(bob);
-
1065 auto const preBob = env.balance(bob);
-
1066 auto const preBobUSD = env.balance(bob, USD.issue());
-
1067
-
1068 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
1069 auto const [txIDs, batchID] = submitBatch(
-
1070 env,
-
1071 tesSUCCESS,
-
1072 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
-
1073 batch::inner(pay(alice, bob, XRP(10)), preAliceSeq + 1),
-
1074 batch::inner(pay(bob, alice, XRP(5)), preBobSeq - 10),
-
1075 batch::sig(bob));
-
1076
-
1077 env.close();
-
1078 {
-
1079 std::vector<TestLedgerData> testCases = {
-
1080 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
1081 };
-
1082 validateClosedLedger(env, testCases);
-
1083 }
-
1084
-
1085 env.close();
-
1086 {
-
1087 // next ledger is empty
-
1088 std::vector<TestLedgerData> testCases = {};
-
1089 validateClosedLedger(env, testCases);
-
1090 }
-
1091
-
1092 // Alice pays fee & Bob should not be affected.
-
1093 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
-
1094 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
-
1095 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
-
1096 BEAST_EXPECT(env.seq(bob) == preBobSeq);
-
1097 BEAST_EXPECT(env.balance(bob) == preBob);
-
1098 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
-
1099 }
-
1100
-
1101 // Invalid: Bob Sequence is a future sequence
-
1102 {
-
1103 auto const preAliceSeq = env.seq(alice);
-
1104 auto const preAlice = env.balance(alice);
-
1105 auto const preAliceUSD = env.balance(alice, USD.issue());
-
1106 auto const preBobSeq = env.seq(bob);
-
1107 auto const preBob = env.balance(bob);
-
1108 auto const preBobUSD = env.balance(bob, USD.issue());
-
1109
-
1110 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
1111 auto const [txIDs, batchID] = submitBatch(
-
1112 env,
-
1113 tesSUCCESS,
-
1114 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
-
1115 batch::inner(pay(alice, bob, XRP(10)), preAliceSeq + 1),
-
1116 batch::inner(pay(bob, alice, XRP(5)), preBobSeq + 10),
-
1117 batch::sig(bob));
-
1118
-
1119 env.close();
-
1120 {
-
1121 std::vector<TestLedgerData> testCases = {
-
1122 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
1123 };
-
1124 validateClosedLedger(env, testCases);
-
1125 }
-
1126
-
1127 env.close();
-
1128 {
-
1129 // next ledger is empty
-
1130 std::vector<TestLedgerData> testCases = {};
-
1131 validateClosedLedger(env, testCases);
-
1132 }
-
1133
-
1134 // Alice pays fee & Bob should not be affected.
-
1135 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
-
1136 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
-
1137 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
-
1138 BEAST_EXPECT(env.seq(bob) == preBobSeq);
-
1139 BEAST_EXPECT(env.balance(bob) == preBob);
-
1140 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
-
1141 }
-
1142
-
1143 // Invalid: Outer and Inner Sequence are the same
-
1144 {
-
1145 auto const preAliceSeq = env.seq(alice);
-
1146 auto const preAlice = env.balance(alice);
-
1147 auto const preAliceUSD = env.balance(alice, USD.issue());
-
1148 auto const preBobSeq = env.seq(bob);
-
1149 auto const preBob = env.balance(bob);
-
1150 auto const preBobUSD = env.balance(bob, USD.issue());
-
1151
-
1152 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
1153 auto const [txIDs, batchID] = submitBatch(
-
1154 env,
-
1155 tesSUCCESS,
-
1156 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
-
1157 batch::inner(pay(alice, bob, XRP(10)), preAliceSeq),
-
1158 batch::inner(pay(bob, alice, XRP(5)), preBobSeq),
-
1159 batch::sig(bob));
-
1160
-
1161 env.close();
-
1162 {
-
1163 std::vector<TestLedgerData> testCases = {
-
1164 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
1165 };
-
1166 validateClosedLedger(env, testCases);
-
1167 }
-
1168
-
1169 env.close();
-
1170 {
-
1171 // next ledger is empty
-
1172 std::vector<TestLedgerData> testCases = {};
-
1173 validateClosedLedger(env, testCases);
-
1174 }
-
1175
-
1176 // Alice pays fee & Bob should not be affected.
-
1177 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
-
1178 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
-
1179 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
-
1180 BEAST_EXPECT(env.seq(bob) == preBobSeq);
-
1181 BEAST_EXPECT(env.balance(bob) == preBob);
-
1182 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
-
1183 }
-
1184 }
+
960 test::jtx::Env env{*this, features};
+
961
+
962 auto const alice = Account("alice");
+
963 auto const bob = Account("bob");
+
964 auto const gw = Account("gw");
+
965 auto const USD = gw["USD"];
+
966
+
967 env.fund(XRP(10000), alice, bob, gw);
+
968 env.close();
+
969 env.trust(USD(1000), alice, bob);
+
970 env(pay(gw, alice, USD(100)));
+
971 env(pay(gw, bob, USD(100)));
+
972 env.close();
+
973
+
974 env(noop(bob), ter(tesSUCCESS));
+
975 env.close();
+
976
+
977 // Invalid: Alice Sequence is a past sequence
+
978 {
+
979 auto const preAliceSeq = env.seq(alice);
+
980 auto const preAlice = env.balance(alice);
+
981 auto const preAliceUSD = env.balance(alice, USD.issue());
+
982 auto const preBobSeq = env.seq(bob);
+
983 auto const preBob = env.balance(bob);
+
984 auto const preBobUSD = env.balance(bob, USD.issue());
+
985
+
986 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
987 auto const [txIDs, batchID] = submitBatch(
+
988 env,
+ +
990 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
+
991 batch::inner(pay(alice, bob, XRP(10)), preAliceSeq - 10),
+
992 batch::inner(pay(bob, alice, XRP(5)), preBobSeq),
+
993 batch::sig(bob));
+
994
+
995 env.close();
+
996 {
+
997 std::vector<TestLedgerData> testCases = {
+
998 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
999 };
+
1000 validateClosedLedger(env, testCases);
+
1001 }
+
1002
+
1003 env.close();
+
1004 {
+
1005 // next ledger is empty
+
1006 std::vector<TestLedgerData> testCases = {};
+
1007 validateClosedLedger(env, testCases);
+
1008 }
+
1009
+
1010 // Alice pays fee & Bob should not be affected.
+
1011 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
+
1012 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
+
1013 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
+
1014 BEAST_EXPECT(env.seq(bob) == preBobSeq);
+
1015 BEAST_EXPECT(env.balance(bob) == preBob);
+
1016 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
+
1017 }
+
1018
+
1019 // Invalid: Alice Sequence is a future sequence
+
1020 {
+
1021 auto const preAliceSeq = env.seq(alice);
+
1022 auto const preAlice = env.balance(alice);
+
1023 auto const preAliceUSD = env.balance(alice, USD.issue());
+
1024 auto const preBobSeq = env.seq(bob);
+
1025 auto const preBob = env.balance(bob);
+
1026 auto const preBobUSD = env.balance(bob, USD.issue());
+
1027
+
1028 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
1029 auto const [txIDs, batchID] = submitBatch(
+
1030 env,
+
1031 tesSUCCESS,
+
1032 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
+
1033 batch::inner(pay(alice, bob, XRP(10)), preAliceSeq + 10),
+
1034 batch::inner(pay(bob, alice, XRP(5)), preBobSeq),
+
1035 batch::sig(bob));
+
1036
+
1037 env.close();
+
1038 {
+
1039 std::vector<TestLedgerData> testCases = {
+
1040 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
1041 };
+
1042 validateClosedLedger(env, testCases);
+
1043 }
+
1044
+
1045 env.close();
+
1046 {
+
1047 // next ledger is empty
+
1048 std::vector<TestLedgerData> testCases = {};
+
1049 validateClosedLedger(env, testCases);
+
1050 }
+
1051
+
1052 // Alice pays fee & Bob should not be affected.
+
1053 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
+
1054 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
+
1055 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
+
1056 BEAST_EXPECT(env.seq(bob) == preBobSeq);
+
1057 BEAST_EXPECT(env.balance(bob) == preBob);
+
1058 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
+
1059 }
+
1060
+
1061 // Invalid: Bob Sequence is a past sequence
+
1062 {
+
1063 auto const preAliceSeq = env.seq(alice);
+
1064 auto const preAlice = env.balance(alice);
+
1065 auto const preAliceUSD = env.balance(alice, USD.issue());
+
1066 auto const preBobSeq = env.seq(bob);
+
1067 auto const preBob = env.balance(bob);
+
1068 auto const preBobUSD = env.balance(bob, USD.issue());
+
1069
+
1070 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
1071 auto const [txIDs, batchID] = submitBatch(
+
1072 env,
+
1073 tesSUCCESS,
+
1074 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
+
1075 batch::inner(pay(alice, bob, XRP(10)), preAliceSeq + 1),
+
1076 batch::inner(pay(bob, alice, XRP(5)), preBobSeq - 10),
+
1077 batch::sig(bob));
+
1078
+
1079 env.close();
+
1080 {
+
1081 std::vector<TestLedgerData> testCases = {
+
1082 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
1083 };
+
1084 validateClosedLedger(env, testCases);
+
1085 }
+
1086
+
1087 env.close();
+
1088 {
+
1089 // next ledger is empty
+
1090 std::vector<TestLedgerData> testCases = {};
+
1091 validateClosedLedger(env, testCases);
+
1092 }
+
1093
+
1094 // Alice pays fee & Bob should not be affected.
+
1095 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
+
1096 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
+
1097 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
+
1098 BEAST_EXPECT(env.seq(bob) == preBobSeq);
+
1099 BEAST_EXPECT(env.balance(bob) == preBob);
+
1100 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
+
1101 }
+
1102
+
1103 // Invalid: Bob Sequence is a future sequence
+
1104 {
+
1105 auto const preAliceSeq = env.seq(alice);
+
1106 auto const preAlice = env.balance(alice);
+
1107 auto const preAliceUSD = env.balance(alice, USD.issue());
+
1108 auto const preBobSeq = env.seq(bob);
+
1109 auto const preBob = env.balance(bob);
+
1110 auto const preBobUSD = env.balance(bob, USD.issue());
+
1111
+
1112 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
1113 auto const [txIDs, batchID] = submitBatch(
+
1114 env,
+
1115 tesSUCCESS,
+
1116 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
+
1117 batch::inner(pay(alice, bob, XRP(10)), preAliceSeq + 1),
+
1118 batch::inner(pay(bob, alice, XRP(5)), preBobSeq + 10),
+
1119 batch::sig(bob));
+
1120
+
1121 env.close();
+
1122 {
+
1123 std::vector<TestLedgerData> testCases = {
+
1124 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
1125 };
+
1126 validateClosedLedger(env, testCases);
+
1127 }
+
1128
+
1129 env.close();
+
1130 {
+
1131 // next ledger is empty
+
1132 std::vector<TestLedgerData> testCases = {};
+
1133 validateClosedLedger(env, testCases);
+
1134 }
+
1135
+
1136 // Alice pays fee & Bob should not be affected.
+
1137 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
+
1138 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
+
1139 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
+
1140 BEAST_EXPECT(env.seq(bob) == preBobSeq);
+
1141 BEAST_EXPECT(env.balance(bob) == preBob);
+
1142 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
+
1143 }
+
1144
+
1145 // Invalid: Outer and Inner Sequence are the same
+
1146 {
+
1147 auto const preAliceSeq = env.seq(alice);
+
1148 auto const preAlice = env.balance(alice);
+
1149 auto const preAliceUSD = env.balance(alice, USD.issue());
+
1150 auto const preBobSeq = env.seq(bob);
+
1151 auto const preBob = env.balance(bob);
+
1152 auto const preBobUSD = env.balance(bob, USD.issue());
+
1153
+
1154 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
1155 auto const [txIDs, batchID] = submitBatch(
+
1156 env,
+
1157 tesSUCCESS,
+
1158 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
+
1159 batch::inner(pay(alice, bob, XRP(10)), preAliceSeq),
+
1160 batch::inner(pay(bob, alice, XRP(5)), preBobSeq),
+
1161 batch::sig(bob));
+
1162
+
1163 env.close();
+
1164 {
+
1165 std::vector<TestLedgerData> testCases = {
+
1166 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
1167 };
+
1168 validateClosedLedger(env, testCases);
+
1169 }
+
1170
+
1171 env.close();
+
1172 {
+
1173 // next ledger is empty
+
1174 std::vector<TestLedgerData> testCases = {};
+
1175 validateClosedLedger(env, testCases);
+
1176 }
+
1177
+
1178 // Alice pays fee & Bob should not be affected.
+
1179 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
+
1180 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
+
1181 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
+
1182 BEAST_EXPECT(env.seq(bob) == preBobSeq);
+
1183 BEAST_EXPECT(env.balance(bob) == preBob);
+
1184 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
+
1185 }
+
1186 }
-
1185
-
1186 void
-
- -
1188 {
-
1189 testcase("bad outer fee");
-
1190
-
1191 using namespace test::jtx;
-
1192 using namespace std::literals;
-
1193
-
1194 // Bad Fee Without Signer
-
1195 {
-
1196 test::jtx::Env env{*this, features};
-
1197
-
1198 auto const alice = Account("alice");
-
1199 auto const bob = Account("bob");
-
1200 env.fund(XRP(10000), alice, bob);
-
1201 env.close();
-
1202
-
1203 env(noop(bob), ter(tesSUCCESS));
-
1204 env.close();
-
1205
-
1206 // Bad Fee: Should be batch::calcBatchFee(env, 0, 2)
-
1207 auto const batchFee = batch::calcBatchFee(env, 0, 1);
-
1208 auto const aliceSeq = env.seq(alice);
-
1209 env(batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
-
1210 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1),
-
1211 batch::inner(pay(alice, bob, XRP(15)), aliceSeq + 2),
- -
1213 env.close();
-
1214 }
-
1215
-
1216 // Bad Fee With MultiSign
-
1217 {
-
1218 test::jtx::Env env{*this, features};
-
1219
-
1220 auto const alice = Account("alice");
-
1221 auto const bob = Account("bob");
-
1222 auto const carol = Account("carol");
-
1223 env.fund(XRP(10000), alice, bob, carol);
-
1224 env.close();
-
1225
-
1226 env(noop(bob), ter(tesSUCCESS));
-
1227 env.close();
-
1228
-
1229 env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
-
1230 env.close();
-
1231
-
1232 // Bad Fee: Should be batch::calcBatchFee(env, 2, 2)
-
1233 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
1234 auto const aliceSeq = env.seq(alice);
-
1235 env(batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
-
1236 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1),
-
1237 batch::inner(pay(alice, bob, XRP(15)), aliceSeq + 2),
-
1238 msig(bob, carol),
- -
1240 env.close();
-
1241 }
-
1242
-
1243 // Bad Fee With MultiSign + BatchSigners
-
1244 {
-
1245 test::jtx::Env env{*this, features};
-
1246
-
1247 auto const alice = Account("alice");
-
1248 auto const bob = Account("bob");
-
1249 auto const carol = Account("carol");
-
1250 env.fund(XRP(10000), alice, bob, carol);
-
1251 env.close();
-
1252
-
1253 env(noop(bob), ter(tesSUCCESS));
-
1254 env.close();
-
1255
-
1256 env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
-
1257 env.close();
-
1258
-
1259 // Bad Fee: Should be batch::calcBatchFee(env, 3, 2)
-
1260 auto const batchFee = batch::calcBatchFee(env, 2, 2);
-
1261 auto const aliceSeq = env.seq(alice);
-
1262 auto const bobSeq = env.seq(bob);
-
1263 env(batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
-
1264 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1),
-
1265 batch::inner(pay(bob, alice, XRP(5)), bobSeq),
-
1266 batch::sig(bob),
-
1267 msig(bob, carol),
- -
1269 env.close();
-
1270 }
-
1271
-
1272 // Bad Fee With MultiSign + BatchSigners.Signers
-
1273 {
-
1274 test::jtx::Env env{*this, features};
-
1275
-
1276 auto const alice = Account("alice");
-
1277 auto const bob = Account("bob");
-
1278 auto const carol = Account("carol");
-
1279 env.fund(XRP(10000), alice, bob, carol);
-
1280 env.close();
-
1281
-
1282 env(noop(bob), ter(tesSUCCESS));
-
1283 env.close();
-
1284
-
1285 env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
-
1286 env.close();
-
1287
-
1288 env(signers(bob, 2, {{alice, 1}, {carol, 1}}));
-
1289 env.close();
-
1290
-
1291 // Bad Fee: Should be batch::calcBatchFee(env, 4, 2)
-
1292 auto const batchFee = batch::calcBatchFee(env, 3, 2);
-
1293 auto const aliceSeq = env.seq(alice);
-
1294 auto const bobSeq = env.seq(bob);
-
1295 env(batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
-
1296 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1),
-
1297 batch::inner(pay(bob, alice, XRP(5)), bobSeq),
-
1298 batch::msig(bob, {alice, carol}),
-
1299 msig(bob, carol),
- -
1301 env.close();
-
1302 }
-
1303
-
1304 // Bad Fee With BatchSigners
-
1305 {
-
1306 test::jtx::Env env{*this, features};
-
1307
-
1308 auto const alice = Account("alice");
-
1309 auto const bob = Account("bob");
-
1310 env.fund(XRP(10000), alice, bob);
-
1311 env.close();
-
1312
-
1313 env(noop(bob), ter(tesSUCCESS));
-
1314 env.close();
-
1315
-
1316 // Bad Fee: Should be batch::calcBatchFee(env, 1, 2)
-
1317 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
1318 auto const aliceSeq = env.seq(alice);
-
1319 auto const bobSeq = env.seq(bob);
-
1320 env(batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
-
1321 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1),
-
1322 batch::inner(pay(bob, alice, XRP(5)), bobSeq),
-
1323 batch::sig(bob),
- -
1325 env.close();
-
1326 }
-
1327
-
1328 // Bad Fee Dynamic Fee Calculation
-
1329 {
-
1330 test::jtx::Env env{*this, features};
-
1331
-
1332 auto const alice = Account("alice");
-
1333 auto const bob = Account("bob");
-
1334 auto const gw = Account("gw");
-
1335 auto const USD = gw["USD"];
-
1336
-
1337 env.fund(XRP(10000), alice, bob, gw);
-
1338 env.close();
-
1339 auto const ammCreate =
-
1340 [&alice](STAmount const& amount, STAmount const& amount2) {
-
1341 Json::Value jv;
-
1342 jv[jss::Account] = alice.human();
-
1343 jv[jss::Amount] = amount.getJson(JsonOptions::none);
-
1344 jv[jss::Amount2] = amount2.getJson(JsonOptions::none);
-
1345 jv[jss::TradingFee] = 0;
-
1346 jv[jss::TransactionType] = jss::AMMCreate;
-
1347 return jv;
-
1348 };
-
1349
-
1350 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
1351 auto const seq = env.seq(alice);
-
1352 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
1353 batch::inner(ammCreate(XRP(10), USD(10)), seq + 1),
-
1354 batch::inner(pay(alice, bob, XRP(10)), seq + 2),
- -
1356 env.close();
-
1357 }
-
1358 }
+
1187
+
1188 void
+
+ +
1190 {
+
1191 testcase("bad outer fee");
+
1192
+
1193 using namespace test::jtx;
+
1194 using namespace std::literals;
+
1195
+
1196 // Bad Fee Without Signer
+
1197 {
+
1198 test::jtx::Env env{*this, features};
+
1199
+
1200 auto const alice = Account("alice");
+
1201 auto const bob = Account("bob");
+
1202 env.fund(XRP(10000), alice, bob);
+
1203 env.close();
+
1204
+
1205 env(noop(bob), ter(tesSUCCESS));
+
1206 env.close();
+
1207
+
1208 // Bad Fee: Should be batch::calcBatchFee(env, 0, 2)
+
1209 auto const batchFee = batch::calcBatchFee(env, 0, 1);
+
1210 auto const aliceSeq = env.seq(alice);
+
1211 env(batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
+
1212 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1),
+
1213 batch::inner(pay(alice, bob, XRP(15)), aliceSeq + 2),
+ +
1215 env.close();
+
1216 }
+
1217
+
1218 // Bad Fee With MultiSign
+
1219 {
+
1220 test::jtx::Env env{*this, features};
+
1221
+
1222 auto const alice = Account("alice");
+
1223 auto const bob = Account("bob");
+
1224 auto const carol = Account("carol");
+
1225 env.fund(XRP(10000), alice, bob, carol);
+
1226 env.close();
+
1227
+
1228 env(noop(bob), ter(tesSUCCESS));
+
1229 env.close();
+
1230
+
1231 env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
+
1232 env.close();
+
1233
+
1234 // Bad Fee: Should be batch::calcBatchFee(env, 2, 2)
+
1235 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
1236 auto const aliceSeq = env.seq(alice);
+
1237 env(batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
+
1238 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1),
+
1239 batch::inner(pay(alice, bob, XRP(15)), aliceSeq + 2),
+
1240 msig(bob, carol),
+ +
1242 env.close();
+
1243 }
+
1244
+
1245 // Bad Fee With MultiSign + BatchSigners
+
1246 {
+
1247 test::jtx::Env env{*this, features};
+
1248
+
1249 auto const alice = Account("alice");
+
1250 auto const bob = Account("bob");
+
1251 auto const carol = Account("carol");
+
1252 env.fund(XRP(10000), alice, bob, carol);
+
1253 env.close();
+
1254
+
1255 env(noop(bob), ter(tesSUCCESS));
+
1256 env.close();
+
1257
+
1258 env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
+
1259 env.close();
+
1260
+
1261 // Bad Fee: Should be batch::calcBatchFee(env, 3, 2)
+
1262 auto const batchFee = batch::calcBatchFee(env, 2, 2);
+
1263 auto const aliceSeq = env.seq(alice);
+
1264 auto const bobSeq = env.seq(bob);
+
1265 env(batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
+
1266 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1),
+
1267 batch::inner(pay(bob, alice, XRP(5)), bobSeq),
+
1268 batch::sig(bob),
+
1269 msig(bob, carol),
+ +
1271 env.close();
+
1272 }
+
1273
+
1274 // Bad Fee With MultiSign + BatchSigners.Signers
+
1275 {
+
1276 test::jtx::Env env{*this, features};
+
1277
+
1278 auto const alice = Account("alice");
+
1279 auto const bob = Account("bob");
+
1280 auto const carol = Account("carol");
+
1281 env.fund(XRP(10000), alice, bob, carol);
+
1282 env.close();
+
1283
+
1284 env(noop(bob), ter(tesSUCCESS));
+
1285 env.close();
+
1286
+
1287 env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
+
1288 env.close();
+
1289
+
1290 env(signers(bob, 2, {{alice, 1}, {carol, 1}}));
+
1291 env.close();
+
1292
+
1293 // Bad Fee: Should be batch::calcBatchFee(env, 4, 2)
+
1294 auto const batchFee = batch::calcBatchFee(env, 3, 2);
+
1295 auto const aliceSeq = env.seq(alice);
+
1296 auto const bobSeq = env.seq(bob);
+
1297 env(batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
+
1298 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1),
+
1299 batch::inner(pay(bob, alice, XRP(5)), bobSeq),
+
1300 batch::msig(bob, {alice, carol}),
+
1301 msig(bob, carol),
+ +
1303 env.close();
+
1304 }
+
1305
+
1306 // Bad Fee With BatchSigners
+
1307 {
+
1308 test::jtx::Env env{*this, features};
+
1309
+
1310 auto const alice = Account("alice");
+
1311 auto const bob = Account("bob");
+
1312 env.fund(XRP(10000), alice, bob);
+
1313 env.close();
+
1314
+
1315 env(noop(bob), ter(tesSUCCESS));
+
1316 env.close();
+
1317
+
1318 // Bad Fee: Should be batch::calcBatchFee(env, 1, 2)
+
1319 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
1320 auto const aliceSeq = env.seq(alice);
+
1321 auto const bobSeq = env.seq(bob);
+
1322 env(batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
+
1323 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1),
+
1324 batch::inner(pay(bob, alice, XRP(5)), bobSeq),
+
1325 batch::sig(bob),
+ +
1327 env.close();
+
1328 }
+
1329
+
1330 // Bad Fee Dynamic Fee Calculation
+
1331 {
+
1332 test::jtx::Env env{*this, features};
+
1333
+
1334 auto const alice = Account("alice");
+
1335 auto const bob = Account("bob");
+
1336 auto const gw = Account("gw");
+
1337 auto const USD = gw["USD"];
+
1338
+
1339 env.fund(XRP(10000), alice, bob, gw);
+
1340 env.close();
+
1341 auto const ammCreate =
+
1342 [&alice](STAmount const& amount, STAmount const& amount2) {
+
1343 Json::Value jv;
+
1344 jv[jss::Account] = alice.human();
+
1345 jv[jss::Amount] = amount.getJson(JsonOptions::none);
+
1346 jv[jss::Amount2] = amount2.getJson(JsonOptions::none);
+
1347 jv[jss::TradingFee] = 0;
+
1348 jv[jss::TransactionType] = jss::AMMCreate;
+
1349 return jv;
+
1350 };
+
1351
+
1352 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
1353 auto const seq = env.seq(alice);
+
1354 env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
1355 batch::inner(ammCreate(XRP(10), USD(10)), seq + 1),
+
1356 batch::inner(pay(alice, bob, XRP(10)), seq + 2),
+ +
1358 env.close();
+
1359 }
+
1360 }
-
1359
-
1360 void
-
- -
1362 {
-
1363 testcase("calculate base fee");
-
1364
-
1365 using namespace test::jtx;
-
1366 using namespace std::literals;
-
1367
-
1368 // telENV_RPC_FAILED: Batch: txns array exceeds 8 entries.
-
1369 {
-
1370 test::jtx::Env env{*this, features};
-
1371
-
1372 auto const alice = Account("alice");
-
1373 auto const bob = Account("bob");
-
1374 env.fund(XRP(10000), alice, bob);
-
1375 env.close();
-
1376
-
1377 auto const batchFee = batch::calcBatchFee(env, 0, 9);
-
1378 auto const aliceSeq = env.seq(alice);
-
1379 env(batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
-
1380 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
-
1381 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
+
1361
+
1362 void
+
+ +
1364 {
+
1365 testcase("calculate base fee");
+
1366
+
1367 using namespace test::jtx;
+
1368 using namespace std::literals;
+
1369
+
1370 // telENV_RPC_FAILED: Batch: txns array exceeds 8 entries.
+
1371 {
+
1372 test::jtx::Env env{*this, features};
+
1373
+
1374 auto const alice = Account("alice");
+
1375 auto const bob = Account("bob");
+
1376 env.fund(XRP(10000), alice, bob);
+
1377 env.close();
+
1378
+
1379 auto const batchFee = batch::calcBatchFee(env, 0, 9);
+
1380 auto const aliceSeq = env.seq(alice);
+
1381 env(batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1382 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
1383 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
1384 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
@@ -1503,3181 +1503,3183 @@ $(document).ready(function() { init_codefold(0); });
1386 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
1387 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
1388 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
- -
1390 env.close();
-
1391 }
-
1392
-
1393 // temARRAY_TOO_LARGE: Batch: txns array exceeds 8 entries.
-
1394 {
-
1395 test::jtx::Env env{*this, features};
-
1396
-
1397 auto const alice = Account("alice");
-
1398 auto const bob = Account("bob");
-
1399 env.fund(XRP(10000), alice, bob);
-
1400 env.close();
-
1401
-
1402 auto const batchFee = batch::calcBatchFee(env, 0, 9);
-
1403 auto const aliceSeq = env.seq(alice);
-
1404 auto jt = env.jtnofill(
-
1405 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
-
1406 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
-
1407 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
+
1389 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
+
1390 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
+ +
1392 env.close();
+
1393 }
+
1394
+
1395 // temARRAY_TOO_LARGE: Batch: txns array exceeds 8 entries.
+
1396 {
+
1397 test::jtx::Env env{*this, features};
+
1398
+
1399 auto const alice = Account("alice");
+
1400 auto const bob = Account("bob");
+
1401 env.fund(XRP(10000), alice, bob);
+
1402 env.close();
+
1403
+
1404 auto const batchFee = batch::calcBatchFee(env, 0, 9);
+
1405 auto const aliceSeq = env.seq(alice);
+
1406 auto jt = env.jtnofill(
+
1407 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1408 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
1409 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
1410 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
1411 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
1412 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
1413 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
-
1414 batch::inner(pay(alice, bob, XRP(1)), aliceSeq));
-
1415
-
1416 env.app().openLedger().modify(
-
1417 [&](OpenView& view, beast::Journal j) {
-
1418 auto const result =
-
1419 xrpl::apply(env.app(), view, *jt.stx, tapNONE, j);
-
1420 BEAST_EXPECT(
-
1421 !result.applied && result.ter == temARRAY_TOO_LARGE);
-
1422 return result.applied;
-
1423 });
-
1424 }
-
1425
-
1426 // telENV_RPC_FAILED: Batch: signers array exceeds 8 entries.
-
1427 {
-
1428 test::jtx::Env env{*this, features};
-
1429
-
1430 auto const alice = Account("alice");
-
1431 auto const bob = Account("bob");
-
1432 env.fund(XRP(10000), alice, bob);
-
1433 env.close();
-
1434
-
1435 auto const aliceSeq = env.seq(alice);
-
1436 auto const batchFee = batch::calcBatchFee(env, 9, 2);
-
1437 env(batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
-
1438 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1),
-
1439 batch::inner(pay(alice, bob, XRP(5)), aliceSeq + 2),
-
1440 batch::sig(bob, bob, bob, bob, bob, bob, bob, bob, bob, bob),
- -
1442 env.close();
-
1443 }
-
1444
-
1445 // temARRAY_TOO_LARGE: Batch: signers array exceeds 8 entries.
-
1446 {
-
1447 test::jtx::Env env{*this, features};
-
1448
-
1449 auto const alice = Account("alice");
-
1450 auto const bob = Account("bob");
-
1451 env.fund(XRP(10000), alice, bob);
-
1452 env.close();
-
1453
-
1454 auto const batchFee = batch::calcBatchFee(env, 0, 9);
-
1455 auto const aliceSeq = env.seq(alice);
-
1456 auto jt = env.jtnofill(
-
1457 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
-
1458 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1),
-
1459 batch::inner(pay(alice, bob, XRP(5)), aliceSeq + 2),
-
1460 batch::sig(bob, bob, bob, bob, bob, bob, bob, bob, bob, bob));
-
1461
-
1462 env.app().openLedger().modify(
-
1463 [&](OpenView& view, beast::Journal j) {
-
1464 auto const result =
-
1465 xrpl::apply(env.app(), view, *jt.stx, tapNONE, j);
-
1466 BEAST_EXPECT(
-
1467 !result.applied && result.ter == temARRAY_TOO_LARGE);
-
1468 return result.applied;
-
1469 });
-
1470 }
-
1471 }
+
1414 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
+
1415 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
+
1416 batch::inner(pay(alice, bob, XRP(1)), aliceSeq));
+
1417
+
1418 env.app().openLedger().modify(
+
1419 [&](OpenView& view, beast::Journal j) {
+
1420 auto const result =
+
1421 xrpl::apply(env.app(), view, *jt.stx, tapNONE, j);
+
1422 BEAST_EXPECT(
+
1423 !result.applied && result.ter == temARRAY_TOO_LARGE);
+
1424 return result.applied;
+
1425 });
+
1426 }
+
1427
+
1428 // telENV_RPC_FAILED: Batch: signers array exceeds 8 entries.
+
1429 {
+
1430 test::jtx::Env env{*this, features};
+
1431
+
1432 auto const alice = Account("alice");
+
1433 auto const bob = Account("bob");
+
1434 env.fund(XRP(10000), alice, bob);
+
1435 env.close();
+
1436
+
1437 auto const aliceSeq = env.seq(alice);
+
1438 auto const batchFee = batch::calcBatchFee(env, 9, 2);
+
1439 env(batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
+
1440 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1),
+
1441 batch::inner(pay(alice, bob, XRP(5)), aliceSeq + 2),
+
1442 batch::sig(bob, bob, bob, bob, bob, bob, bob, bob, bob, bob),
+ +
1444 env.close();
+
1445 }
+
1446
+
1447 // temARRAY_TOO_LARGE: Batch: signers array exceeds 8 entries.
+
1448 {
+
1449 test::jtx::Env env{*this, features};
+
1450
+
1451 auto const alice = Account("alice");
+
1452 auto const bob = Account("bob");
+
1453 env.fund(XRP(10000), alice, bob);
+
1454 env.close();
+
1455
+
1456 auto const batchFee = batch::calcBatchFee(env, 0, 9);
+
1457 auto const aliceSeq = env.seq(alice);
+
1458 auto jt = env.jtnofill(
+
1459 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
+
1460 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1),
+
1461 batch::inner(pay(alice, bob, XRP(5)), aliceSeq + 2),
+
1462 batch::sig(bob, bob, bob, bob, bob, bob, bob, bob, bob, bob));
+
1463
+
1464 env.app().openLedger().modify(
+
1465 [&](OpenView& view, beast::Journal j) {
+
1466 auto const result =
+
1467 xrpl::apply(env.app(), view, *jt.stx, tapNONE, j);
+
1468 BEAST_EXPECT(
+
1469 !result.applied && result.ter == temARRAY_TOO_LARGE);
+
1470 return result.applied;
+
1471 });
+
1472 }
+
1473 }
-
1472
-
1473 void
-
- -
1475 {
-
1476 testcase("all or nothing");
-
1477
-
1478 using namespace test::jtx;
-
1479 using namespace std::literals;
-
1480
-
1481 test::jtx::Env env{*this, features};
+
1474
+
1475 void
+
+ +
1477 {
+
1478 testcase("all or nothing");
+
1479
+
1480 using namespace test::jtx;
+
1481 using namespace std::literals;
1482
-
1483 auto const alice = Account("alice");
-
1484 auto const bob = Account("bob");
-
1485 auto const gw = Account("gw");
-
1486 auto const USD = gw["USD"];
-
1487 env.fund(XRP(10000), alice, bob, gw);
-
1488 env.close();
-
1489
-
1490 // all
-
1491 {
-
1492 auto const preAlice = env.balance(alice);
-
1493 auto const preBob = env.balance(bob);
-
1494
-
1495 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
1496 auto const seq = env.seq(alice);
-
1497 auto const [txIDs, batchID] = submitBatch(
-
1498 env,
-
1499 tesSUCCESS,
-
1500 batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
1501 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
1502 batch::inner(pay(alice, bob, XRP(2)), seq + 2));
-
1503 env.close();
-
1504
-
1505 std::vector<TestLedgerData> testCases = {
-
1506 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
1507 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
1508 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
1509 };
-
1510 validateClosedLedger(env, testCases);
-
1511
-
1512 // Alice consumes sequences (# of txns)
-
1513 BEAST_EXPECT(env.seq(alice) == seq + 3);
-
1514
-
1515 // Alice pays XRP & Fee; Bob receives XRP
-
1516 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(3) - batchFee);
-
1517 BEAST_EXPECT(env.balance(bob) == preBob + XRP(3));
-
1518 }
-
1519
-
1520 // tec failure
-
1521 {
-
1522 auto const preAlice = env.balance(alice);
-
1523 auto const preBob = env.balance(bob);
-
1524
-
1525 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
1526 auto const seq = env.seq(alice);
-
1527
-
1528 auto const [txIDs, batchID] = submitBatch(
-
1529 env,
-
1530 tesSUCCESS,
-
1531 batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
1532 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
1533 // tecUNFUNDED_PAYMENT: alice does not have enough XRP
-
1534 batch::inner(pay(alice, bob, XRP(9999)), seq + 2));
-
1535 env.close();
-
1536
-
1537 std::vector<TestLedgerData> testCases = {
-
1538 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
1539 };
-
1540 validateClosedLedger(env, testCases);
-
1541
-
1542 // Alice consumes sequence
-
1543 BEAST_EXPECT(env.seq(alice) == seq + 1);
-
1544
-
1545 // Alice pays Fee; Bob should not be affected
-
1546 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
-
1547 BEAST_EXPECT(env.balance(bob) == preBob);
-
1548 }
-
1549
-
1550 // tef failure
-
1551 {
-
1552 auto const preAlice = env.balance(alice);
-
1553 auto const preBob = env.balance(bob);
-
1554
-
1555 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
1556 auto const seq = env.seq(alice);
-
1557 auto const [txIDs, batchID] = submitBatch(
-
1558 env,
-
1559 tesSUCCESS,
-
1560 batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
1561 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
1562 // tefNO_AUTH_REQUIRED: trustline auth is not required
-
1563 batch::inner(trust(alice, USD(1000), tfSetfAuth), seq + 2));
-
1564 env.close();
-
1565
-
1566 std::vector<TestLedgerData> testCases = {
-
1567 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
1568 };
-
1569 validateClosedLedger(env, testCases);
-
1570
-
1571 // Alice consumes sequence
-
1572 BEAST_EXPECT(env.seq(alice) == seq + 1);
-
1573
-
1574 // Alice pays Fee; Bob should not be affected
-
1575 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
-
1576 BEAST_EXPECT(env.balance(bob) == preBob);
-
1577 }
-
1578
-
1579 // ter failure
-
1580 {
-
1581 auto const preAlice = env.balance(alice);
-
1582 auto const preBob = env.balance(bob);
-
1583
-
1584 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
1585 auto const seq = env.seq(alice);
-
1586 auto const [txIDs, batchID] = submitBatch(
-
1587 env,
-
1588 tesSUCCESS,
-
1589 batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
1590 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
1591 // terPRE_TICKET: ticket does not exist
-
1592 batch::inner(trust(alice, USD(1000), tfSetfAuth), 0, seq + 2));
-
1593 env.close();
-
1594
-
1595 std::vector<TestLedgerData> testCases = {
-
1596 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
1597 };
-
1598 validateClosedLedger(env, testCases);
-
1599
-
1600 // Alice consumes sequence
-
1601 BEAST_EXPECT(env.seq(alice) == seq + 1);
-
1602
-
1603 // Alice pays Fee; Bob should not be affected
-
1604 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
-
1605 BEAST_EXPECT(env.balance(bob) == preBob);
-
1606 }
-
1607 }
+
1483 test::jtx::Env env{*this, features};
+
1484
+
1485 auto const alice = Account("alice");
+
1486 auto const bob = Account("bob");
+
1487 auto const gw = Account("gw");
+
1488 auto const USD = gw["USD"];
+
1489 env.fund(XRP(10000), alice, bob, gw);
+
1490 env.close();
+
1491
+
1492 // all
+
1493 {
+
1494 auto const preAlice = env.balance(alice);
+
1495 auto const preBob = env.balance(bob);
+
1496
+
1497 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
1498 auto const seq = env.seq(alice);
+
1499 auto const [txIDs, batchID] = submitBatch(
+
1500 env,
+
1501 tesSUCCESS,
+
1502 batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
1503 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
1504 batch::inner(pay(alice, bob, XRP(2)), seq + 2));
+
1505 env.close();
+
1506
+
1507 std::vector<TestLedgerData> testCases = {
+
1508 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
1509 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
1510 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
1511 };
+
1512 validateClosedLedger(env, testCases);
+
1513
+
1514 // Alice consumes sequences (# of txns)
+
1515 BEAST_EXPECT(env.seq(alice) == seq + 3);
+
1516
+
1517 // Alice pays XRP & Fee; Bob receives XRP
+
1518 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(3) - batchFee);
+
1519 BEAST_EXPECT(env.balance(bob) == preBob + XRP(3));
+
1520 }
+
1521
+
1522 // tec failure
+
1523 {
+
1524 auto const preAlice = env.balance(alice);
+
1525 auto const preBob = env.balance(bob);
+
1526
+
1527 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
1528 auto const seq = env.seq(alice);
+
1529
+
1530 auto const [txIDs, batchID] = submitBatch(
+
1531 env,
+
1532 tesSUCCESS,
+
1533 batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
1534 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
1535 // tecUNFUNDED_PAYMENT: alice does not have enough XRP
+
1536 batch::inner(pay(alice, bob, XRP(9999)), seq + 2));
+
1537 env.close();
+
1538
+
1539 std::vector<TestLedgerData> testCases = {
+
1540 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
1541 };
+
1542 validateClosedLedger(env, testCases);
+
1543
+
1544 // Alice consumes sequence
+
1545 BEAST_EXPECT(env.seq(alice) == seq + 1);
+
1546
+
1547 // Alice pays Fee; Bob should not be affected
+
1548 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
+
1549 BEAST_EXPECT(env.balance(bob) == preBob);
+
1550 }
+
1551
+
1552 // tef failure
+
1553 {
+
1554 auto const preAlice = env.balance(alice);
+
1555 auto const preBob = env.balance(bob);
+
1556
+
1557 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
1558 auto const seq = env.seq(alice);
+
1559 auto const [txIDs, batchID] = submitBatch(
+
1560 env,
+
1561 tesSUCCESS,
+
1562 batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
1563 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
1564 // tefNO_AUTH_REQUIRED: trustline auth is not required
+
1565 batch::inner(trust(alice, USD(1000), tfSetfAuth), seq + 2));
+
1566 env.close();
+
1567
+
1568 std::vector<TestLedgerData> testCases = {
+
1569 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
1570 };
+
1571 validateClosedLedger(env, testCases);
+
1572
+
1573 // Alice consumes sequence
+
1574 BEAST_EXPECT(env.seq(alice) == seq + 1);
+
1575
+
1576 // Alice pays Fee; Bob should not be affected
+
1577 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
+
1578 BEAST_EXPECT(env.balance(bob) == preBob);
+
1579 }
+
1580
+
1581 // ter failure
+
1582 {
+
1583 auto const preAlice = env.balance(alice);
+
1584 auto const preBob = env.balance(bob);
+
1585
+
1586 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
1587 auto const seq = env.seq(alice);
+
1588 auto const [txIDs, batchID] = submitBatch(
+
1589 env,
+
1590 tesSUCCESS,
+
1591 batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
1592 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
1593 // terPRE_TICKET: ticket does not exist
+
1594 batch::inner(trust(alice, USD(1000), tfSetfAuth), 0, seq + 2));
+
1595 env.close();
+
1596
+
1597 std::vector<TestLedgerData> testCases = {
+
1598 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
1599 };
+
1600 validateClosedLedger(env, testCases);
+
1601
+
1602 // Alice consumes sequence
+
1603 BEAST_EXPECT(env.seq(alice) == seq + 1);
+
1604
+
1605 // Alice pays Fee; Bob should not be affected
+
1606 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
+
1607 BEAST_EXPECT(env.balance(bob) == preBob);
+
1608 }
+
1609 }
-
1608
-
1609 void
-
- -
1611 {
-
1612 testcase("only one");
-
1613
-
1614 using namespace test::jtx;
-
1615 using namespace std::literals;
-
1616
-
1617 test::jtx::Env env{*this, features};
+
1610
+
1611 void
+
+ +
1613 {
+
1614 testcase("only one");
+
1615
+
1616 using namespace test::jtx;
+
1617 using namespace std::literals;
1618
-
1619 auto const alice = Account("alice");
-
1620 auto const bob = Account("bob");
-
1621 auto const carol = Account("carol");
-
1622 auto const dave = Account("dave");
-
1623 auto const gw = Account("gw");
-
1624 auto const USD = gw["USD"];
-
1625 env.fund(XRP(10000), alice, bob, carol, dave, gw);
-
1626 env.close();
-
1627
-
1628 // all transactions fail
-
1629 {
-
1630 auto const preAlice = env.balance(alice);
-
1631 auto const preBob = env.balance(bob);
-
1632
-
1633 auto const batchFee = batch::calcBatchFee(env, 0, 3);
-
1634 auto const seq = env.seq(alice);
-
1635 auto const [txIDs, batchID] = submitBatch(
-
1636 env,
-
1637 tesSUCCESS,
-
1638 batch::outer(alice, seq, batchFee, tfOnlyOne),
-
1639 // tecUNFUNDED_PAYMENT: alice does not have enough XRP
-
1640 batch::inner(pay(alice, bob, XRP(9999)), seq + 1),
+
1619 test::jtx::Env env{*this, features};
+
1620
+
1621 auto const alice = Account("alice");
+
1622 auto const bob = Account("bob");
+
1623 auto const carol = Account("carol");
+
1624 auto const dave = Account("dave");
+
1625 auto const gw = Account("gw");
+
1626 auto const USD = gw["USD"];
+
1627 env.fund(XRP(10000), alice, bob, carol, dave, gw);
+
1628 env.close();
+
1629
+
1630 // all transactions fail
+
1631 {
+
1632 auto const preAlice = env.balance(alice);
+
1633 auto const preBob = env.balance(bob);
+
1634
+
1635 auto const batchFee = batch::calcBatchFee(env, 0, 3);
+
1636 auto const seq = env.seq(alice);
+
1637 auto const [txIDs, batchID] = submitBatch(
+
1638 env,
+
1639 tesSUCCESS,
+
1640 batch::outer(alice, seq, batchFee, tfOnlyOne),
1641 // tecUNFUNDED_PAYMENT: alice does not have enough XRP
-
1642 batch::inner(pay(alice, bob, XRP(9999)), seq + 2),
+
1642 batch::inner(pay(alice, bob, XRP(9999)), seq + 1),
1643 // tecUNFUNDED_PAYMENT: alice does not have enough XRP
-
1644 batch::inner(pay(alice, bob, XRP(9999)), seq + 3));
-
1645 env.close();
-
1646
-
1647 std::vector<TestLedgerData> testCases = {
-
1648 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
1649 {1, "Payment", "tecUNFUNDED_PAYMENT", txIDs[0], batchID},
-
1650 {2, "Payment", "tecUNFUNDED_PAYMENT", txIDs[1], batchID},
-
1651 {3, "Payment", "tecUNFUNDED_PAYMENT", txIDs[2], batchID},
-
1652 };
-
1653 validateClosedLedger(env, testCases);
-
1654
-
1655 // Alice consumes sequences (# of txns)
-
1656 BEAST_EXPECT(env.seq(alice) == seq + 4);
-
1657
-
1658 // Alice pays XRP & Fee; Bob receives XRP
-
1659 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
-
1660 BEAST_EXPECT(env.balance(bob) == preBob);
-
1661 }
-
1662
-
1663 // first transaction fails
-
1664 {
-
1665 auto const preAlice = env.balance(alice);
-
1666 auto const preBob = env.balance(bob);
-
1667
-
1668 auto const batchFee = batch::calcBatchFee(env, 0, 3);
-
1669 auto const seq = env.seq(alice);
-
1670 auto const [txIDs, batchID] = submitBatch(
-
1671 env,
-
1672 tesSUCCESS,
-
1673 batch::outer(alice, seq, batchFee, tfOnlyOne),
-
1674 // tecUNFUNDED_PAYMENT: alice does not have enough XRP
-
1675 batch::inner(pay(alice, bob, XRP(9999)), seq + 1),
-
1676 batch::inner(pay(alice, bob, XRP(1)), seq + 2),
-
1677 batch::inner(pay(alice, bob, XRP(2)), seq + 3));
-
1678 env.close();
-
1679
-
1680 std::vector<TestLedgerData> testCases = {
-
1681 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
1682 {1, "Payment", "tecUNFUNDED_PAYMENT", txIDs[0], batchID},
-
1683 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
1684 };
-
1685 validateClosedLedger(env, testCases);
-
1686
-
1687 // Alice consumes sequences (# of txns)
-
1688 BEAST_EXPECT(env.seq(alice) == seq + 3);
-
1689
-
1690 // Alice pays XRP & Fee; Bob receives XRP
-
1691 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(1) - batchFee);
-
1692 BEAST_EXPECT(env.balance(bob) == preBob + XRP(1));
-
1693 }
-
1694
-
1695 // tec failure
-
1696 {
-
1697 auto const preAlice = env.balance(alice);
-
1698 auto const preBob = env.balance(bob);
-
1699
-
1700 auto const batchFee = batch::calcBatchFee(env, 0, 3);
-
1701 auto const seq = env.seq(alice);
-
1702 auto const [txIDs, batchID] = submitBatch(
-
1703 env,
-
1704 tesSUCCESS,
-
1705 batch::outer(alice, seq, batchFee, tfOnlyOne),
-
1706 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
1707 // tecUNFUNDED_PAYMENT: alice does not have enough XRP
-
1708 batch::inner(pay(alice, bob, XRP(9999)), seq + 2),
-
1709 batch::inner(pay(alice, bob, XRP(2)), seq + 3));
-
1710 env.close();
-
1711
-
1712 std::vector<TestLedgerData> testCases = {
-
1713 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
1714 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
1715 };
-
1716 validateClosedLedger(env, testCases);
-
1717
-
1718 // Alice consumes sequences (# of txns)
-
1719 BEAST_EXPECT(env.seq(alice) == seq + 2);
-
1720
-
1721 // Alice pays XRP & Fee; Bob receives XRP
-
1722 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(1) - batchFee);
-
1723 BEAST_EXPECT(env.balance(bob) == preBob + XRP(1));
-
1724 }
-
1725
-
1726 // tef failure
-
1727 {
-
1728 auto const preAlice = env.balance(alice);
-
1729 auto const preBob = env.balance(bob);
-
1730
-
1731 auto const batchFee = batch::calcBatchFee(env, 0, 3);
-
1732 auto const seq = env.seq(alice);
-
1733 auto const [txIDs, batchID] = submitBatch(
-
1734 env,
-
1735 tesSUCCESS,
-
1736 batch::outer(alice, seq, batchFee, tfOnlyOne),
-
1737 // tefNO_AUTH_REQUIRED: trustline auth is not required
-
1738 batch::inner(trust(alice, USD(1000), tfSetfAuth), seq + 1),
-
1739 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
1740 batch::inner(pay(alice, bob, XRP(2)), seq + 3));
-
1741 env.close();
-
1742
-
1743 std::vector<TestLedgerData> testCases = {
-
1744 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
1745 {1, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
1746 };
-
1747 validateClosedLedger(env, testCases);
-
1748
-
1749 // Alice consumes sequences (# of txns)
-
1750 BEAST_EXPECT(env.seq(alice) == seq + 2);
-
1751
-
1752 // Alice pays XRP & Fee; Bob receives XRP
-
1753 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee - XRP(1));
-
1754 BEAST_EXPECT(env.balance(bob) == preBob + XRP(1));
-
1755 }
-
1756
-
1757 // ter failure
-
1758 {
-
1759 auto const preAlice = env.balance(alice);
-
1760 auto const preBob = env.balance(bob);
-
1761
-
1762 auto const batchFee = batch::calcBatchFee(env, 0, 3);
-
1763 auto const seq = env.seq(alice);
-
1764 auto const [txIDs, batchID] = submitBatch(
-
1765 env,
-
1766 tesSUCCESS,
-
1767 batch::outer(alice, seq, batchFee, tfOnlyOne),
-
1768 // terPRE_TICKET: ticket does not exist
-
1769 batch::inner(trust(alice, USD(1000), tfSetfAuth), 0, seq + 1),
-
1770 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
1771 batch::inner(pay(alice, bob, XRP(2)), seq + 3));
-
1772 env.close();
-
1773
-
1774 std::vector<TestLedgerData> testCases = {
-
1775 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
1776 {1, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
1777 };
-
1778 validateClosedLedger(env, testCases);
-
1779
-
1780 // Alice consumes sequences (# of txns)
-
1781 BEAST_EXPECT(env.seq(alice) == seq + 2);
-
1782
-
1783 // Alice pays XRP & Fee; Bob receives XRP
-
1784 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee - XRP(1));
-
1785 BEAST_EXPECT(env.balance(bob) == preBob + XRP(1));
-
1786 }
-
1787
-
1788 // tec (tecKILLED) error
-
1789 {
-
1790 auto const preAlice = env.balance(alice);
-
1791 auto const preBob = env.balance(bob);
-
1792 auto const preCarol = env.balance(carol);
-
1793 auto const seq = env.seq(alice);
-
1794 auto const batchFee = batch::calcBatchFee(env, 0, 6);
-
1795
-
1796 auto const [txIDs, batchID] = submitBatch(
-
1797 env,
-
1798 tesSUCCESS,
-
1799 batch::outer(alice, seq, batchFee, tfOnlyOne),
- -
1801 offer(
-
1802 alice,
-
1803 alice["USD"](100),
-
1804 XRP(100),
- -
1806 seq + 1),
- -
1808 offer(
-
1809 alice,
-
1810 alice["USD"](100),
-
1811 XRP(100),
- -
1813 seq + 2),
- -
1815 offer(
-
1816 alice,
-
1817 alice["USD"](100),
-
1818 XRP(100),
- -
1820 seq + 3),
-
1821 batch::inner(pay(alice, bob, XRP(100)), seq + 4),
-
1822 batch::inner(pay(alice, carol, XRP(100)), seq + 5),
-
1823 batch::inner(pay(alice, dave, XRP(100)), seq + 6));
-
1824 env.close();
-
1825
-
1826 std::vector<TestLedgerData> testCases = {
-
1827 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
1828 {1, "OfferCreate", "tecKILLED", txIDs[0], batchID},
-
1829 {2, "OfferCreate", "tecKILLED", txIDs[1], batchID},
-
1830 {3, "OfferCreate", "tecKILLED", txIDs[2], batchID},
-
1831 {4, "Payment", "tesSUCCESS", txIDs[3], batchID},
-
1832 };
-
1833 validateClosedLedger(env, testCases);
-
1834
-
1835 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(100) - batchFee);
-
1836 BEAST_EXPECT(env.balance(bob) == preBob + XRP(100));
-
1837 BEAST_EXPECT(env.balance(carol) == preCarol);
-
1838 }
-
1839 }
+
1644 batch::inner(pay(alice, bob, XRP(9999)), seq + 2),
+
1645 // tecUNFUNDED_PAYMENT: alice does not have enough XRP
+
1646 batch::inner(pay(alice, bob, XRP(9999)), seq + 3));
+
1647 env.close();
+
1648
+
1649 std::vector<TestLedgerData> testCases = {
+
1650 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
1651 {1, "Payment", "tecUNFUNDED_PAYMENT", txIDs[0], batchID},
+
1652 {2, "Payment", "tecUNFUNDED_PAYMENT", txIDs[1], batchID},
+
1653 {3, "Payment", "tecUNFUNDED_PAYMENT", txIDs[2], batchID},
+
1654 };
+
1655 validateClosedLedger(env, testCases);
+
1656
+
1657 // Alice consumes sequences (# of txns)
+
1658 BEAST_EXPECT(env.seq(alice) == seq + 4);
+
1659
+
1660 // Alice pays XRP & Fee; Bob receives XRP
+
1661 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
+
1662 BEAST_EXPECT(env.balance(bob) == preBob);
+
1663 }
+
1664
+
1665 // first transaction fails
+
1666 {
+
1667 auto const preAlice = env.balance(alice);
+
1668 auto const preBob = env.balance(bob);
+
1669
+
1670 auto const batchFee = batch::calcBatchFee(env, 0, 3);
+
1671 auto const seq = env.seq(alice);
+
1672 auto const [txIDs, batchID] = submitBatch(
+
1673 env,
+
1674 tesSUCCESS,
+
1675 batch::outer(alice, seq, batchFee, tfOnlyOne),
+
1676 // tecUNFUNDED_PAYMENT: alice does not have enough XRP
+
1677 batch::inner(pay(alice, bob, XRP(9999)), seq + 1),
+
1678 batch::inner(pay(alice, bob, XRP(1)), seq + 2),
+
1679 batch::inner(pay(alice, bob, XRP(2)), seq + 3));
+
1680 env.close();
+
1681
+
1682 std::vector<TestLedgerData> testCases = {
+
1683 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
1684 {1, "Payment", "tecUNFUNDED_PAYMENT", txIDs[0], batchID},
+
1685 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
1686 };
+
1687 validateClosedLedger(env, testCases);
+
1688
+
1689 // Alice consumes sequences (# of txns)
+
1690 BEAST_EXPECT(env.seq(alice) == seq + 3);
+
1691
+
1692 // Alice pays XRP & Fee; Bob receives XRP
+
1693 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(1) - batchFee);
+
1694 BEAST_EXPECT(env.balance(bob) == preBob + XRP(1));
+
1695 }
+
1696
+
1697 // tec failure
+
1698 {
+
1699 auto const preAlice = env.balance(alice);
+
1700 auto const preBob = env.balance(bob);
+
1701
+
1702 auto const batchFee = batch::calcBatchFee(env, 0, 3);
+
1703 auto const seq = env.seq(alice);
+
1704 auto const [txIDs, batchID] = submitBatch(
+
1705 env,
+
1706 tesSUCCESS,
+
1707 batch::outer(alice, seq, batchFee, tfOnlyOne),
+
1708 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
1709 // tecUNFUNDED_PAYMENT: alice does not have enough XRP
+
1710 batch::inner(pay(alice, bob, XRP(9999)), seq + 2),
+
1711 batch::inner(pay(alice, bob, XRP(2)), seq + 3));
+
1712 env.close();
+
1713
+
1714 std::vector<TestLedgerData> testCases = {
+
1715 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
1716 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
1717 };
+
1718 validateClosedLedger(env, testCases);
+
1719
+
1720 // Alice consumes sequences (# of txns)
+
1721 BEAST_EXPECT(env.seq(alice) == seq + 2);
+
1722
+
1723 // Alice pays XRP & Fee; Bob receives XRP
+
1724 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(1) - batchFee);
+
1725 BEAST_EXPECT(env.balance(bob) == preBob + XRP(1));
+
1726 }
+
1727
+
1728 // tef failure
+
1729 {
+
1730 auto const preAlice = env.balance(alice);
+
1731 auto const preBob = env.balance(bob);
+
1732
+
1733 auto const batchFee = batch::calcBatchFee(env, 0, 3);
+
1734 auto const seq = env.seq(alice);
+
1735 auto const [txIDs, batchID] = submitBatch(
+
1736 env,
+
1737 tesSUCCESS,
+
1738 batch::outer(alice, seq, batchFee, tfOnlyOne),
+
1739 // tefNO_AUTH_REQUIRED: trustline auth is not required
+
1740 batch::inner(trust(alice, USD(1000), tfSetfAuth), seq + 1),
+
1741 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
1742 batch::inner(pay(alice, bob, XRP(2)), seq + 3));
+
1743 env.close();
+
1744
+
1745 std::vector<TestLedgerData> testCases = {
+
1746 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
1747 {1, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
1748 };
+
1749 validateClosedLedger(env, testCases);
+
1750
+
1751 // Alice consumes sequences (# of txns)
+
1752 BEAST_EXPECT(env.seq(alice) == seq + 2);
+
1753
+
1754 // Alice pays XRP & Fee; Bob receives XRP
+
1755 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee - XRP(1));
+
1756 BEAST_EXPECT(env.balance(bob) == preBob + XRP(1));
+
1757 }
+
1758
+
1759 // ter failure
+
1760 {
+
1761 auto const preAlice = env.balance(alice);
+
1762 auto const preBob = env.balance(bob);
+
1763
+
1764 auto const batchFee = batch::calcBatchFee(env, 0, 3);
+
1765 auto const seq = env.seq(alice);
+
1766 auto const [txIDs, batchID] = submitBatch(
+
1767 env,
+
1768 tesSUCCESS,
+
1769 batch::outer(alice, seq, batchFee, tfOnlyOne),
+
1770 // terPRE_TICKET: ticket does not exist
+
1771 batch::inner(trust(alice, USD(1000), tfSetfAuth), 0, seq + 1),
+
1772 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
1773 batch::inner(pay(alice, bob, XRP(2)), seq + 3));
+
1774 env.close();
+
1775
+
1776 std::vector<TestLedgerData> testCases = {
+
1777 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
1778 {1, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
1779 };
+
1780 validateClosedLedger(env, testCases);
+
1781
+
1782 // Alice consumes sequences (# of txns)
+
1783 BEAST_EXPECT(env.seq(alice) == seq + 2);
+
1784
+
1785 // Alice pays XRP & Fee; Bob receives XRP
+
1786 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee - XRP(1));
+
1787 BEAST_EXPECT(env.balance(bob) == preBob + XRP(1));
+
1788 }
+
1789
+
1790 // tec (tecKILLED) error
+
1791 {
+
1792 auto const preAlice = env.balance(alice);
+
1793 auto const preBob = env.balance(bob);
+
1794 auto const preCarol = env.balance(carol);
+
1795 auto const seq = env.seq(alice);
+
1796 auto const batchFee = batch::calcBatchFee(env, 0, 6);
+
1797
+
1798 auto const [txIDs, batchID] = submitBatch(
+
1799 env,
+
1800 tesSUCCESS,
+
1801 batch::outer(alice, seq, batchFee, tfOnlyOne),
+ +
1803 offer(
+
1804 alice,
+
1805 alice["USD"](100),
+
1806 XRP(100),
+ +
1808 seq + 1),
+ +
1810 offer(
+
1811 alice,
+
1812 alice["USD"](100),
+
1813 XRP(100),
+ +
1815 seq + 2),
+ +
1817 offer(
+
1818 alice,
+
1819 alice["USD"](100),
+
1820 XRP(100),
+ +
1822 seq + 3),
+
1823 batch::inner(pay(alice, bob, XRP(100)), seq + 4),
+
1824 batch::inner(pay(alice, carol, XRP(100)), seq + 5),
+
1825 batch::inner(pay(alice, dave, XRP(100)), seq + 6));
+
1826 env.close();
+
1827
+
1828 std::vector<TestLedgerData> testCases = {
+
1829 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
1830 {1, "OfferCreate", "tecKILLED", txIDs[0], batchID},
+
1831 {2, "OfferCreate", "tecKILLED", txIDs[1], batchID},
+
1832 {3, "OfferCreate", "tecKILLED", txIDs[2], batchID},
+
1833 {4, "Payment", "tesSUCCESS", txIDs[3], batchID},
+
1834 };
+
1835 validateClosedLedger(env, testCases);
+
1836
+
1837 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(100) - batchFee);
+
1838 BEAST_EXPECT(env.balance(bob) == preBob + XRP(100));
+
1839 BEAST_EXPECT(env.balance(carol) == preCarol);
+
1840 }
+
1841 }
-
1840
-
1841 void
-
- -
1843 {
-
1844 testcase("until failure");
-
1845
-
1846 using namespace test::jtx;
-
1847 using namespace std::literals;
-
1848
-
1849 test::jtx::Env env{*this, features};
+
1842
+
1843 void
+
+ +
1845 {
+
1846 testcase("until failure");
+
1847
+
1848 using namespace test::jtx;
+
1849 using namespace std::literals;
1850
-
1851 auto const alice = Account("alice");
-
1852 auto const bob = Account("bob");
-
1853 auto const carol = Account("carol");
-
1854 auto const dave = Account("dave");
-
1855 auto const gw = Account("gw");
-
1856 auto const USD = gw["USD"];
-
1857 env.fund(XRP(10000), alice, bob, carol, dave, gw);
-
1858 env.close();
-
1859
-
1860 // first transaction fails
-
1861 {
-
1862 auto const preAlice = env.balance(alice);
-
1863 auto const preBob = env.balance(bob);
-
1864
-
1865 auto const batchFee = batch::calcBatchFee(env, 0, 4);
-
1866 auto const seq = env.seq(alice);
-
1867 auto const [txIDs, batchID] = submitBatch(
-
1868 env,
-
1869 tesSUCCESS,
-
1870 batch::outer(alice, seq, batchFee, tfUntilFailure),
-
1871 // tecUNFUNDED_PAYMENT: alice does not have enough XRP
-
1872 batch::inner(pay(alice, bob, XRP(9999)), seq + 1),
-
1873 batch::inner(pay(alice, bob, XRP(1)), seq + 2),
-
1874 batch::inner(pay(alice, bob, XRP(2)), seq + 3),
-
1875 batch::inner(pay(alice, bob, XRP(3)), seq + 4));
-
1876 env.close();
-
1877
-
1878 std::vector<TestLedgerData> testCases = {
-
1879 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
1880 {1, "Payment", "tecUNFUNDED_PAYMENT", txIDs[0], batchID},
-
1881 };
-
1882 validateClosedLedger(env, testCases);
-
1883
-
1884 // Alice consumes sequences (# of txns)
-
1885 BEAST_EXPECT(env.seq(alice) == seq + 2);
-
1886
-
1887 // Alice pays XRP & Fee; Bob receives XRP
-
1888 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
-
1889 BEAST_EXPECT(env.balance(bob) == preBob);
-
1890 }
-
1891
-
1892 // all transactions succeed
-
1893 {
-
1894 auto const preAlice = env.balance(alice);
-
1895 auto const preBob = env.balance(bob);
-
1896
-
1897 auto const batchFee = batch::calcBatchFee(env, 0, 4);
-
1898 auto const seq = env.seq(alice);
-
1899 auto const [txIDs, batchID] = submitBatch(
-
1900 env,
-
1901 tesSUCCESS,
-
1902 batch::outer(alice, seq, batchFee, tfUntilFailure),
-
1903 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
1904 batch::inner(pay(alice, bob, XRP(2)), seq + 2),
-
1905 batch::inner(pay(alice, bob, XRP(3)), seq + 3),
-
1906 batch::inner(pay(alice, bob, XRP(4)), seq + 4));
-
1907 env.close();
-
1908
-
1909 std::vector<TestLedgerData> testCases = {
-
1910 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
1911 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
1912 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
1913 {3, "Payment", "tesSUCCESS", txIDs[2], batchID},
-
1914 {4, "Payment", "tesSUCCESS", txIDs[3], batchID},
-
1915 };
-
1916 validateClosedLedger(env, testCases);
-
1917
-
1918 // Alice consumes sequences (# of txns)
-
1919 BEAST_EXPECT(env.seq(alice) == seq + 5);
-
1920
-
1921 // Alice pays XRP & Fee; Bob receives XRP
-
1922 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(10) - batchFee);
-
1923 BEAST_EXPECT(env.balance(bob) == preBob + XRP(10));
-
1924 }
-
1925
-
1926 // tec error
-
1927 {
-
1928 auto const preAlice = env.balance(alice);
-
1929 auto const preBob = env.balance(bob);
-
1930
-
1931 auto const batchFee = batch::calcBatchFee(env, 0, 4);
-
1932 auto const seq = env.seq(alice);
-
1933 auto const [txIDs, batchID] = submitBatch(
-
1934 env,
-
1935 tesSUCCESS,
-
1936 batch::outer(alice, seq, batchFee, tfUntilFailure),
-
1937 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
1938 batch::inner(pay(alice, bob, XRP(2)), seq + 2),
-
1939 // tecUNFUNDED_PAYMENT: alice does not have enough XRP
-
1940 batch::inner(pay(alice, bob, XRP(9999)), seq + 3),
-
1941 batch::inner(pay(alice, bob, XRP(3)), seq + 4));
-
1942 env.close();
-
1943
-
1944 std::vector<TestLedgerData> testCases = {
-
1945 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
1946 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
1947 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
1948 {3, "Payment", "tecUNFUNDED_PAYMENT", txIDs[2], batchID},
-
1949 };
-
1950 validateClosedLedger(env, testCases);
-
1951
-
1952 // Alice consumes sequences (# of txns)
-
1953 BEAST_EXPECT(env.seq(alice) == seq + 4);
-
1954
-
1955 // Alice pays XRP & Fee; Bob receives XRP
-
1956 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(3) - batchFee);
-
1957 BEAST_EXPECT(env.balance(bob) == preBob + XRP(3));
-
1958 }
-
1959
-
1960 // tef error
-
1961 {
-
1962 auto const preAlice = env.balance(alice);
-
1963 auto const preBob = env.balance(bob);
-
1964
-
1965 auto const batchFee = batch::calcBatchFee(env, 0, 4);
-
1966 auto const seq = env.seq(alice);
-
1967 auto const [txIDs, batchID] = submitBatch(
-
1968 env,
-
1969 tesSUCCESS,
-
1970 batch::outer(alice, seq, batchFee, tfUntilFailure),
-
1971 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
1972 batch::inner(pay(alice, bob, XRP(2)), seq + 2),
-
1973 // tefNO_AUTH_REQUIRED: trustline auth is not required
-
1974 batch::inner(trust(alice, USD(1000), tfSetfAuth), seq + 3),
-
1975 batch::inner(pay(alice, bob, XRP(3)), seq + 4));
-
1976 env.close();
-
1977
-
1978 std::vector<TestLedgerData> testCases = {
-
1979 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
1980 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
1981 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
1982 };
-
1983 validateClosedLedger(env, testCases);
-
1984
-
1985 // Alice consumes sequences (# of txns)
-
1986 BEAST_EXPECT(env.seq(alice) == seq + 3);
-
1987
-
1988 // Alice pays XRP & Fee; Bob receives XRP
-
1989 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(3) - batchFee);
-
1990 BEAST_EXPECT(env.balance(bob) == preBob + XRP(3));
-
1991 }
-
1992
-
1993 // ter error
-
1994 {
-
1995 auto const preAlice = env.balance(alice);
-
1996 auto const preBob = env.balance(bob);
-
1997
-
1998 auto const batchFee = batch::calcBatchFee(env, 0, 4);
-
1999 auto const seq = env.seq(alice);
-
2000 auto const [txIDs, batchID] = submitBatch(
-
2001 env,
-
2002 tesSUCCESS,
-
2003 batch::outer(alice, seq, batchFee, tfUntilFailure),
-
2004 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
2005 batch::inner(pay(alice, bob, XRP(2)), seq + 2),
-
2006 // terPRE_TICKET: ticket does not exist
-
2007 batch::inner(trust(alice, USD(1000), tfSetfAuth), 0, seq + 3),
-
2008 batch::inner(pay(alice, bob, XRP(3)), seq + 4));
-
2009 env.close();
-
2010
-
2011 std::vector<TestLedgerData> testCases = {
-
2012 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
2013 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
2014 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
2015 };
-
2016 validateClosedLedger(env, testCases);
-
2017
-
2018 // Alice consumes sequences (# of txns)
-
2019 BEAST_EXPECT(env.seq(alice) == seq + 3);
-
2020
-
2021 // Alice pays XRP & Fee; Bob receives XRP
-
2022 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(3) - batchFee);
-
2023 BEAST_EXPECT(env.balance(bob) == preBob + XRP(3));
-
2024 }
-
2025
-
2026 // tec (tecKILLED) error
-
2027 {
-
2028 auto const preAlice = env.balance(alice);
-
2029 auto const preBob = env.balance(bob);
-
2030 auto const preCarol = env.balance(carol);
-
2031 auto const seq = env.seq(alice);
-
2032 auto const batchFee = batch::calcBatchFee(env, 0, 4);
-
2033 auto const [txIDs, batchID] = submitBatch(
-
2034 env,
-
2035 tesSUCCESS,
-
2036 batch::outer(alice, seq, batchFee, tfUntilFailure),
-
2037 batch::inner(pay(alice, bob, XRP(100)), seq + 1),
-
2038 batch::inner(pay(alice, carol, XRP(100)), seq + 2),
- -
2040 offer(
-
2041 alice,
-
2042 alice["USD"](100),
-
2043 XRP(100),
- -
2045 seq + 3),
-
2046 batch::inner(pay(alice, dave, XRP(100)), seq + 4));
-
2047 env.close();
-
2048
-
2049 std::vector<TestLedgerData> testCases = {
-
2050 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
2051 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
2052 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
2053 {3, "OfferCreate", "tecKILLED", txIDs[2], batchID},
-
2054 };
-
2055 validateClosedLedger(env, testCases);
-
2056
-
2057 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(200) - batchFee);
-
2058 BEAST_EXPECT(env.balance(bob) == preBob + XRP(100));
-
2059 BEAST_EXPECT(env.balance(carol) == preCarol + XRP(100));
-
2060 }
-
2061 }
+
1851 test::jtx::Env env{*this, features};
+
1852
+
1853 auto const alice = Account("alice");
+
1854 auto const bob = Account("bob");
+
1855 auto const carol = Account("carol");
+
1856 auto const dave = Account("dave");
+
1857 auto const gw = Account("gw");
+
1858 auto const USD = gw["USD"];
+
1859 env.fund(XRP(10000), alice, bob, carol, dave, gw);
+
1860 env.close();
+
1861
+
1862 // first transaction fails
+
1863 {
+
1864 auto const preAlice = env.balance(alice);
+
1865 auto const preBob = env.balance(bob);
+
1866
+
1867 auto const batchFee = batch::calcBatchFee(env, 0, 4);
+
1868 auto const seq = env.seq(alice);
+
1869 auto const [txIDs, batchID] = submitBatch(
+
1870 env,
+
1871 tesSUCCESS,
+
1872 batch::outer(alice, seq, batchFee, tfUntilFailure),
+
1873 // tecUNFUNDED_PAYMENT: alice does not have enough XRP
+
1874 batch::inner(pay(alice, bob, XRP(9999)), seq + 1),
+
1875 batch::inner(pay(alice, bob, XRP(1)), seq + 2),
+
1876 batch::inner(pay(alice, bob, XRP(2)), seq + 3),
+
1877 batch::inner(pay(alice, bob, XRP(3)), seq + 4));
+
1878 env.close();
+
1879
+
1880 std::vector<TestLedgerData> testCases = {
+
1881 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
1882 {1, "Payment", "tecUNFUNDED_PAYMENT", txIDs[0], batchID},
+
1883 };
+
1884 validateClosedLedger(env, testCases);
+
1885
+
1886 // Alice consumes sequences (# of txns)
+
1887 BEAST_EXPECT(env.seq(alice) == seq + 2);
+
1888
+
1889 // Alice pays XRP & Fee; Bob receives XRP
+
1890 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
+
1891 BEAST_EXPECT(env.balance(bob) == preBob);
+
1892 }
+
1893
+
1894 // all transactions succeed
+
1895 {
+
1896 auto const preAlice = env.balance(alice);
+
1897 auto const preBob = env.balance(bob);
+
1898
+
1899 auto const batchFee = batch::calcBatchFee(env, 0, 4);
+
1900 auto const seq = env.seq(alice);
+
1901 auto const [txIDs, batchID] = submitBatch(
+
1902 env,
+
1903 tesSUCCESS,
+
1904 batch::outer(alice, seq, batchFee, tfUntilFailure),
+
1905 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
1906 batch::inner(pay(alice, bob, XRP(2)), seq + 2),
+
1907 batch::inner(pay(alice, bob, XRP(3)), seq + 3),
+
1908 batch::inner(pay(alice, bob, XRP(4)), seq + 4));
+
1909 env.close();
+
1910
+
1911 std::vector<TestLedgerData> testCases = {
+
1912 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
1913 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
1914 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
1915 {3, "Payment", "tesSUCCESS", txIDs[2], batchID},
+
1916 {4, "Payment", "tesSUCCESS", txIDs[3], batchID},
+
1917 };
+
1918 validateClosedLedger(env, testCases);
+
1919
+
1920 // Alice consumes sequences (# of txns)
+
1921 BEAST_EXPECT(env.seq(alice) == seq + 5);
+
1922
+
1923 // Alice pays XRP & Fee; Bob receives XRP
+
1924 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(10) - batchFee);
+
1925 BEAST_EXPECT(env.balance(bob) == preBob + XRP(10));
+
1926 }
+
1927
+
1928 // tec error
+
1929 {
+
1930 auto const preAlice = env.balance(alice);
+
1931 auto const preBob = env.balance(bob);
+
1932
+
1933 auto const batchFee = batch::calcBatchFee(env, 0, 4);
+
1934 auto const seq = env.seq(alice);
+
1935 auto const [txIDs, batchID] = submitBatch(
+
1936 env,
+
1937 tesSUCCESS,
+
1938 batch::outer(alice, seq, batchFee, tfUntilFailure),
+
1939 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
1940 batch::inner(pay(alice, bob, XRP(2)), seq + 2),
+
1941 // tecUNFUNDED_PAYMENT: alice does not have enough XRP
+
1942 batch::inner(pay(alice, bob, XRP(9999)), seq + 3),
+
1943 batch::inner(pay(alice, bob, XRP(3)), seq + 4));
+
1944 env.close();
+
1945
+
1946 std::vector<TestLedgerData> testCases = {
+
1947 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
1948 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
1949 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
1950 {3, "Payment", "tecUNFUNDED_PAYMENT", txIDs[2], batchID},
+
1951 };
+
1952 validateClosedLedger(env, testCases);
+
1953
+
1954 // Alice consumes sequences (# of txns)
+
1955 BEAST_EXPECT(env.seq(alice) == seq + 4);
+
1956
+
1957 // Alice pays XRP & Fee; Bob receives XRP
+
1958 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(3) - batchFee);
+
1959 BEAST_EXPECT(env.balance(bob) == preBob + XRP(3));
+
1960 }
+
1961
+
1962 // tef error
+
1963 {
+
1964 auto const preAlice = env.balance(alice);
+
1965 auto const preBob = env.balance(bob);
+
1966
+
1967 auto const batchFee = batch::calcBatchFee(env, 0, 4);
+
1968 auto const seq = env.seq(alice);
+
1969 auto const [txIDs, batchID] = submitBatch(
+
1970 env,
+
1971 tesSUCCESS,
+
1972 batch::outer(alice, seq, batchFee, tfUntilFailure),
+
1973 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
1974 batch::inner(pay(alice, bob, XRP(2)), seq + 2),
+
1975 // tefNO_AUTH_REQUIRED: trustline auth is not required
+
1976 batch::inner(trust(alice, USD(1000), tfSetfAuth), seq + 3),
+
1977 batch::inner(pay(alice, bob, XRP(3)), seq + 4));
+
1978 env.close();
+
1979
+
1980 std::vector<TestLedgerData> testCases = {
+
1981 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
1982 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
1983 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
1984 };
+
1985 validateClosedLedger(env, testCases);
+
1986
+
1987 // Alice consumes sequences (# of txns)
+
1988 BEAST_EXPECT(env.seq(alice) == seq + 3);
+
1989
+
1990 // Alice pays XRP & Fee; Bob receives XRP
+
1991 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(3) - batchFee);
+
1992 BEAST_EXPECT(env.balance(bob) == preBob + XRP(3));
+
1993 }
+
1994
+
1995 // ter error
+
1996 {
+
1997 auto const preAlice = env.balance(alice);
+
1998 auto const preBob = env.balance(bob);
+
1999
+
2000 auto const batchFee = batch::calcBatchFee(env, 0, 4);
+
2001 auto const seq = env.seq(alice);
+
2002 auto const [txIDs, batchID] = submitBatch(
+
2003 env,
+
2004 tesSUCCESS,
+
2005 batch::outer(alice, seq, batchFee, tfUntilFailure),
+
2006 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
2007 batch::inner(pay(alice, bob, XRP(2)), seq + 2),
+
2008 // terPRE_TICKET: ticket does not exist
+
2009 batch::inner(trust(alice, USD(1000), tfSetfAuth), 0, seq + 3),
+
2010 batch::inner(pay(alice, bob, XRP(3)), seq + 4));
+
2011 env.close();
+
2012
+
2013 std::vector<TestLedgerData> testCases = {
+
2014 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
2015 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
2016 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
2017 };
+
2018 validateClosedLedger(env, testCases);
+
2019
+
2020 // Alice consumes sequences (# of txns)
+
2021 BEAST_EXPECT(env.seq(alice) == seq + 3);
+
2022
+
2023 // Alice pays XRP & Fee; Bob receives XRP
+
2024 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(3) - batchFee);
+
2025 BEAST_EXPECT(env.balance(bob) == preBob + XRP(3));
+
2026 }
+
2027
+
2028 // tec (tecKILLED) error
+
2029 {
+
2030 auto const preAlice = env.balance(alice);
+
2031 auto const preBob = env.balance(bob);
+
2032 auto const preCarol = env.balance(carol);
+
2033 auto const seq = env.seq(alice);
+
2034 auto const batchFee = batch::calcBatchFee(env, 0, 4);
+
2035 auto const [txIDs, batchID] = submitBatch(
+
2036 env,
+
2037 tesSUCCESS,
+
2038 batch::outer(alice, seq, batchFee, tfUntilFailure),
+
2039 batch::inner(pay(alice, bob, XRP(100)), seq + 1),
+
2040 batch::inner(pay(alice, carol, XRP(100)), seq + 2),
+ +
2042 offer(
+
2043 alice,
+
2044 alice["USD"](100),
+
2045 XRP(100),
+ +
2047 seq + 3),
+
2048 batch::inner(pay(alice, dave, XRP(100)), seq + 4));
+
2049 env.close();
+
2050
+
2051 std::vector<TestLedgerData> testCases = {
+
2052 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
2053 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
2054 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
2055 {3, "OfferCreate", "tecKILLED", txIDs[2], batchID},
+
2056 };
+
2057 validateClosedLedger(env, testCases);
+
2058
+
2059 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(200) - batchFee);
+
2060 BEAST_EXPECT(env.balance(bob) == preBob + XRP(100));
+
2061 BEAST_EXPECT(env.balance(carol) == preCarol + XRP(100));
+
2062 }
+
2063 }
-
2062
-
2063 void
-
- -
2065 {
-
2066 testcase("independent");
-
2067
-
2068 using namespace test::jtx;
-
2069 using namespace std::literals;
-
2070
-
2071 test::jtx::Env env{*this, features};
+
2064
+
2065 void
+
+ +
2067 {
+
2068 testcase("independent");
+
2069
+
2070 using namespace test::jtx;
+
2071 using namespace std::literals;
2072
-
2073 auto const alice = Account("alice");
-
2074 auto const bob = Account("bob");
-
2075 auto const carol = Account("carol");
-
2076 auto const gw = Account("gw");
-
2077 auto const USD = gw["USD"];
-
2078 env.fund(XRP(10000), alice, bob, carol, gw);
-
2079 env.close();
-
2080
-
2081 // multiple transactions fail
-
2082 {
-
2083 auto const preAlice = env.balance(alice);
-
2084 auto const preBob = env.balance(bob);
-
2085
-
2086 auto const batchFee = batch::calcBatchFee(env, 0, 4);
-
2087 auto const seq = env.seq(alice);
-
2088 auto const [txIDs, batchID] = submitBatch(
-
2089 env,
-
2090 tesSUCCESS,
-
2091 batch::outer(alice, seq, batchFee, tfIndependent),
-
2092 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
2093 // tecUNFUNDED_PAYMENT: alice does not have enough XRP
-
2094 batch::inner(pay(alice, bob, XRP(9999)), seq + 2),
+
2073 test::jtx::Env env{*this, features};
+
2074
+
2075 auto const alice = Account("alice");
+
2076 auto const bob = Account("bob");
+
2077 auto const carol = Account("carol");
+
2078 auto const gw = Account("gw");
+
2079 auto const USD = gw["USD"];
+
2080 env.fund(XRP(10000), alice, bob, carol, gw);
+
2081 env.close();
+
2082
+
2083 // multiple transactions fail
+
2084 {
+
2085 auto const preAlice = env.balance(alice);
+
2086 auto const preBob = env.balance(bob);
+
2087
+
2088 auto const batchFee = batch::calcBatchFee(env, 0, 4);
+
2089 auto const seq = env.seq(alice);
+
2090 auto const [txIDs, batchID] = submitBatch(
+
2091 env,
+
2092 tesSUCCESS,
+
2093 batch::outer(alice, seq, batchFee, tfIndependent),
+
2094 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
2095 // tecUNFUNDED_PAYMENT: alice does not have enough XRP
-
2096 batch::inner(pay(alice, bob, XRP(9999)), seq + 3),
-
2097 batch::inner(pay(alice, bob, XRP(3)), seq + 4));
-
2098 env.close();
-
2099
-
2100 std::vector<TestLedgerData> testCases = {
-
2101 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
2102 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
2103 {2, "Payment", "tecUNFUNDED_PAYMENT", txIDs[1], batchID},
-
2104 {3, "Payment", "tecUNFUNDED_PAYMENT", txIDs[2], batchID},
-
2105 {4, "Payment", "tesSUCCESS", txIDs[3], batchID},
-
2106 };
-
2107 validateClosedLedger(env, testCases);
-
2108
-
2109 // Alice consumes sequences (# of txns)
-
2110 BEAST_EXPECT(env.seq(alice) == seq + 5);
-
2111
-
2112 // Alice pays XRP & Fee; Bob receives XRP
-
2113 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(4) - batchFee);
-
2114 BEAST_EXPECT(env.balance(bob) == preBob + XRP(4));
-
2115 }
-
2116
-
2117 // tec error
-
2118 {
-
2119 auto const preAlice = env.balance(alice);
-
2120 auto const preBob = env.balance(bob);
-
2121
-
2122 auto const batchFee = batch::calcBatchFee(env, 0, 4);
-
2123 auto const seq = env.seq(alice);
-
2124 auto const [txIDs, batchID] = submitBatch(
-
2125 env,
-
2126 tesSUCCESS,
-
2127 batch::outer(alice, seq, batchFee, tfIndependent),
-
2128 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
2129 batch::inner(pay(alice, bob, XRP(2)), seq + 2),
-
2130 // tecUNFUNDED_PAYMENT: alice does not have enough XRP
-
2131 batch::inner(pay(alice, bob, XRP(9999)), seq + 3),
-
2132 batch::inner(pay(alice, bob, XRP(3)), seq + 4));
-
2133 env.close();
-
2134
-
2135 std::vector<TestLedgerData> testCases = {
-
2136 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
2137 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
2138 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
2139 {3, "Payment", "tecUNFUNDED_PAYMENT", txIDs[2], batchID},
-
2140 {4, "Payment", "tesSUCCESS", txIDs[3], batchID},
-
2141 };
-
2142 validateClosedLedger(env, testCases);
-
2143
-
2144 // Alice consumes sequences (# of txns)
-
2145 BEAST_EXPECT(env.seq(alice) == seq + 5);
-
2146
-
2147 // Alice pays XRP & Fee; Bob receives XRP
-
2148 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(6) - batchFee);
-
2149 BEAST_EXPECT(env.balance(bob) == preBob + XRP(6));
-
2150 }
-
2151
-
2152 // tef error
-
2153 {
-
2154 auto const preAlice = env.balance(alice);
-
2155 auto const preBob = env.balance(bob);
-
2156
-
2157 auto const batchFee = batch::calcBatchFee(env, 0, 4);
-
2158 auto const seq = env.seq(alice);
-
2159 auto const [txIDs, batchID] = submitBatch(
-
2160 env,
-
2161 tesSUCCESS,
-
2162 batch::outer(alice, seq, batchFee, tfIndependent),
-
2163 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
2164 batch::inner(pay(alice, bob, XRP(2)), seq + 2),
-
2165 // tefNO_AUTH_REQUIRED: trustline auth is not required
-
2166 batch::inner(trust(alice, USD(1000), tfSetfAuth), seq + 3),
-
2167 batch::inner(pay(alice, bob, XRP(3)), seq + 3));
-
2168 env.close();
-
2169
-
2170 std::vector<TestLedgerData> testCases = {
-
2171 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
2172 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
2173 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
2174 {3, "Payment", "tesSUCCESS", txIDs[3], batchID},
-
2175 };
-
2176 validateClosedLedger(env, testCases);
-
2177
-
2178 // Alice consumes sequences (# of txns)
-
2179 BEAST_EXPECT(env.seq(alice) == seq + 4);
-
2180
-
2181 // Alice pays XRP & Fee; Bob receives XRP
-
2182 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee - XRP(6));
-
2183 BEAST_EXPECT(env.balance(bob) == preBob + XRP(6));
-
2184 }
-
2185
-
2186 // ter error
-
2187 {
-
2188 auto const preAlice = env.balance(alice);
-
2189 auto const preBob = env.balance(bob);
-
2190
-
2191 auto const batchFee = batch::calcBatchFee(env, 0, 4);
-
2192 auto const seq = env.seq(alice);
-
2193 auto const [txIDs, batchID] = submitBatch(
-
2194 env,
-
2195 tesSUCCESS,
-
2196 batch::outer(alice, seq, batchFee, tfIndependent),
-
2197 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
2198 batch::inner(pay(alice, bob, XRP(2)), seq + 2),
-
2199 // terPRE_TICKET: ticket does not exist
-
2200 batch::inner(trust(alice, USD(1000), tfSetfAuth), 0, seq + 3),
-
2201 batch::inner(pay(alice, bob, XRP(3)), seq + 3));
-
2202 env.close();
-
2203
-
2204 std::vector<TestLedgerData> testCases = {
-
2205 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
2206 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
2207 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
2208 {3, "Payment", "tesSUCCESS", txIDs[3], batchID},
-
2209 };
-
2210 validateClosedLedger(env, testCases);
-
2211
-
2212 // Alice consumes sequences (# of txns)
-
2213 BEAST_EXPECT(env.seq(alice) == seq + 4);
-
2214
-
2215 // Alice pays XRP & Fee; Bob receives XRP
-
2216 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee - XRP(6));
-
2217 BEAST_EXPECT(env.balance(bob) == preBob + XRP(6));
-
2218 }
-
2219
-
2220 // tec (tecKILLED) error
-
2221 {
-
2222 auto const preAlice = env.balance(alice);
-
2223 auto const preBob = env.balance(bob);
-
2224 auto const preCarol = env.balance(carol);
-
2225 auto const seq = env.seq(alice);
-
2226 auto const batchFee = batch::calcBatchFee(env, 0, 3);
-
2227 auto const [txIDs, batchID] = submitBatch(
-
2228 env,
-
2229 tesSUCCESS,
-
2230 batch::outer(alice, seq, batchFee, tfIndependent),
-
2231 batch::inner(pay(alice, bob, XRP(100)), seq + 1),
-
2232 batch::inner(pay(alice, carol, XRP(100)), seq + 2),
- -
2234 offer(
-
2235 alice,
-
2236 alice["USD"](100),
-
2237 XRP(100),
- -
2239 seq + 3));
-
2240 env.close();
-
2241
-
2242 std::vector<TestLedgerData> testCases = {
-
2243 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
2244 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
2245 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
2246 {3, "OfferCreate", "tecKILLED", txIDs[2], batchID},
-
2247 };
-
2248 validateClosedLedger(env, testCases);
-
2249
-
2250 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(200) - batchFee);
-
2251 BEAST_EXPECT(env.balance(bob) == preBob + XRP(100));
-
2252 BEAST_EXPECT(env.balance(carol) == preCarol + XRP(100));
-
2253 }
-
2254 }
+
2096 batch::inner(pay(alice, bob, XRP(9999)), seq + 2),
+
2097 // tecUNFUNDED_PAYMENT: alice does not have enough XRP
+
2098 batch::inner(pay(alice, bob, XRP(9999)), seq + 3),
+
2099 batch::inner(pay(alice, bob, XRP(3)), seq + 4));
+
2100 env.close();
+
2101
+
2102 std::vector<TestLedgerData> testCases = {
+
2103 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
2104 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
2105 {2, "Payment", "tecUNFUNDED_PAYMENT", txIDs[1], batchID},
+
2106 {3, "Payment", "tecUNFUNDED_PAYMENT", txIDs[2], batchID},
+
2107 {4, "Payment", "tesSUCCESS", txIDs[3], batchID},
+
2108 };
+
2109 validateClosedLedger(env, testCases);
+
2110
+
2111 // Alice consumes sequences (# of txns)
+
2112 BEAST_EXPECT(env.seq(alice) == seq + 5);
+
2113
+
2114 // Alice pays XRP & Fee; Bob receives XRP
+
2115 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(4) - batchFee);
+
2116 BEAST_EXPECT(env.balance(bob) == preBob + XRP(4));
+
2117 }
+
2118
+
2119 // tec error
+
2120 {
+
2121 auto const preAlice = env.balance(alice);
+
2122 auto const preBob = env.balance(bob);
+
2123
+
2124 auto const batchFee = batch::calcBatchFee(env, 0, 4);
+
2125 auto const seq = env.seq(alice);
+
2126 auto const [txIDs, batchID] = submitBatch(
+
2127 env,
+
2128 tesSUCCESS,
+
2129 batch::outer(alice, seq, batchFee, tfIndependent),
+
2130 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
2131 batch::inner(pay(alice, bob, XRP(2)), seq + 2),
+
2132 // tecUNFUNDED_PAYMENT: alice does not have enough XRP
+
2133 batch::inner(pay(alice, bob, XRP(9999)), seq + 3),
+
2134 batch::inner(pay(alice, bob, XRP(3)), seq + 4));
+
2135 env.close();
+
2136
+
2137 std::vector<TestLedgerData> testCases = {
+
2138 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
2139 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
2140 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
2141 {3, "Payment", "tecUNFUNDED_PAYMENT", txIDs[2], batchID},
+
2142 {4, "Payment", "tesSUCCESS", txIDs[3], batchID},
+
2143 };
+
2144 validateClosedLedger(env, testCases);
+
2145
+
2146 // Alice consumes sequences (# of txns)
+
2147 BEAST_EXPECT(env.seq(alice) == seq + 5);
+
2148
+
2149 // Alice pays XRP & Fee; Bob receives XRP
+
2150 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(6) - batchFee);
+
2151 BEAST_EXPECT(env.balance(bob) == preBob + XRP(6));
+
2152 }
+
2153
+
2154 // tef error
+
2155 {
+
2156 auto const preAlice = env.balance(alice);
+
2157 auto const preBob = env.balance(bob);
+
2158
+
2159 auto const batchFee = batch::calcBatchFee(env, 0, 4);
+
2160 auto const seq = env.seq(alice);
+
2161 auto const [txIDs, batchID] = submitBatch(
+
2162 env,
+
2163 tesSUCCESS,
+
2164 batch::outer(alice, seq, batchFee, tfIndependent),
+
2165 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
2166 batch::inner(pay(alice, bob, XRP(2)), seq + 2),
+
2167 // tefNO_AUTH_REQUIRED: trustline auth is not required
+
2168 batch::inner(trust(alice, USD(1000), tfSetfAuth), seq + 3),
+
2169 batch::inner(pay(alice, bob, XRP(3)), seq + 3));
+
2170 env.close();
+
2171
+
2172 std::vector<TestLedgerData> testCases = {
+
2173 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
2174 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
2175 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
2176 {3, "Payment", "tesSUCCESS", txIDs[3], batchID},
+
2177 };
+
2178 validateClosedLedger(env, testCases);
+
2179
+
2180 // Alice consumes sequences (# of txns)
+
2181 BEAST_EXPECT(env.seq(alice) == seq + 4);
+
2182
+
2183 // Alice pays XRP & Fee; Bob receives XRP
+
2184 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee - XRP(6));
+
2185 BEAST_EXPECT(env.balance(bob) == preBob + XRP(6));
+
2186 }
+
2187
+
2188 // ter error
+
2189 {
+
2190 auto const preAlice = env.balance(alice);
+
2191 auto const preBob = env.balance(bob);
+
2192
+
2193 auto const batchFee = batch::calcBatchFee(env, 0, 4);
+
2194 auto const seq = env.seq(alice);
+
2195 auto const [txIDs, batchID] = submitBatch(
+
2196 env,
+
2197 tesSUCCESS,
+
2198 batch::outer(alice, seq, batchFee, tfIndependent),
+
2199 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
2200 batch::inner(pay(alice, bob, XRP(2)), seq + 2),
+
2201 // terPRE_TICKET: ticket does not exist
+
2202 batch::inner(trust(alice, USD(1000), tfSetfAuth), 0, seq + 3),
+
2203 batch::inner(pay(alice, bob, XRP(3)), seq + 3));
+
2204 env.close();
+
2205
+
2206 std::vector<TestLedgerData> testCases = {
+
2207 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
2208 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
2209 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
2210 {3, "Payment", "tesSUCCESS", txIDs[3], batchID},
+
2211 };
+
2212 validateClosedLedger(env, testCases);
+
2213
+
2214 // Alice consumes sequences (# of txns)
+
2215 BEAST_EXPECT(env.seq(alice) == seq + 4);
+
2216
+
2217 // Alice pays XRP & Fee; Bob receives XRP
+
2218 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee - XRP(6));
+
2219 BEAST_EXPECT(env.balance(bob) == preBob + XRP(6));
+
2220 }
+
2221
+
2222 // tec (tecKILLED) error
+
2223 {
+
2224 auto const preAlice = env.balance(alice);
+
2225 auto const preBob = env.balance(bob);
+
2226 auto const preCarol = env.balance(carol);
+
2227 auto const seq = env.seq(alice);
+
2228 auto const batchFee = batch::calcBatchFee(env, 0, 3);
+
2229 auto const [txIDs, batchID] = submitBatch(
+
2230 env,
+
2231 tesSUCCESS,
+
2232 batch::outer(alice, seq, batchFee, tfIndependent),
+
2233 batch::inner(pay(alice, bob, XRP(100)), seq + 1),
+
2234 batch::inner(pay(alice, carol, XRP(100)), seq + 2),
+ +
2236 offer(
+
2237 alice,
+
2238 alice["USD"](100),
+
2239 XRP(100),
+ +
2241 seq + 3));
+
2242 env.close();
+
2243
+
2244 std::vector<TestLedgerData> testCases = {
+
2245 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
2246 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
2247 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
2248 {3, "OfferCreate", "tecKILLED", txIDs[2], batchID},
+
2249 };
+
2250 validateClosedLedger(env, testCases);
+
2251
+
2252 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(200) - batchFee);
+
2253 BEAST_EXPECT(env.balance(bob) == preBob + XRP(100));
+
2254 BEAST_EXPECT(env.balance(carol) == preCarol + XRP(100));
+
2255 }
+
2256 }
-
2255
-
2256 void
-
-
2257 doTestInnerSubmitRPC(FeatureBitset features, bool withBatch)
-
2258 {
-
2259 bool const withInnerSigFix = features[fixBatchInnerSigs];
-
2260
-
2261 std::string const testName = [&]() {
- -
2263 ss << "inner submit rpc: batch "
-
2264 << (withBatch ? "enabled" : "disabled") << ", inner sig fix: "
-
2265 << (withInnerSigFix ? "enabled" : "disabled") << ": ";
-
2266 return ss.str();
-
2267 }();
-
2268
-
2269 auto const amend = withBatch ? features : features - featureBatch;
+
2257
+
2258 void
+
+
2259 doTestInnerSubmitRPC(FeatureBitset features, bool withBatch)
+
2260 {
+
2261 bool const withInnerSigFix = features[fixBatchInnerSigs];
+
2262
+
2263 std::string const testName = [&]() {
+ +
2265 ss << "inner submit rpc: batch "
+
2266 << (withBatch ? "enabled" : "disabled") << ", inner sig fix: "
+
2267 << (withInnerSigFix ? "enabled" : "disabled") << ": ";
+
2268 return ss.str();
+
2269 }();
2270
-
2271 using namespace test::jtx;
-
2272 using namespace std::literals;
-
2273
-
2274 test::jtx::Env env{*this, amend};
-
2275 if (!BEAST_EXPECT(amend[featureBatch] == withBatch))
-
2276 return;
-
2277
-
2278 auto const alice = Account("alice");
-
2279 auto const bob = Account("bob");
-
2280
-
2281 env.fund(XRP(10000), alice, bob);
-
2282 env.close();
-
2283
-
2284 auto submitAndValidate =
-
2285 [&](std::string caseName,
-
2286 Slice const& slice,
-
2287 int line,
-
2288 std::optional<std::string> expectedEnabled = std::nullopt,
-
2289 std::optional<std::string> expectedDisabled = std::nullopt,
-
2290 bool expectInvalidFlag = false) {
-
2291 testcase << testName << caseName
-
2292 << (expectInvalidFlag
-
2293 ? " - Expected to reach tx engine!"
-
2294 : "");
-
2295 auto const jrr = env.rpc("submit", strHex(slice))[jss::result];
-
2296 auto const expected = withBatch
-
2297 ? expectedEnabled.value_or(
-
2298 "fails local checks: Malformed: Invalid inner batch "
-
2299 "transaction.")
-
2300 : expectedDisabled.value_or(
-
2301 "fails local checks: Empty SigningPubKey.");
-
2302 if (expectInvalidFlag)
-
2303 {
-
2304 expect(
-
2305 jrr[jss::status] == "success" &&
-
2306 jrr[jss::engine_result] == "temINVALID_FLAG",
-
2307 pretty(jrr),
-
2308 __FILE__,
-
2309 line);
-
2310 }
-
2311 else
-
2312 {
-
2313 expect(
-
2314 jrr[jss::status] == "error" &&
-
2315 jrr[jss::error] == "invalidTransaction" &&
-
2316 jrr[jss::error_exception] == expected,
-
2317 pretty(jrr),
-
2318 __FILE__,
-
2319 line);
-
2320 }
-
2321 env.close();
-
2322 };
-
2323
-
2324 // Invalid RPC Submission: TxnSignature
-
2325 // + has `TxnSignature` field
-
2326 // - has no `SigningPubKey` field
-
2327 // - has no `Signers` field
-
2328 // + has `tfInnerBatchTxn` flag
-
2329 {
-
2330 auto txn = batch::inner(pay(alice, bob, XRP(1)), env.seq(alice));
-
2331 txn[sfTxnSignature] = "DEADBEEF";
-
2332 STParsedJSONObject parsed("test", txn.getTxn());
-
2333 Serializer s;
-
2334 parsed.object->add(s);
-
2335 submitAndValidate("TxnSignature set", s.slice(), __LINE__);
-
2336 }
-
2337
-
2338 // Invalid RPC Submission: SigningPubKey
-
2339 // - has no `TxnSignature` field
-
2340 // + has `SigningPubKey` field
-
2341 // - has no `Signers` field
-
2342 // + has `tfInnerBatchTxn` flag
-
2343 {
-
2344 auto txn = batch::inner(pay(alice, bob, XRP(1)), env.seq(alice));
-
2345 txn[sfSigningPubKey] = strHex(alice.pk());
-
2346 STParsedJSONObject parsed("test", txn.getTxn());
-
2347 Serializer s;
-
2348 parsed.object->add(s);
-
2349 submitAndValidate(
-
2350 "SigningPubKey set",
-
2351 s.slice(),
-
2352 __LINE__,
- -
2354 "fails local checks: Invalid signature.");
-
2355 }
-
2356
-
2357 // Invalid RPC Submission: Signers
-
2358 // - has no `TxnSignature` field
-
2359 // + has empty `SigningPubKey` field
-
2360 // + has `Signers` field
-
2361 // + has `tfInnerBatchTxn` flag
-
2362 {
-
2363 auto txn = batch::inner(pay(alice, bob, XRP(1)), env.seq(alice));
-
2364 txn[sfSigners] = Json::arrayValue;
-
2365 STParsedJSONObject parsed("test", txn.getTxn());
-
2366 Serializer s;
-
2367 parsed.object->add(s);
-
2368 submitAndValidate(
-
2369 "Signers set",
-
2370 s.slice(),
-
2371 __LINE__,
- -
2373 "fails local checks: Invalid Signers array size.");
-
2374 }
-
2375
-
2376 {
-
2377 // Fully signed inner batch transaction
-
2378 auto const txn =
-
2379 batch::inner(pay(alice, bob, XRP(1)), env.seq(alice));
-
2380 auto const jt = env.jt(txn.getTxn());
-
2381
-
2382 STParsedJSONObject parsed("test", jt.jv);
-
2383 Serializer s;
-
2384 parsed.object->add(s);
-
2385 submitAndValidate(
-
2386 "Fully signed",
-
2387 s.slice(),
-
2388 __LINE__,
- - -
2391 !withBatch);
-
2392 }
-
2393
-
2394 // Invalid RPC Submission: tfInnerBatchTxn
-
2395 // - has no `TxnSignature` field
-
2396 // + has empty `SigningPubKey` field
-
2397 // - has no `Signers` field
-
2398 // + has `tfInnerBatchTxn` flag
-
2399 {
-
2400 auto txn = batch::inner(pay(alice, bob, XRP(1)), env.seq(alice));
-
2401 STParsedJSONObject parsed("test", txn.getTxn());
-
2402 Serializer s;
-
2403 parsed.object->add(s);
-
2404 submitAndValidate(
-
2405 "No signing fields set",
-
2406 s.slice(),
-
2407 __LINE__,
-
2408 "fails local checks: Empty SigningPubKey.",
-
2409 "fails local checks: Empty SigningPubKey.",
-
2410 withBatch && !withInnerSigFix);
-
2411 }
-
2412
-
2413 // Invalid RPC Submission: tfInnerBatchTxn pseudo-transaction
-
2414 // - has no `TxnSignature` field
-
2415 // + has empty `SigningPubKey` field
-
2416 // - has no `Signers` field
-
2417 // + has `tfInnerBatchTxn` flag
-
2418 {
-
2419 STTx amendTx(
-
2420 ttAMENDMENT, [seq = env.closed()->header().seq + 1](auto& obj) {
-
2421 obj.setAccountID(sfAccount, AccountID());
-
2422 obj.setFieldH256(sfAmendment, fixBatchInnerSigs);
-
2423 obj.setFieldU32(sfLedgerSequence, seq);
-
2424 obj.setFieldU32(sfFlags, tfInnerBatchTxn);
-
2425 });
-
2426 auto txn = batch::inner(
-
2427 amendTx.getJson(JsonOptions::none), env.seq(alice));
-
2428 STParsedJSONObject parsed("test", txn.getTxn());
-
2429 Serializer s;
-
2430 parsed.object->add(s);
-
2431 submitAndValidate(
-
2432 "Pseudo-transaction",
-
2433 s.slice(),
-
2434 __LINE__,
-
2435 withInnerSigFix
-
2436 ? "fails local checks: Empty SigningPubKey."
-
2437 : "fails local checks: Cannot submit pseudo transactions.",
-
2438 "fails local checks: Empty SigningPubKey.");
-
2439 }
-
2440 }
+
2271 auto const amend = withBatch ? features : features - featureBatch;
+
2272
+
2273 using namespace test::jtx;
+
2274 using namespace std::literals;
+
2275
+
2276 test::jtx::Env env{*this, amend};
+
2277 if (!BEAST_EXPECT(amend[featureBatch] == withBatch))
+
2278 return;
+
2279
+
2280 auto const alice = Account("alice");
+
2281 auto const bob = Account("bob");
+
2282
+
2283 env.fund(XRP(10000), alice, bob);
+
2284 env.close();
+
2285
+
2286 auto submitAndValidate =
+
2287 [&](std::string caseName,
+
2288 Slice const& slice,
+
2289 int line,
+
2290 std::optional<std::string> expectedEnabled = std::nullopt,
+
2291 std::optional<std::string> expectedDisabled = std::nullopt,
+
2292 bool expectInvalidFlag = false) {
+
2293 testcase << testName << caseName
+
2294 << (expectInvalidFlag
+
2295 ? " - Expected to reach tx engine!"
+
2296 : "");
+
2297 auto const jrr = env.rpc("submit", strHex(slice))[jss::result];
+
2298 auto const expected = withBatch
+
2299 ? expectedEnabled.value_or(
+
2300 "fails local checks: Malformed: Invalid inner batch "
+
2301 "transaction.")
+
2302 : expectedDisabled.value_or(
+
2303 "fails local checks: Empty SigningPubKey.");
+
2304 if (expectInvalidFlag)
+
2305 {
+
2306 expect(
+
2307 jrr[jss::status] == "success" &&
+
2308 jrr[jss::engine_result] == "temINVALID_FLAG",
+
2309 pretty(jrr),
+
2310 __FILE__,
+
2311 line);
+
2312 }
+
2313 else
+
2314 {
+
2315 expect(
+
2316 jrr[jss::status] == "error" &&
+
2317 jrr[jss::error] == "invalidTransaction" &&
+
2318 jrr[jss::error_exception] == expected,
+
2319 pretty(jrr),
+
2320 __FILE__,
+
2321 line);
+
2322 }
+
2323 env.close();
+
2324 };
+
2325
+
2326 // Invalid RPC Submission: TxnSignature
+
2327 // + has `TxnSignature` field
+
2328 // - has no `SigningPubKey` field
+
2329 // - has no `Signers` field
+
2330 // + has `tfInnerBatchTxn` flag
+
2331 {
+
2332 auto txn = batch::inner(pay(alice, bob, XRP(1)), env.seq(alice));
+
2333 txn[sfTxnSignature] = "DEADBEEF";
+
2334 STParsedJSONObject parsed("test", txn.getTxn());
+
2335 Serializer s;
+
2336 parsed.object->add(s);
+
2337 submitAndValidate("TxnSignature set", s.slice(), __LINE__);
+
2338 }
+
2339
+
2340 // Invalid RPC Submission: SigningPubKey
+
2341 // - has no `TxnSignature` field
+
2342 // + has `SigningPubKey` field
+
2343 // - has no `Signers` field
+
2344 // + has `tfInnerBatchTxn` flag
+
2345 {
+
2346 auto txn = batch::inner(pay(alice, bob, XRP(1)), env.seq(alice));
+
2347 txn[sfSigningPubKey] = strHex(alice.pk());
+
2348 STParsedJSONObject parsed("test", txn.getTxn());
+
2349 Serializer s;
+
2350 parsed.object->add(s);
+
2351 submitAndValidate(
+
2352 "SigningPubKey set",
+
2353 s.slice(),
+
2354 __LINE__,
+ +
2356 "fails local checks: Invalid signature.");
+
2357 }
+
2358
+
2359 // Invalid RPC Submission: Signers
+
2360 // - has no `TxnSignature` field
+
2361 // + has empty `SigningPubKey` field
+
2362 // + has `Signers` field
+
2363 // + has `tfInnerBatchTxn` flag
+
2364 {
+
2365 auto txn = batch::inner(pay(alice, bob, XRP(1)), env.seq(alice));
+
2366 txn[sfSigners] = Json::arrayValue;
+
2367 STParsedJSONObject parsed("test", txn.getTxn());
+
2368 Serializer s;
+
2369 parsed.object->add(s);
+
2370 submitAndValidate(
+
2371 "Signers set",
+
2372 s.slice(),
+
2373 __LINE__,
+ +
2375 "fails local checks: Invalid Signers array size.");
+
2376 }
+
2377
+
2378 {
+
2379 // Fully signed inner batch transaction
+
2380 auto const txn =
+
2381 batch::inner(pay(alice, bob, XRP(1)), env.seq(alice));
+
2382 auto const jt = env.jt(txn.getTxn());
+
2383
+
2384 STParsedJSONObject parsed("test", jt.jv);
+
2385 Serializer s;
+
2386 parsed.object->add(s);
+
2387 submitAndValidate(
+
2388 "Fully signed",
+
2389 s.slice(),
+
2390 __LINE__,
+ + +
2393 !withBatch);
+
2394 }
+
2395
+
2396 // Invalid RPC Submission: tfInnerBatchTxn
+
2397 // - has no `TxnSignature` field
+
2398 // + has empty `SigningPubKey` field
+
2399 // - has no `Signers` field
+
2400 // + has `tfInnerBatchTxn` flag
+
2401 {
+
2402 auto txn = batch::inner(pay(alice, bob, XRP(1)), env.seq(alice));
+
2403 STParsedJSONObject parsed("test", txn.getTxn());
+
2404 Serializer s;
+
2405 parsed.object->add(s);
+
2406 submitAndValidate(
+
2407 "No signing fields set",
+
2408 s.slice(),
+
2409 __LINE__,
+
2410 "fails local checks: Empty SigningPubKey.",
+
2411 "fails local checks: Empty SigningPubKey.",
+
2412 withBatch && !withInnerSigFix);
+
2413 }
+
2414
+
2415 // Invalid RPC Submission: tfInnerBatchTxn pseudo-transaction
+
2416 // - has no `TxnSignature` field
+
2417 // + has empty `SigningPubKey` field
+
2418 // - has no `Signers` field
+
2419 // + has `tfInnerBatchTxn` flag
+
2420 {
+
2421 STTx amendTx(
+
2422 ttAMENDMENT, [seq = env.closed()->header().seq + 1](auto& obj) {
+
2423 obj.setAccountID(sfAccount, AccountID());
+
2424 obj.setFieldH256(sfAmendment, fixBatchInnerSigs);
+
2425 obj.setFieldU32(sfLedgerSequence, seq);
+
2426 obj.setFieldU32(sfFlags, tfInnerBatchTxn);
+
2427 });
+
2428 auto txn = batch::inner(
+
2429 amendTx.getJson(JsonOptions::none), env.seq(alice));
+
2430 STParsedJSONObject parsed("test", txn.getTxn());
+
2431 Serializer s;
+
2432 parsed.object->add(s);
+
2433 submitAndValidate(
+
2434 "Pseudo-transaction",
+
2435 s.slice(),
+
2436 __LINE__,
+
2437 withInnerSigFix
+
2438 ? "fails local checks: Empty SigningPubKey."
+
2439 : "fails local checks: Cannot submit pseudo transactions.",
+
2440 "fails local checks: Empty SigningPubKey.");
+
2441 }
+
2442 }
-
2441
-
2442 void
-
- -
2444 {
-
2445 for (bool const withBatch : {true, false})
-
2446 {
-
2447 doTestInnerSubmitRPC(features, withBatch);
-
2448 }
-
2449 }
+
2443
+
2444 void
+
+ +
2446 {
+
2447 for (bool const withBatch : {true, false})
+
2448 {
+
2449 doTestInnerSubmitRPC(features, withBatch);
+
2450 }
+
2451 }
-
2450
-
2451 void
-
- -
2453 {
-
2454 testcase("account activation");
-
2455
-
2456 using namespace test::jtx;
-
2457 using namespace std::literals;
-
2458
-
2459 test::jtx::Env env{*this, features};
+
2452
+
2453 void
+
+ +
2455 {
+
2456 testcase("account activation");
+
2457
+
2458 using namespace test::jtx;
+
2459 using namespace std::literals;
2460
-
2461 auto const alice = Account("alice");
-
2462 auto const bob = Account("bob");
-
2463 env.fund(XRP(10000), alice);
-
2464 env.close();
-
2465 env.memoize(bob);
-
2466
-
2467 auto const preAlice = env.balance(alice);
-
2468 auto const ledSeq = env.current()->seq();
-
2469 auto const seq = env.seq(alice);
-
2470 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
2471 auto const [txIDs, batchID] = submitBatch(
-
2472 env,
-
2473 tesSUCCESS,
-
2474 batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
2475 batch::inner(pay(alice, bob, XRP(1000)), seq + 1),
- -
2477 batch::sig(bob));
-
2478 env.close();
-
2479
-
2480 std::vector<TestLedgerData> testCases = {
-
2481 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
2482 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
2483 {2, "AccountSet", "tesSUCCESS", txIDs[1], batchID},
-
2484 };
-
2485 validateClosedLedger(env, testCases);
-
2486
-
2487 // Alice consumes sequences (# of txns)
-
2488 BEAST_EXPECT(env.seq(alice) == seq + 2);
-
2489
-
2490 // Bob consumes sequences (# of txns)
-
2491 BEAST_EXPECT(env.seq(bob) == ledSeq + 1);
-
2492
-
2493 // Alice pays XRP & Fee; Bob receives XRP
-
2494 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(1000) - batchFee);
-
2495 BEAST_EXPECT(env.balance(bob) == XRP(1000));
-
2496 }
+
2461 test::jtx::Env env{*this, features};
+
2462
+
2463 auto const alice = Account("alice");
+
2464 auto const bob = Account("bob");
+
2465 env.fund(XRP(10000), alice);
+
2466 env.close();
+
2467 env.memoize(bob);
+
2468
+
2469 auto const preAlice = env.balance(alice);
+
2470 auto const ledSeq = env.current()->seq();
+
2471 auto const seq = env.seq(alice);
+
2472 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
2473 auto const [txIDs, batchID] = submitBatch(
+
2474 env,
+
2475 tesSUCCESS,
+
2476 batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
2477 batch::inner(pay(alice, bob, XRP(1000)), seq + 1),
+ +
2479 batch::sig(bob));
+
2480 env.close();
+
2481
+
2482 std::vector<TestLedgerData> testCases = {
+
2483 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
2484 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
2485 {2, "AccountSet", "tesSUCCESS", txIDs[1], batchID},
+
2486 };
+
2487 validateClosedLedger(env, testCases);
+
2488
+
2489 // Alice consumes sequences (# of txns)
+
2490 BEAST_EXPECT(env.seq(alice) == seq + 2);
+
2491
+
2492 // Bob consumes sequences (# of txns)
+
2493 BEAST_EXPECT(env.seq(bob) == ledSeq + 1);
+
2494
+
2495 // Alice pays XRP & Fee; Bob receives XRP
+
2496 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(1000) - batchFee);
+
2497 BEAST_EXPECT(env.balance(bob) == XRP(1000));
+
2498 }
-
2497
-
2498 void
-
- -
2500 {
-
2501 testcase("account set");
-
2502
-
2503 using namespace test::jtx;
-
2504 using namespace std::literals;
-
2505
-
2506 test::jtx::Env env{*this, features};
+
2499
+
2500 void
+
+ +
2502 {
+
2503 testcase("account set");
+
2504
+
2505 using namespace test::jtx;
+
2506 using namespace std::literals;
2507
-
2508 auto const alice = Account("alice");
-
2509 auto const bob = Account("bob");
-
2510 env.fund(XRP(10000), alice, bob);
-
2511 env.close();
-
2512
-
2513 auto const preAlice = env.balance(alice);
-
2514 auto const preBob = env.balance(bob);
-
2515
-
2516 auto const seq = env.seq(alice);
-
2517 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
2518 auto tx1 = batch::inner(noop(alice), seq + 1);
-
2519 std::string domain = "example.com";
-
2520 tx1[sfDomain] = strHex(domain);
-
2521 auto const [txIDs, batchID] = submitBatch(
-
2522 env,
-
2523 tesSUCCESS,
-
2524 batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
2525 tx1,
-
2526 batch::inner(pay(alice, bob, XRP(1)), seq + 2));
-
2527 env.close();
-
2528
-
2529 std::vector<TestLedgerData> testCases = {
-
2530 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
2531 {1, "AccountSet", "tesSUCCESS", txIDs[0], batchID},
-
2532 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
2533 };
-
2534 validateClosedLedger(env, testCases);
-
2535
-
2536 auto const sle = env.le(keylet::account(alice));
-
2537 BEAST_EXPECT(sle);
-
2538 BEAST_EXPECT(
-
2539 sle->getFieldVL(sfDomain) == Blob(domain.begin(), domain.end()));
-
2540
-
2541 // Alice consumes sequences (# of txns)
-
2542 BEAST_EXPECT(env.seq(alice) == seq + 3);
-
2543
-
2544 // Alice pays XRP & Fee; Bob receives XRP
-
2545 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(1) - batchFee);
-
2546 BEAST_EXPECT(env.balance(bob) == preBob + XRP(1));
-
2547 }
+
2508 test::jtx::Env env{*this, features};
+
2509
+
2510 auto const alice = Account("alice");
+
2511 auto const bob = Account("bob");
+
2512 env.fund(XRP(10000), alice, bob);
+
2513 env.close();
+
2514
+
2515 auto const preAlice = env.balance(alice);
+
2516 auto const preBob = env.balance(bob);
+
2517
+
2518 auto const seq = env.seq(alice);
+
2519 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
2520 auto tx1 = batch::inner(noop(alice), seq + 1);
+
2521 std::string domain = "example.com";
+
2522 tx1[sfDomain] = strHex(domain);
+
2523 auto const [txIDs, batchID] = submitBatch(
+
2524 env,
+
2525 tesSUCCESS,
+
2526 batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
2527 tx1,
+
2528 batch::inner(pay(alice, bob, XRP(1)), seq + 2));
+
2529 env.close();
+
2530
+
2531 std::vector<TestLedgerData> testCases = {
+
2532 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
2533 {1, "AccountSet", "tesSUCCESS", txIDs[0], batchID},
+
2534 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
2535 };
+
2536 validateClosedLedger(env, testCases);
+
2537
+
2538 auto const sle = env.le(keylet::account(alice));
+
2539 BEAST_EXPECT(sle);
+
2540 BEAST_EXPECT(
+
2541 sle->getFieldVL(sfDomain) == Blob(domain.begin(), domain.end()));
+
2542
+
2543 // Alice consumes sequences (# of txns)
+
2544 BEAST_EXPECT(env.seq(alice) == seq + 3);
+
2545
+
2546 // Alice pays XRP & Fee; Bob receives XRP
+
2547 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(1) - batchFee);
+
2548 BEAST_EXPECT(env.balance(bob) == preBob + XRP(1));
+
2549 }
-
2548
-
2549 void
-
- -
2551 {
-
2552 testcase("account delete");
-
2553
-
2554 using namespace test::jtx;
-
2555 using namespace std::literals;
-
2556
-
2557 // tfIndependent: account delete success
-
2558 {
-
2559 test::jtx::Env env{*this, features};
-
2560
-
2561 auto const alice = Account("alice");
-
2562 auto const bob = Account("bob");
-
2563 env.fund(XRP(10000), alice, bob);
-
2564 env.close();
-
2565
-
2566 incLgrSeqForAccDel(env, alice);
-
2567 for (int i = 0; i < 5; ++i)
-
2568 env.close();
-
2569
-
2570 auto const preAlice = env.balance(alice);
-
2571 auto const preBob = env.balance(bob);
-
2572
-
2573 auto const seq = env.seq(alice);
-
2574 auto const batchFee = batch::calcBatchFee(env, 0, 2) +
-
2575 env.current()->fees().increment;
-
2576 auto const [txIDs, batchID] = submitBatch(
-
2577 env,
-
2578 tesSUCCESS,
-
2579 batch::outer(alice, seq, batchFee, tfIndependent),
-
2580 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
2581 batch::inner(acctdelete(alice, bob), seq + 2),
-
2582 // terNO_ACCOUNT: alice does not exist
-
2583 batch::inner(pay(alice, bob, XRP(2)), seq + 3));
-
2584 env.close();
-
2585
-
2586 std::vector<TestLedgerData> testCases = {
-
2587 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
2588 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
2589 {2, "AccountDelete", "tesSUCCESS", txIDs[1], batchID},
-
2590 };
-
2591 validateClosedLedger(env, testCases);
-
2592
-
2593 // Alice does not exist; Bob receives Alice's XRP
-
2594 BEAST_EXPECT(!env.le(keylet::account(alice)));
-
2595 BEAST_EXPECT(env.balance(bob) == preBob + (preAlice - batchFee));
-
2596 }
-
2597
-
2598 // tfIndependent: account delete fails
-
2599 {
-
2600 test::jtx::Env env{*this, features};
-
2601
-
2602 auto const alice = Account("alice");
-
2603 auto const bob = Account("bob");
-
2604 env.fund(XRP(10000), alice, bob);
-
2605 env.close();
-
2606
-
2607 incLgrSeqForAccDel(env, alice);
-
2608 for (int i = 0; i < 5; ++i)
-
2609 env.close();
-
2610
-
2611 auto const preAlice = env.balance(alice);
-
2612 auto const preBob = env.balance(bob);
-
2613
-
2614 env.trust(bob["USD"](1000), alice);
-
2615 env.close();
-
2616
-
2617 auto const seq = env.seq(alice);
-
2618 auto const batchFee = batch::calcBatchFee(env, 0, 2) +
-
2619 env.current()->fees().increment;
-
2620 auto const [txIDs, batchID] = submitBatch(
-
2621 env,
-
2622 tesSUCCESS,
-
2623 batch::outer(alice, seq, batchFee, tfIndependent),
-
2624 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
2625 // tecHAS_OBLIGATIONS: alice has obligations
-
2626 batch::inner(acctdelete(alice, bob), seq + 2),
-
2627 batch::inner(pay(alice, bob, XRP(2)), seq + 3));
-
2628 env.close();
-
2629
-
2630 std::vector<TestLedgerData> testCases = {
-
2631 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
2632 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
2633 {2, "AccountDelete", "tecHAS_OBLIGATIONS", txIDs[1], batchID},
-
2634 {3, "Payment", "tesSUCCESS", txIDs[2], batchID},
-
2635 };
-
2636 validateClosedLedger(env, testCases);
-
2637
-
2638 // Alice does not exist; Bob receives XRP
-
2639 BEAST_EXPECT(env.le(keylet::account(alice)));
-
2640 BEAST_EXPECT(env.balance(bob) == preBob + XRP(3));
-
2641 }
-
2642
-
2643 // tfAllOrNothing: account delete fails
-
2644 {
-
2645 test::jtx::Env env{*this, features};
-
2646
-
2647 auto const alice = Account("alice");
-
2648 auto const bob = Account("bob");
-
2649 env.fund(XRP(10000), alice, bob);
-
2650 env.close();
-
2651
-
2652 incLgrSeqForAccDel(env, alice);
-
2653 for (int i = 0; i < 5; ++i)
-
2654 env.close();
-
2655
-
2656 auto const preAlice = env.balance(alice);
-
2657 auto const preBob = env.balance(bob);
-
2658
-
2659 auto const seq = env.seq(alice);
-
2660 auto const batchFee = batch::calcBatchFee(env, 0, 2) +
-
2661 env.current()->fees().increment;
-
2662 auto const [txIDs, batchID] = submitBatch(
-
2663 env,
-
2664 tesSUCCESS,
-
2665 batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
2666 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
2667 batch::inner(acctdelete(alice, bob), seq + 2),
-
2668 // terNO_ACCOUNT: alice does not exist
-
2669 batch::inner(pay(alice, bob, XRP(2)), seq + 3));
-
2670 env.close();
-
2671
-
2672 std::vector<TestLedgerData> testCases = {
-
2673 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
2674 };
-
2675 validateClosedLedger(env, testCases);
-
2676
-
2677 // Alice still exists; Bob is unchanged
-
2678 BEAST_EXPECT(env.le(keylet::account(alice)));
-
2679 BEAST_EXPECT(env.balance(bob) == preBob);
-
2680 }
-
2681 }
+
2550
+
2551 void
+
+ +
2553 {
+
2554 testcase("account delete");
+
2555
+
2556 using namespace test::jtx;
+
2557 using namespace std::literals;
+
2558
+
2559 // tfIndependent: account delete success
+
2560 {
+
2561 test::jtx::Env env{*this, features};
+
2562
+
2563 auto const alice = Account("alice");
+
2564 auto const bob = Account("bob");
+
2565 env.fund(XRP(10000), alice, bob);
+
2566 env.close();
+
2567
+
2568 incLgrSeqForAccDel(env, alice);
+
2569 for (int i = 0; i < 5; ++i)
+
2570 env.close();
+
2571
+
2572 auto const preAlice = env.balance(alice);
+
2573 auto const preBob = env.balance(bob);
+
2574
+
2575 auto const seq = env.seq(alice);
+
2576 auto const batchFee = batch::calcBatchFee(env, 0, 2) +
+
2577 env.current()->fees().increment;
+
2578 auto const [txIDs, batchID] = submitBatch(
+
2579 env,
+
2580 tesSUCCESS,
+
2581 batch::outer(alice, seq, batchFee, tfIndependent),
+
2582 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
2583 batch::inner(acctdelete(alice, bob), seq + 2),
+
2584 // terNO_ACCOUNT: alice does not exist
+
2585 batch::inner(pay(alice, bob, XRP(2)), seq + 3));
+
2586 env.close();
+
2587
+
2588 std::vector<TestLedgerData> testCases = {
+
2589 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
2590 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
2591 {2, "AccountDelete", "tesSUCCESS", txIDs[1], batchID},
+
2592 };
+
2593 validateClosedLedger(env, testCases);
+
2594
+
2595 // Alice does not exist; Bob receives Alice's XRP
+
2596 BEAST_EXPECT(!env.le(keylet::account(alice)));
+
2597 BEAST_EXPECT(env.balance(bob) == preBob + (preAlice - batchFee));
+
2598 }
+
2599
+
2600 // tfIndependent: account delete fails
+
2601 {
+
2602 test::jtx::Env env{*this, features};
+
2603
+
2604 auto const alice = Account("alice");
+
2605 auto const bob = Account("bob");
+
2606 env.fund(XRP(10000), alice, bob);
+
2607 env.close();
+
2608
+
2609 incLgrSeqForAccDel(env, alice);
+
2610 for (int i = 0; i < 5; ++i)
+
2611 env.close();
+
2612
+
2613 auto const preAlice = env.balance(alice);
+
2614 auto const preBob = env.balance(bob);
+
2615
+
2616 env.trust(bob["USD"](1000), alice);
+
2617 env.close();
+
2618
+
2619 auto const seq = env.seq(alice);
+
2620 auto const batchFee = batch::calcBatchFee(env, 0, 2) +
+
2621 env.current()->fees().increment;
+
2622 auto const [txIDs, batchID] = submitBatch(
+
2623 env,
+
2624 tesSUCCESS,
+
2625 batch::outer(alice, seq, batchFee, tfIndependent),
+
2626 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
2627 // tecHAS_OBLIGATIONS: alice has obligations
+
2628 batch::inner(acctdelete(alice, bob), seq + 2),
+
2629 batch::inner(pay(alice, bob, XRP(2)), seq + 3));
+
2630 env.close();
+
2631
+
2632 std::vector<TestLedgerData> testCases = {
+
2633 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
2634 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
2635 {2, "AccountDelete", "tecHAS_OBLIGATIONS", txIDs[1], batchID},
+
2636 {3, "Payment", "tesSUCCESS", txIDs[2], batchID},
+
2637 };
+
2638 validateClosedLedger(env, testCases);
+
2639
+
2640 // Alice does not exist; Bob receives XRP
+
2641 BEAST_EXPECT(env.le(keylet::account(alice)));
+
2642 BEAST_EXPECT(env.balance(bob) == preBob + XRP(3));
+
2643 }
+
2644
+
2645 // tfAllOrNothing: account delete fails
+
2646 {
+
2647 test::jtx::Env env{*this, features};
+
2648
+
2649 auto const alice = Account("alice");
+
2650 auto const bob = Account("bob");
+
2651 env.fund(XRP(10000), alice, bob);
+
2652 env.close();
+
2653
+
2654 incLgrSeqForAccDel(env, alice);
+
2655 for (int i = 0; i < 5; ++i)
+
2656 env.close();
+
2657
+
2658 auto const preAlice = env.balance(alice);
+
2659 auto const preBob = env.balance(bob);
+
2660
+
2661 auto const seq = env.seq(alice);
+
2662 auto const batchFee = batch::calcBatchFee(env, 0, 2) +
+
2663 env.current()->fees().increment;
+
2664 auto const [txIDs, batchID] = submitBatch(
+
2665 env,
+
2666 tesSUCCESS,
+
2667 batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
2668 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
2669 batch::inner(acctdelete(alice, bob), seq + 2),
+
2670 // terNO_ACCOUNT: alice does not exist
+
2671 batch::inner(pay(alice, bob, XRP(2)), seq + 3));
+
2672 env.close();
+
2673
+
2674 std::vector<TestLedgerData> testCases = {
+
2675 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
2676 };
+
2677 validateClosedLedger(env, testCases);
+
2678
+
2679 // Alice still exists; Bob is unchanged
+
2680 BEAST_EXPECT(env.le(keylet::account(alice)));
+
2681 BEAST_EXPECT(env.balance(bob) == preBob);
+
2682 }
+
2683 }
-
2682
-
2683 void
-
- -
2685 {
-
2686 testcase("loan");
-
2687
-
2688 bool const lendingBatchEnabled = !std::any_of(
-
2689 Batch::disabledTxTypes.begin(),
- -
2691 [](auto const& disabled) { return disabled == ttLOAN_BROKER_SET; });
-
2692
-
2693 using namespace test::jtx;
+
2684
+
2685 void
+
+ +
2687 {
+
2688 testcase("loan");
+
2689
+
2690 bool const lendingBatchEnabled = !std::any_of(
+
2691 Batch::disabledTxTypes.begin(),
+ +
2693 [](auto const& disabled) { return disabled == ttLOAN_BROKER_SET; });
2694
-
2695 test::jtx::Env env{
-
2696 *this,
-
2697 features | featureSingleAssetVault | featureLendingProtocol |
-
2698 featureMPTokensV1};
-
2699
-
2700 Account const issuer{"issuer"};
-
2701 // For simplicity, lender will be the sole actor for the vault &
-
2702 // brokers.
-
2703 Account const lender{"lender"};
-
2704 // Borrower only wants to borrow
-
2705 Account const borrower{"borrower"};
-
2706
-
2707 // Fund the accounts and trust lines with the same amount so that tests
-
2708 // can use the same values regardless of the asset.
-
2709 env.fund(XRP(100'000), issuer, noripple(lender, borrower));
-
2710 env.close();
-
2711
-
2712 // Just use an XRP asset
-
2713 PrettyAsset const asset{xrpIssue(), 1'000'000};
-
2714
-
2715 Vault vault{env};
+
2695 using namespace test::jtx;
+
2696
+
2697 test::jtx::Env env{
+
2698 *this,
+
2699 features | featureSingleAssetVault | featureLendingProtocol |
+
2700 featureMPTokensV1};
+
2701
+
2702 Account const issuer{"issuer"};
+
2703 // For simplicity, lender will be the sole actor for the vault &
+
2704 // brokers.
+
2705 Account const lender{"lender"};
+
2706 // Borrower only wants to borrow
+
2707 Account const borrower{"borrower"};
+
2708
+
2709 // Fund the accounts and trust lines with the same amount so that tests
+
2710 // can use the same values regardless of the asset.
+
2711 env.fund(XRP(100'000), issuer, noripple(lender, borrower));
+
2712 env.close();
+
2713
+
2714 // Just use an XRP asset
+
2715 PrettyAsset const asset{xrpIssue(), 1'000'000};
2716
-
2717 auto const deposit = asset(50'000);
-
2718 auto const debtMaximumValue = asset(25'000).value();
-
2719 auto const coverDepositValue = asset(1000).value();
-
2720
-
2721 auto [tx, vaultKeylet] =
-
2722 vault.create({.owner = lender, .asset = asset});
-
2723 env(tx);
-
2724 env.close();
-
2725 BEAST_EXPECT(env.le(vaultKeylet));
-
2726
-
2727 env(vault.deposit(
-
2728 {.depositor = lender, .id = vaultKeylet.key, .amount = deposit}));
-
2729 env.close();
-
2730
-
2731 auto const brokerKeylet =
-
2732 keylet::loanbroker(lender.id(), env.seq(lender));
-
2733
-
2734 {
-
2735 using namespace loanBroker;
-
2736 env(set(lender, vaultKeylet.key),
-
2737 managementFeeRate(TenthBips16(100)),
-
2738 debtMaximum(debtMaximumValue),
-
2739 coverRateMinimum(TenthBips32(percentageToTenthBips(10))),
-
2740 coverRateLiquidation(TenthBips32(percentageToTenthBips(25))));
-
2741
-
2742 env(coverDeposit(lender, brokerKeylet.key, coverDepositValue));
+
2717 Vault vault{env};
+
2718
+
2719 auto const deposit = asset(50'000);
+
2720 auto const debtMaximumValue = asset(25'000).value();
+
2721 auto const coverDepositValue = asset(1000).value();
+
2722
+
2723 auto [tx, vaultKeylet] =
+
2724 vault.create({.owner = lender, .asset = asset});
+
2725 env(tx);
+
2726 env.close();
+
2727 BEAST_EXPECT(env.le(vaultKeylet));
+
2728
+
2729 env(vault.deposit(
+
2730 {.depositor = lender, .id = vaultKeylet.key, .amount = deposit}));
+
2731 env.close();
+
2732
+
2733 auto const brokerKeylet =
+
2734 keylet::loanbroker(lender.id(), env.seq(lender));
+
2735
+
2736 {
+
2737 using namespace loanBroker;
+
2738 env(set(lender, vaultKeylet.key),
+
2739 managementFeeRate(TenthBips16(100)),
+
2740 debtMaximum(debtMaximumValue),
+
2741 coverRateMinimum(TenthBips32(percentageToTenthBips(10))),
+
2742 coverRateLiquidation(TenthBips32(percentageToTenthBips(25))));
2743
-
2744 env.close();
-
2745 }
-
2746
-
2747 {
-
2748 using namespace loan;
-
2749 using namespace std::chrono_literals;
-
2750
-
2751 auto const lenderSeq = env.seq(lender);
-
2752 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
2753
-
2754 auto const loanKeylet = keylet::loan(brokerKeylet.key, 1);
-
2755 {
-
2756 auto const [txIDs, batchID] = submitBatch(
-
2757 env,
-
2758 lendingBatchEnabled ? temBAD_SIGNATURE
- -
2760 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
- -
2762 env.json(
-
2763 set(lender, brokerKeylet.key, asset(1000).value()),
-
2764 // Not allowed to include the counterparty signature
-
2765 sig(sfCounterpartySignature, borrower),
-
2766 sig(none),
-
2767 fee(none),
-
2768 seq(none)),
-
2769 lenderSeq + 1),
- -
2771 pay(lender,
-
2772 loanKeylet.key,
-
2773 STAmount{asset, asset(500).value()}),
-
2774 lenderSeq + 2));
-
2775 }
-
2776 {
-
2777 auto const [txIDs, batchID] = submitBatch(
-
2778 env,
- -
2780 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
- -
2782 env.json(
-
2783 set(lender, brokerKeylet.key, asset(1000).value()),
-
2784 // Counterparty must be set
-
2785 sig(none),
-
2786 fee(none),
-
2787 seq(none)),
-
2788 lenderSeq + 1),
- -
2790 pay(lender,
-
2791 loanKeylet.key,
-
2792 STAmount{asset, asset(500).value()}),
-
2793 lenderSeq + 2));
-
2794 }
-
2795 {
-
2796 auto const [txIDs, batchID] = submitBatch(
-
2797 env,
-
2798 lendingBatchEnabled ? temBAD_SIGNER
- -
2800 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
- -
2802 env.json(
-
2803 set(lender, brokerKeylet.key, asset(1000).value()),
-
2804 // Counterparty must sign the outer transaction
-
2805 counterparty(borrower.id()),
-
2806 sig(none),
-
2807 fee(none),
-
2808 seq(none)),
-
2809 lenderSeq + 1),
- -
2811 pay(lender,
-
2812 loanKeylet.key,
-
2813 STAmount{asset, asset(500).value()}),
-
2814 lenderSeq + 2));
-
2815 }
-
2816 {
-
2817 // LoanSet normally charges at least 2x base fee, but since the
-
2818 // signature check is done by the batch, it only charges the
-
2819 // base fee.
-
2820 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
2821 auto const [txIDs, batchID] = submitBatch(
-
2822 env,
-
2823 lendingBatchEnabled ? TER(tesSUCCESS)
- -
2825 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
- -
2827 env.json(
-
2828 set(lender, brokerKeylet.key, asset(1000).value()),
-
2829 counterparty(borrower.id()),
-
2830 sig(none),
-
2831 fee(none),
-
2832 seq(none)),
-
2833 lenderSeq + 1),
- -
2835 pay(
-
2836 // However, this inner transaction will fail,
-
2837 // because the lender is not allowed to draw the
-
2838 // transaction
-
2839 lender,
-
2840 loanKeylet.key,
-
2841 STAmount{asset, asset(500).value()}),
-
2842 lenderSeq + 2),
-
2843 batch::sig(borrower));
-
2844 }
-
2845 env.close();
-
2846 BEAST_EXPECT(env.le(brokerKeylet));
-
2847 BEAST_EXPECT(!env.le(loanKeylet));
-
2848 {
-
2849 // LoanSet normally charges at least 2x base fee, but since the
-
2850 // signature check is done by the batch, it only charges the
-
2851 // base fee.
-
2852 auto const lenderSeq = env.seq(lender);
-
2853 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
2854 auto const [txIDs, batchID] = submitBatch(
-
2855 env,
-
2856 lendingBatchEnabled ? TER(tesSUCCESS)
- -
2858 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
- -
2860 env.json(
-
2861 set(lender, brokerKeylet.key, asset(1000).value()),
-
2862 counterparty(borrower.id()),
-
2863 sig(none),
-
2864 fee(none),
-
2865 seq(none)),
-
2866 lenderSeq + 1),
- -
2868 manage(lender, loanKeylet.key, tfLoanImpair),
-
2869 lenderSeq + 2),
-
2870 batch::sig(borrower));
-
2871 }
-
2872 env.close();
-
2873 BEAST_EXPECT(env.le(brokerKeylet));
-
2874 if (auto const sleLoan = env.le(loanKeylet); lendingBatchEnabled
-
2875 ? BEAST_EXPECT(sleLoan)
-
2876 : !BEAST_EXPECT(!sleLoan))
-
2877 {
-
2878 BEAST_EXPECT(sleLoan->isFlag(lsfLoanImpaired));
-
2879 }
-
2880 }
-
2881 }
+
2744 env(coverDeposit(lender, brokerKeylet.key, coverDepositValue));
+
2745
+
2746 env.close();
+
2747 }
+
2748
+
2749 {
+
2750 using namespace loan;
+
2751 using namespace std::chrono_literals;
+
2752
+
2753 auto const lenderSeq = env.seq(lender);
+
2754 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
2755
+
2756 auto const loanKeylet = keylet::loan(brokerKeylet.key, 1);
+
2757 {
+
2758 auto const [txIDs, batchID] = submitBatch(
+
2759 env,
+
2760 lendingBatchEnabled ? temBAD_SIGNATURE
+ +
2762 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
+ +
2764 env.json(
+
2765 set(lender, brokerKeylet.key, asset(1000).value()),
+
2766 // Not allowed to include the counterparty signature
+
2767 sig(sfCounterpartySignature, borrower),
+
2768 sig(none),
+
2769 fee(none),
+
2770 seq(none)),
+
2771 lenderSeq + 1),
+ +
2773 pay(lender,
+
2774 loanKeylet.key,
+
2775 STAmount{asset, asset(500).value()}),
+
2776 lenderSeq + 2));
+
2777 }
+
2778 {
+
2779 auto const [txIDs, batchID] = submitBatch(
+
2780 env,
+ +
2782 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
+ +
2784 env.json(
+
2785 set(lender, brokerKeylet.key, asset(1000).value()),
+
2786 // Counterparty must be set
+
2787 sig(none),
+
2788 fee(none),
+
2789 seq(none)),
+
2790 lenderSeq + 1),
+ +
2792 pay(lender,
+
2793 loanKeylet.key,
+
2794 STAmount{asset, asset(500).value()}),
+
2795 lenderSeq + 2));
+
2796 }
+
2797 {
+
2798 auto const [txIDs, batchID] = submitBatch(
+
2799 env,
+
2800 lendingBatchEnabled ? temBAD_SIGNER
+ +
2802 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
+ +
2804 env.json(
+
2805 set(lender, brokerKeylet.key, asset(1000).value()),
+
2806 // Counterparty must sign the outer transaction
+
2807 counterparty(borrower.id()),
+
2808 sig(none),
+
2809 fee(none),
+
2810 seq(none)),
+
2811 lenderSeq + 1),
+ +
2813 pay(lender,
+
2814 loanKeylet.key,
+
2815 STAmount{asset, asset(500).value()}),
+
2816 lenderSeq + 2));
+
2817 }
+
2818 {
+
2819 // LoanSet normally charges at least 2x base fee, but since the
+
2820 // signature check is done by the batch, it only charges the
+
2821 // base fee.
+
2822 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
2823 auto const [txIDs, batchID] = submitBatch(
+
2824 env,
+
2825 lendingBatchEnabled ? TER(tesSUCCESS)
+ +
2827 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
+ +
2829 env.json(
+
2830 set(lender, brokerKeylet.key, asset(1000).value()),
+
2831 counterparty(borrower.id()),
+
2832 sig(none),
+
2833 fee(none),
+
2834 seq(none)),
+
2835 lenderSeq + 1),
+ +
2837 pay(
+
2838 // However, this inner transaction will fail,
+
2839 // because the lender is not allowed to draw the
+
2840 // transaction
+
2841 lender,
+
2842 loanKeylet.key,
+
2843 STAmount{asset, asset(500).value()}),
+
2844 lenderSeq + 2),
+
2845 batch::sig(borrower));
+
2846 }
+
2847 env.close();
+
2848 BEAST_EXPECT(env.le(brokerKeylet));
+
2849 BEAST_EXPECT(!env.le(loanKeylet));
+
2850 {
+
2851 // LoanSet normally charges at least 2x base fee, but since the
+
2852 // signature check is done by the batch, it only charges the
+
2853 // base fee.
+
2854 auto const lenderSeq = env.seq(lender);
+
2855 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
2856 auto const [txIDs, batchID] = submitBatch(
+
2857 env,
+
2858 lendingBatchEnabled ? TER(tesSUCCESS)
+ +
2860 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
+ +
2862 env.json(
+
2863 set(lender, brokerKeylet.key, asset(1000).value()),
+
2864 counterparty(borrower.id()),
+
2865 sig(none),
+
2866 fee(none),
+
2867 seq(none)),
+
2868 lenderSeq + 1),
+ +
2870 manage(lender, loanKeylet.key, tfLoanImpair),
+
2871 lenderSeq + 2),
+
2872 batch::sig(borrower));
+
2873 }
+
2874 env.close();
+
2875 BEAST_EXPECT(env.le(brokerKeylet));
+
2876 if (auto const sleLoan = env.le(loanKeylet); lendingBatchEnabled
+
2877 ? BEAST_EXPECT(sleLoan)
+
2878 : !BEAST_EXPECT(!sleLoan))
+
2879 {
+
2880 BEAST_EXPECT(sleLoan->isFlag(lsfLoanImpaired));
+
2881 }
+
2882 }
+
2883 }
-
2882
-
2883 void
-
- -
2885 {
-
2886 testcase("object create w/ sequence");
-
2887
-
2888 using namespace test::jtx;
-
2889 using namespace std::literals;
-
2890
-
2891 test::jtx::Env env{*this, features};
+
2884
+
2885 void
+
+ +
2887 {
+
2888 testcase("object create w/ sequence");
+
2889
+
2890 using namespace test::jtx;
+
2891 using namespace std::literals;
2892
-
2893 auto const alice = Account("alice");
-
2894 auto const bob = Account("bob");
-
2895 auto const gw = Account("gw");
-
2896 auto const USD = gw["USD"];
-
2897
-
2898 env.fund(XRP(10000), alice, bob, gw);
-
2899 env.close();
-
2900
-
2901 env.trust(USD(1000), alice, bob);
-
2902 env(pay(gw, alice, USD(100)));
-
2903 env(pay(gw, bob, USD(100)));
-
2904 env.close();
-
2905
-
2906 // success
-
2907 {
-
2908 auto const aliceSeq = env.seq(alice);
-
2909 auto const bobSeq = env.seq(bob);
-
2910 auto const preAlice = env.balance(alice);
-
2911 auto const preBob = env.balance(bob);
-
2912 auto const preAliceUSD = env.balance(alice, USD.issue());
-
2913 auto const preBobUSD = env.balance(bob, USD.issue());
-
2914
-
2915 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
2916 uint256 const chkID{getCheckIndex(bob, env.seq(bob))};
-
2917 auto const [txIDs, batchID] = submitBatch(
-
2918 env,
-
2919 tesSUCCESS,
-
2920 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
-
2921 batch::inner(check::create(bob, alice, USD(10)), bobSeq),
-
2922 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq + 1),
-
2923 batch::sig(bob));
-
2924 env.close();
-
2925
-
2926 std::vector<TestLedgerData> testCases = {
-
2927 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
2928 {1, "CheckCreate", "tesSUCCESS", txIDs[0], batchID},
-
2929 {2, "CheckCash", "tesSUCCESS", txIDs[1], batchID},
-
2930 };
-
2931 validateClosedLedger(env, testCases);
-
2932
-
2933 // Alice consumes sequences (# of txns)
-
2934 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
-
2935
-
2936 // Alice consumes sequences (# of txns)
-
2937 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
-
2938
-
2939 // Alice pays Fee; Bob XRP Unchanged
-
2940 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
-
2941 BEAST_EXPECT(env.balance(bob) == preBob);
-
2942
-
2943 // Alice pays USD & Bob receives USD
-
2944 BEAST_EXPECT(
-
2945 env.balance(alice, USD.issue()) == preAliceUSD + USD(10));
-
2946 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD - USD(10));
-
2947 }
-
2948
-
2949 // failure
-
2950 {
-
2951 env(fset(alice, asfRequireDest));
-
2952 env.close();
-
2953
-
2954 auto const aliceSeq = env.seq(alice);
-
2955 auto const bobSeq = env.seq(bob);
-
2956 auto const preAlice = env.balance(alice);
-
2957 auto const preBob = env.balance(bob);
-
2958 auto const preAliceUSD = env.balance(alice, USD.issue());
-
2959 auto const preBobUSD = env.balance(bob, USD.issue());
-
2960
-
2961 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
2962 uint256 const chkID{getCheckIndex(bob, env.seq(bob))};
-
2963 auto const [txIDs, batchID] = submitBatch(
-
2964 env,
-
2965 tesSUCCESS,
-
2966 batch::outer(alice, aliceSeq, batchFee, tfIndependent),
-
2967 // tecDST_TAG_NEEDED - alice has enabled asfRequireDest
-
2968 batch::inner(check::create(bob, alice, USD(10)), bobSeq),
-
2969 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq + 1),
-
2970 batch::sig(bob));
-
2971 env.close();
-
2972
-
2973 std::vector<TestLedgerData> testCases = {
-
2974 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
2975 {1, "CheckCreate", "tecDST_TAG_NEEDED", txIDs[0], batchID},
-
2976 {2, "CheckCash", "tecNO_ENTRY", txIDs[1], batchID},
-
2977 };
-
2978 validateClosedLedger(env, testCases);
-
2979
-
2980 // Alice consumes sequences (# of txns)
-
2981 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
-
2982
-
2983 // Bob consumes sequences (# of txns)
-
2984 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
-
2985
-
2986 // Alice pays Fee; Bob XRP Unchanged
-
2987 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
-
2988 BEAST_EXPECT(env.balance(bob) == preBob);
-
2989
-
2990 // Alice pays USD & Bob receives USD
-
2991 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
-
2992 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
-
2993 }
-
2994 }
+
2893 test::jtx::Env env{*this, features};
+
2894
+
2895 auto const alice = Account("alice");
+
2896 auto const bob = Account("bob");
+
2897 auto const gw = Account("gw");
+
2898 auto const USD = gw["USD"];
+
2899
+
2900 env.fund(XRP(10000), alice, bob, gw);
+
2901 env.close();
+
2902
+
2903 env.trust(USD(1000), alice, bob);
+
2904 env(pay(gw, alice, USD(100)));
+
2905 env(pay(gw, bob, USD(100)));
+
2906 env.close();
+
2907
+
2908 // success
+
2909 {
+
2910 auto const aliceSeq = env.seq(alice);
+
2911 auto const bobSeq = env.seq(bob);
+
2912 auto const preAlice = env.balance(alice);
+
2913 auto const preBob = env.balance(bob);
+
2914 auto const preAliceUSD = env.balance(alice, USD.issue());
+
2915 auto const preBobUSD = env.balance(bob, USD.issue());
+
2916
+
2917 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
2918 uint256 const chkID{getCheckIndex(bob, env.seq(bob))};
+
2919 auto const [txIDs, batchID] = submitBatch(
+
2920 env,
+
2921 tesSUCCESS,
+
2922 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
+
2923 batch::inner(check::create(bob, alice, USD(10)), bobSeq),
+
2924 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq + 1),
+
2925 batch::sig(bob));
+
2926 env.close();
+
2927
+
2928 std::vector<TestLedgerData> testCases = {
+
2929 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
2930 {1, "CheckCreate", "tesSUCCESS", txIDs[0], batchID},
+
2931 {2, "CheckCash", "tesSUCCESS", txIDs[1], batchID},
+
2932 };
+
2933 validateClosedLedger(env, testCases);
+
2934
+
2935 // Alice consumes sequences (# of txns)
+
2936 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
+
2937
+
2938 // Alice consumes sequences (# of txns)
+
2939 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
+
2940
+
2941 // Alice pays Fee; Bob XRP Unchanged
+
2942 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
+
2943 BEAST_EXPECT(env.balance(bob) == preBob);
+
2944
+
2945 // Alice pays USD & Bob receives USD
+
2946 BEAST_EXPECT(
+
2947 env.balance(alice, USD.issue()) == preAliceUSD + USD(10));
+
2948 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD - USD(10));
+
2949 }
+
2950
+
2951 // failure
+
2952 {
+
2953 env(fset(alice, asfRequireDest));
+
2954 env.close();
+
2955
+
2956 auto const aliceSeq = env.seq(alice);
+
2957 auto const bobSeq = env.seq(bob);
+
2958 auto const preAlice = env.balance(alice);
+
2959 auto const preBob = env.balance(bob);
+
2960 auto const preAliceUSD = env.balance(alice, USD.issue());
+
2961 auto const preBobUSD = env.balance(bob, USD.issue());
+
2962
+
2963 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
2964 uint256 const chkID{getCheckIndex(bob, env.seq(bob))};
+
2965 auto const [txIDs, batchID] = submitBatch(
+
2966 env,
+
2967 tesSUCCESS,
+
2968 batch::outer(alice, aliceSeq, batchFee, tfIndependent),
+
2969 // tecDST_TAG_NEEDED - alice has enabled asfRequireDest
+
2970 batch::inner(check::create(bob, alice, USD(10)), bobSeq),
+
2971 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq + 1),
+
2972 batch::sig(bob));
+
2973 env.close();
+
2974
+
2975 std::vector<TestLedgerData> testCases = {
+
2976 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
2977 {1, "CheckCreate", "tecDST_TAG_NEEDED", txIDs[0], batchID},
+
2978 {2, "CheckCash", "tecNO_ENTRY", txIDs[1], batchID},
+
2979 };
+
2980 validateClosedLedger(env, testCases);
+
2981
+
2982 // Alice consumes sequences (# of txns)
+
2983 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
+
2984
+
2985 // Bob consumes sequences (# of txns)
+
2986 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
+
2987
+
2988 // Alice pays Fee; Bob XRP Unchanged
+
2989 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
+
2990 BEAST_EXPECT(env.balance(bob) == preBob);
+
2991
+
2992 // Alice pays USD & Bob receives USD
+
2993 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
+
2994 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
+
2995 }
+
2996 }
-
2995
-
2996 void
-
- -
2998 {
-
2999 testcase("object create w/ ticket");
-
3000
-
3001 using namespace test::jtx;
-
3002 using namespace std::literals;
-
3003
-
3004 test::jtx::Env env{*this, features};
+
2997
+
2998 void
+
+ +
3000 {
+
3001 testcase("object create w/ ticket");
+
3002
+
3003 using namespace test::jtx;
+
3004 using namespace std::literals;
3005
-
3006 auto const alice = Account("alice");
-
3007 auto const bob = Account("bob");
-
3008 auto const gw = Account("gw");
-
3009 auto const USD = gw["USD"];
-
3010
-
3011 env.fund(XRP(10000), alice, bob, gw);
-
3012 env.close();
-
3013
-
3014 env.trust(USD(1000), alice, bob);
-
3015 env(pay(gw, alice, USD(100)));
-
3016 env(pay(gw, bob, USD(100)));
-
3017 env.close();
-
3018
-
3019 auto const aliceSeq = env.seq(alice);
-
3020 auto const bobSeq = env.seq(bob);
-
3021 auto const preAlice = env.balance(alice);
-
3022 auto const preBob = env.balance(bob);
-
3023 auto const preAliceUSD = env.balance(alice, USD.issue());
-
3024 auto const preBobUSD = env.balance(bob, USD.issue());
-
3025
-
3026 auto const batchFee = batch::calcBatchFee(env, 1, 3);
-
3027 uint256 const chkID{getCheckIndex(bob, bobSeq + 1)};
-
3028 auto const [txIDs, batchID] = submitBatch(
-
3029 env,
-
3030 tesSUCCESS,
-
3031 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
-
3032 batch::inner(ticket::create(bob, 10), bobSeq),
-
3033 batch::inner(check::create(bob, alice, USD(10)), 0, bobSeq + 1),
-
3034 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq + 1),
-
3035 batch::sig(bob));
-
3036 env.close();
-
3037
-
3038 std::vector<TestLedgerData> testCases = {
-
3039 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
3040 {1, "TicketCreate", "tesSUCCESS", txIDs[0], batchID},
-
3041 {2, "CheckCreate", "tesSUCCESS", txIDs[1], batchID},
-
3042 {3, "CheckCash", "tesSUCCESS", txIDs[2], batchID},
-
3043 };
-
3044 validateClosedLedger(env, testCases);
-
3045
-
3046 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
-
3047 BEAST_EXPECT(env.seq(bob) == bobSeq + 10 + 1);
-
3048 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
-
3049 BEAST_EXPECT(env.balance(bob) == preBob);
-
3050 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD + USD(10));
-
3051 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD - USD(10));
-
3052 }
+
3006 test::jtx::Env env{*this, features};
+
3007
+
3008 auto const alice = Account("alice");
+
3009 auto const bob = Account("bob");
+
3010 auto const gw = Account("gw");
+
3011 auto const USD = gw["USD"];
+
3012
+
3013 env.fund(XRP(10000), alice, bob, gw);
+
3014 env.close();
+
3015
+
3016 env.trust(USD(1000), alice, bob);
+
3017 env(pay(gw, alice, USD(100)));
+
3018 env(pay(gw, bob, USD(100)));
+
3019 env.close();
+
3020
+
3021 auto const aliceSeq = env.seq(alice);
+
3022 auto const bobSeq = env.seq(bob);
+
3023 auto const preAlice = env.balance(alice);
+
3024 auto const preBob = env.balance(bob);
+
3025 auto const preAliceUSD = env.balance(alice, USD.issue());
+
3026 auto const preBobUSD = env.balance(bob, USD.issue());
+
3027
+
3028 auto const batchFee = batch::calcBatchFee(env, 1, 3);
+
3029 uint256 const chkID{getCheckIndex(bob, bobSeq + 1)};
+
3030 auto const [txIDs, batchID] = submitBatch(
+
3031 env,
+
3032 tesSUCCESS,
+
3033 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
+
3034 batch::inner(ticket::create(bob, 10), bobSeq),
+
3035 batch::inner(check::create(bob, alice, USD(10)), 0, bobSeq + 1),
+
3036 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq + 1),
+
3037 batch::sig(bob));
+
3038 env.close();
+
3039
+
3040 std::vector<TestLedgerData> testCases = {
+
3041 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
3042 {1, "TicketCreate", "tesSUCCESS", txIDs[0], batchID},
+
3043 {2, "CheckCreate", "tesSUCCESS", txIDs[1], batchID},
+
3044 {3, "CheckCash", "tesSUCCESS", txIDs[2], batchID},
+
3045 };
+
3046 validateClosedLedger(env, testCases);
+
3047
+
3048 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
+
3049 BEAST_EXPECT(env.seq(bob) == bobSeq + 10 + 1);
+
3050 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
+
3051 BEAST_EXPECT(env.balance(bob) == preBob);
+
3052 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD + USD(10));
+
3053 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD - USD(10));
+
3054 }
-
3053
-
3054 void
-
- -
3056 {
-
3057 testcase("object create w/ 3rd party");
-
3058
-
3059 using namespace test::jtx;
-
3060 using namespace std::literals;
-
3061
-
3062 test::jtx::Env env{*this, features};
+
3055
+
3056 void
+
+ +
3058 {
+
3059 testcase("object create w/ 3rd party");
+
3060
+
3061 using namespace test::jtx;
+
3062 using namespace std::literals;
3063
-
3064 auto const alice = Account("alice");
-
3065 auto const bob = Account("bob");
-
3066 auto const carol = Account("carol");
-
3067 auto const gw = Account("gw");
-
3068 auto const USD = gw["USD"];
-
3069
-
3070 env.fund(XRP(10000), alice, bob, carol, gw);
-
3071 env.close();
-
3072
-
3073 env.trust(USD(1000), alice, bob);
-
3074 env(pay(gw, alice, USD(100)));
-
3075 env(pay(gw, bob, USD(100)));
-
3076 env.close();
-
3077
-
3078 auto const aliceSeq = env.seq(alice);
-
3079 auto const bobSeq = env.seq(bob);
-
3080 auto const carolSeq = env.seq(carol);
-
3081 auto const preAlice = env.balance(alice);
-
3082 auto const preBob = env.balance(bob);
-
3083 auto const preCarol = env.balance(carol);
-
3084 auto const preAliceUSD = env.balance(alice, USD.issue());
-
3085 auto const preBobUSD = env.balance(bob, USD.issue());
-
3086
-
3087 auto const batchFee = batch::calcBatchFee(env, 2, 2);
-
3088 uint256 const chkID{getCheckIndex(bob, env.seq(bob))};
-
3089 auto const [txIDs, batchID] = submitBatch(
-
3090 env,
-
3091 tesSUCCESS,
-
3092 batch::outer(carol, carolSeq, batchFee, tfAllOrNothing),
-
3093 batch::inner(check::create(bob, alice, USD(10)), bobSeq),
-
3094 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq),
-
3095 batch::sig(alice, bob));
-
3096 env.close();
-
3097
-
3098 std::vector<TestLedgerData> testCases = {
-
3099 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
3100 {1, "CheckCreate", "tesSUCCESS", txIDs[0], batchID},
-
3101 {2, "CheckCash", "tesSUCCESS", txIDs[1], batchID},
-
3102 };
-
3103 validateClosedLedger(env, testCases);
-
3104
-
3105 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
-
3106 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
-
3107 BEAST_EXPECT(env.seq(carol) == carolSeq + 1);
-
3108 BEAST_EXPECT(env.balance(alice) == preAlice);
-
3109 BEAST_EXPECT(env.balance(bob) == preBob);
-
3110 BEAST_EXPECT(env.balance(carol) == preCarol - batchFee);
-
3111 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD + USD(10));
-
3112 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD - USD(10));
-
3113 }
+
3064 test::jtx::Env env{*this, features};
+
3065
+
3066 auto const alice = Account("alice");
+
3067 auto const bob = Account("bob");
+
3068 auto const carol = Account("carol");
+
3069 auto const gw = Account("gw");
+
3070 auto const USD = gw["USD"];
+
3071
+
3072 env.fund(XRP(10000), alice, bob, carol, gw);
+
3073 env.close();
+
3074
+
3075 env.trust(USD(1000), alice, bob);
+
3076 env(pay(gw, alice, USD(100)));
+
3077 env(pay(gw, bob, USD(100)));
+
3078 env.close();
+
3079
+
3080 auto const aliceSeq = env.seq(alice);
+
3081 auto const bobSeq = env.seq(bob);
+
3082 auto const carolSeq = env.seq(carol);
+
3083 auto const preAlice = env.balance(alice);
+
3084 auto const preBob = env.balance(bob);
+
3085 auto const preCarol = env.balance(carol);
+
3086 auto const preAliceUSD = env.balance(alice, USD.issue());
+
3087 auto const preBobUSD = env.balance(bob, USD.issue());
+
3088
+
3089 auto const batchFee = batch::calcBatchFee(env, 2, 2);
+
3090 uint256 const chkID{getCheckIndex(bob, env.seq(bob))};
+
3091 auto const [txIDs, batchID] = submitBatch(
+
3092 env,
+
3093 tesSUCCESS,
+
3094 batch::outer(carol, carolSeq, batchFee, tfAllOrNothing),
+
3095 batch::inner(check::create(bob, alice, USD(10)), bobSeq),
+
3096 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq),
+
3097 batch::sig(alice, bob));
+
3098 env.close();
+
3099
+
3100 std::vector<TestLedgerData> testCases = {
+
3101 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
3102 {1, "CheckCreate", "tesSUCCESS", txIDs[0], batchID},
+
3103 {2, "CheckCash", "tesSUCCESS", txIDs[1], batchID},
+
3104 };
+
3105 validateClosedLedger(env, testCases);
+
3106
+
3107 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
+
3108 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
+
3109 BEAST_EXPECT(env.seq(carol) == carolSeq + 1);
+
3110 BEAST_EXPECT(env.balance(alice) == preAlice);
+
3111 BEAST_EXPECT(env.balance(bob) == preBob);
+
3112 BEAST_EXPECT(env.balance(carol) == preCarol - batchFee);
+
3113 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD + USD(10));
+
3114 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD - USD(10));
+
3115 }
-
3114
-
3115 void
-
- -
3117 {
-
3118 {
-
3119 testcase("tickets outer");
-
3120
-
3121 using namespace test::jtx;
-
3122 using namespace std::literals;
-
3123
-
3124 test::jtx::Env env{*this, features};
+
3116
+
3117 void
+
+ +
3119 {
+
3120 {
+
3121 testcase("tickets outer");
+
3122
+
3123 using namespace test::jtx;
+
3124 using namespace std::literals;
3125
-
3126 auto const alice = Account("alice");
-
3127 auto const bob = Account("bob");
-
3128
-
3129 env.fund(XRP(10000), alice, bob);
-
3130 env.close();
-
3131
-
3132 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
-
3133 env(ticket::create(alice, 10));
-
3134 env.close();
-
3135
-
3136 auto const aliceSeq = env.seq(alice);
-
3137 auto const preAlice = env.balance(alice);
-
3138 auto const preBob = env.balance(bob);
-
3139
-
3140 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
3141 auto const [txIDs, batchID] = submitBatch(
-
3142 env,
-
3143 tesSUCCESS,
-
3144 batch::outer(alice, 0, batchFee, tfAllOrNothing),
-
3145 batch::inner(pay(alice, bob, XRP(1)), aliceSeq + 0),
-
3146 batch::inner(pay(alice, bob, XRP(2)), aliceSeq + 1),
-
3147 ticket::use(aliceTicketSeq));
-
3148 env.close();
-
3149
-
3150 std::vector<TestLedgerData> testCases = {
-
3151 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
3152 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
3153 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
3154 };
-
3155 validateClosedLedger(env, testCases);
-
3156
-
3157 auto const sle = env.le(keylet::account(alice));
-
3158 BEAST_EXPECT(sle);
-
3159 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 9);
-
3160 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 9);
-
3161
-
3162 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
-
3163 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(3) - batchFee);
-
3164 BEAST_EXPECT(env.balance(bob) == preBob + XRP(3));
-
3165 }
-
3166
-
3167 {
-
3168 testcase("tickets inner");
-
3169
-
3170 using namespace test::jtx;
-
3171 using namespace std::literals;
-
3172
-
3173 test::jtx::Env env{*this, features};
+
3126 test::jtx::Env env{*this, features};
+
3127
+
3128 auto const alice = Account("alice");
+
3129 auto const bob = Account("bob");
+
3130
+
3131 env.fund(XRP(10000), alice, bob);
+
3132 env.close();
+
3133
+
3134 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
+
3135 env(ticket::create(alice, 10));
+
3136 env.close();
+
3137
+
3138 auto const aliceSeq = env.seq(alice);
+
3139 auto const preAlice = env.balance(alice);
+
3140 auto const preBob = env.balance(bob);
+
3141
+
3142 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
3143 auto const [txIDs, batchID] = submitBatch(
+
3144 env,
+
3145 tesSUCCESS,
+
3146 batch::outer(alice, 0, batchFee, tfAllOrNothing),
+
3147 batch::inner(pay(alice, bob, XRP(1)), aliceSeq + 0),
+
3148 batch::inner(pay(alice, bob, XRP(2)), aliceSeq + 1),
+
3149 ticket::use(aliceTicketSeq));
+
3150 env.close();
+
3151
+
3152 std::vector<TestLedgerData> testCases = {
+
3153 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
3154 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
3155 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
3156 };
+
3157 validateClosedLedger(env, testCases);
+
3158
+
3159 auto const sle = env.le(keylet::account(alice));
+
3160 BEAST_EXPECT(sle);
+
3161 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 9);
+
3162 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 9);
+
3163
+
3164 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
+
3165 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(3) - batchFee);
+
3166 BEAST_EXPECT(env.balance(bob) == preBob + XRP(3));
+
3167 }
+
3168
+
3169 {
+
3170 testcase("tickets inner");
+
3171
+
3172 using namespace test::jtx;
+
3173 using namespace std::literals;
3174
-
3175 auto const alice = Account("alice");
-
3176 auto const bob = Account("bob");
-
3177
-
3178 env.fund(XRP(10000), alice, bob);
-
3179 env.close();
-
3180
-
3181 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
-
3182 env(ticket::create(alice, 10));
-
3183 env.close();
-
3184
-
3185 auto const aliceSeq = env.seq(alice);
-
3186 auto const preAlice = env.balance(alice);
-
3187 auto const preBob = env.balance(bob);
-
3188
-
3189 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
3190 auto const [txIDs, batchID] = submitBatch(
-
3191 env,
-
3192 tesSUCCESS,
-
3193 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
-
3194 batch::inner(pay(alice, bob, XRP(1)), 0, aliceTicketSeq),
-
3195 batch::inner(pay(alice, bob, XRP(2)), 0, aliceTicketSeq + 1));
-
3196 env.close();
-
3197
-
3198 std::vector<TestLedgerData> testCases = {
-
3199 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
3200 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
3201 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
3202 };
-
3203 validateClosedLedger(env, testCases);
-
3204
-
3205 auto const sle = env.le(keylet::account(alice));
-
3206 BEAST_EXPECT(sle);
-
3207 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 8);
-
3208 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 8);
-
3209
-
3210 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
-
3211 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(3) - batchFee);
-
3212 BEAST_EXPECT(env.balance(bob) == preBob + XRP(3));
-
3213 }
-
3214
-
3215 {
-
3216 testcase("tickets outer inner");
-
3217
-
3218 using namespace test::jtx;
-
3219 using namespace std::literals;
-
3220
-
3221 test::jtx::Env env{*this, features};
+
3175 test::jtx::Env env{*this, features};
+
3176
+
3177 auto const alice = Account("alice");
+
3178 auto const bob = Account("bob");
+
3179
+
3180 env.fund(XRP(10000), alice, bob);
+
3181 env.close();
+
3182
+
3183 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
+
3184 env(ticket::create(alice, 10));
+
3185 env.close();
+
3186
+
3187 auto const aliceSeq = env.seq(alice);
+
3188 auto const preAlice = env.balance(alice);
+
3189 auto const preBob = env.balance(bob);
+
3190
+
3191 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
3192 auto const [txIDs, batchID] = submitBatch(
+
3193 env,
+
3194 tesSUCCESS,
+
3195 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
+
3196 batch::inner(pay(alice, bob, XRP(1)), 0, aliceTicketSeq),
+
3197 batch::inner(pay(alice, bob, XRP(2)), 0, aliceTicketSeq + 1));
+
3198 env.close();
+
3199
+
3200 std::vector<TestLedgerData> testCases = {
+
3201 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
3202 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
3203 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
3204 };
+
3205 validateClosedLedger(env, testCases);
+
3206
+
3207 auto const sle = env.le(keylet::account(alice));
+
3208 BEAST_EXPECT(sle);
+
3209 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 8);
+
3210 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 8);
+
3211
+
3212 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
+
3213 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(3) - batchFee);
+
3214 BEAST_EXPECT(env.balance(bob) == preBob + XRP(3));
+
3215 }
+
3216
+
3217 {
+
3218 testcase("tickets outer inner");
+
3219
+
3220 using namespace test::jtx;
+
3221 using namespace std::literals;
3222
-
3223 auto const alice = Account("alice");
-
3224 auto const bob = Account("bob");
-
3225
-
3226 env.fund(XRP(10000), alice, bob);
-
3227 env.close();
-
3228
-
3229 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
-
3230 env(ticket::create(alice, 10));
-
3231 env.close();
-
3232
-
3233 auto const aliceSeq = env.seq(alice);
-
3234 auto const preAlice = env.balance(alice);
-
3235 auto const preBob = env.balance(bob);
-
3236
-
3237 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
3238 auto const [txIDs, batchID] = submitBatch(
-
3239 env,
-
3240 tesSUCCESS,
-
3241 batch::outer(alice, 0, batchFee, tfAllOrNothing),
-
3242 batch::inner(pay(alice, bob, XRP(1)), 0, aliceTicketSeq + 1),
-
3243 batch::inner(pay(alice, bob, XRP(2)), aliceSeq),
-
3244 ticket::use(aliceTicketSeq));
-
3245 env.close();
-
3246
-
3247 std::vector<TestLedgerData> testCases = {
-
3248 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
3249 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
3250 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
3251 };
-
3252 validateClosedLedger(env, testCases);
-
3253
-
3254 auto const sle = env.le(keylet::account(alice));
-
3255 BEAST_EXPECT(sle);
-
3256 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 8);
-
3257 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 8);
-
3258
-
3259 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
-
3260 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(3) - batchFee);
-
3261 BEAST_EXPECT(env.balance(bob) == preBob + XRP(3));
-
3262 }
-
3263 }
+
3223 test::jtx::Env env{*this, features};
+
3224
+
3225 auto const alice = Account("alice");
+
3226 auto const bob = Account("bob");
+
3227
+
3228 env.fund(XRP(10000), alice, bob);
+
3229 env.close();
+
3230
+
3231 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
+
3232 env(ticket::create(alice, 10));
+
3233 env.close();
+
3234
+
3235 auto const aliceSeq = env.seq(alice);
+
3236 auto const preAlice = env.balance(alice);
+
3237 auto const preBob = env.balance(bob);
+
3238
+
3239 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
3240 auto const [txIDs, batchID] = submitBatch(
+
3241 env,
+
3242 tesSUCCESS,
+
3243 batch::outer(alice, 0, batchFee, tfAllOrNothing),
+
3244 batch::inner(pay(alice, bob, XRP(1)), 0, aliceTicketSeq + 1),
+
3245 batch::inner(pay(alice, bob, XRP(2)), aliceSeq),
+
3246 ticket::use(aliceTicketSeq));
+
3247 env.close();
+
3248
+
3249 std::vector<TestLedgerData> testCases = {
+
3250 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
3251 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
3252 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
3253 };
+
3254 validateClosedLedger(env, testCases);
+
3255
+
3256 auto const sle = env.le(keylet::account(alice));
+
3257 BEAST_EXPECT(sle);
+
3258 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 8);
+
3259 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 8);
+
3260
+
3261 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
+
3262 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(3) - batchFee);
+
3263 BEAST_EXPECT(env.balance(bob) == preBob + XRP(3));
+
3264 }
+
3265 }
-
3264
-
3265 void
-
- -
3267 {
-
3268 testcase("sequence open ledger");
-
3269
-
3270 using namespace test::jtx;
-
3271 using namespace std::literals;
-
3272
-
3273 auto const alice = Account("alice");
-
3274 auto const bob = Account("bob");
-
3275 auto const carol = Account("carol");
-
3276
-
3277 // Before Batch Txn w/ retry following ledger
-
3278 {
-
3279 // IMPORTANT: The batch txn is applied first, then the noop txn.
-
3280 // Because of this ordering, the noop txn is not applied and is
-
3281 // overwritten by the payment in the batch transaction. Because the
-
3282 // terPRE_SEQ is outside of the batch this noop transaction will ge
-
3283 // reapplied in the following ledger
-
3284 test::jtx::Env env{*this, features};
-
3285 env.fund(XRP(10000), alice, bob, carol);
-
3286 env.close();
-
3287
-
3288 auto const aliceSeq = env.seq(alice);
-
3289 auto const carolSeq = env.seq(carol);
-
3290
-
3291 // AccountSet Txn
-
3292 auto const noopTxn = env.jt(noop(alice), seq(aliceSeq + 2));
-
3293 auto const noopTxnID = to_string(noopTxn.stx->getTransactionID());
-
3294 env(noopTxn, ter(terPRE_SEQ));
-
3295
-
3296 // Batch Txn
-
3297 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
3298 auto const [txIDs, batchID] = submitBatch(
-
3299 env,
-
3300 tesSUCCESS,
-
3301 batch::outer(carol, carolSeq, batchFee, tfAllOrNothing),
-
3302 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
-
3303 batch::inner(pay(alice, bob, XRP(2)), aliceSeq + 1),
-
3304 batch::sig(alice));
-
3305 env.close();
-
3306
-
3307 {
-
3308 std::vector<TestLedgerData> testCases = {
-
3309 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
3310 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
3311 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
3312 };
-
3313 validateClosedLedger(env, testCases);
-
3314 }
-
3315
-
3316 env.close();
-
3317 {
-
3318 // next ledger contains noop txn
-
3319 std::vector<TestLedgerData> testCases = {
-
3320 {0, "AccountSet", "tesSUCCESS", noopTxnID, std::nullopt},
-
3321 };
-
3322 validateClosedLedger(env, testCases);
-
3323 }
-
3324 }
-
3325
-
3326 // Before Batch Txn w/ same sequence
-
3327 {
-
3328 // IMPORTANT: The batch txn is applied first, then the noop txn.
-
3329 // Because of this ordering, the noop txn is not applied and is
-
3330 // overwritten by the payment in the batch transaction.
-
3331 test::jtx::Env env{*this, features};
-
3332 env.fund(XRP(10000), alice, bob);
-
3333 env.close();
-
3334
-
3335 auto const aliceSeq = env.seq(alice);
+
3266
+
3267 void
+
+ +
3269 {
+
3270 testcase("sequence open ledger");
+
3271
+
3272 using namespace test::jtx;
+
3273 using namespace std::literals;
+
3274
+
3275 auto const alice = Account("alice");
+
3276 auto const bob = Account("bob");
+
3277 auto const carol = Account("carol");
+
3278
+
3279 // Before Batch Txn w/ retry following ledger
+
3280 {
+
3281 // IMPORTANT: The batch txn is applied first, then the noop txn.
+
3282 // Because of this ordering, the noop txn is not applied and is
+
3283 // overwritten by the payment in the batch transaction. Because the
+
3284 // terPRE_SEQ is outside of the batch this noop transaction will ge
+
3285 // reapplied in the following ledger
+
3286 test::jtx::Env env{*this, features};
+
3287 env.fund(XRP(10000), alice, bob, carol);
+
3288 env.close();
+
3289
+
3290 auto const aliceSeq = env.seq(alice);
+
3291 auto const carolSeq = env.seq(carol);
+
3292
+
3293 // AccountSet Txn
+
3294 auto const noopTxn = env.jt(noop(alice), seq(aliceSeq + 2));
+
3295 auto const noopTxnID = to_string(noopTxn.stx->getTransactionID());
+
3296 env(noopTxn, ter(terPRE_SEQ));
+
3297
+
3298 // Batch Txn
+
3299 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
3300 auto const [txIDs, batchID] = submitBatch(
+
3301 env,
+
3302 tesSUCCESS,
+
3303 batch::outer(carol, carolSeq, batchFee, tfAllOrNothing),
+
3304 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
+
3305 batch::inner(pay(alice, bob, XRP(2)), aliceSeq + 1),
+
3306 batch::sig(alice));
+
3307 env.close();
+
3308
+
3309 {
+
3310 std::vector<TestLedgerData> testCases = {
+
3311 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
3312 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
3313 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
3314 };
+
3315 validateClosedLedger(env, testCases);
+
3316 }
+
3317
+
3318 env.close();
+
3319 {
+
3320 // next ledger contains noop txn
+
3321 std::vector<TestLedgerData> testCases = {
+
3322 {0, "AccountSet", "tesSUCCESS", noopTxnID, std::nullopt},
+
3323 };
+
3324 validateClosedLedger(env, testCases);
+
3325 }
+
3326 }
+
3327
+
3328 // Before Batch Txn w/ same sequence
+
3329 {
+
3330 // IMPORTANT: The batch txn is applied first, then the noop txn.
+
3331 // Because of this ordering, the noop txn is not applied and is
+
3332 // overwritten by the payment in the batch transaction.
+
3333 test::jtx::Env env{*this, features};
+
3334 env.fund(XRP(10000), alice, bob);
+
3335 env.close();
3336
-
3337 // AccountSet Txn
-
3338 auto const noopTxn = env.jt(noop(alice), seq(aliceSeq + 1));
-
3339 env(noopTxn, ter(terPRE_SEQ));
-
3340
-
3341 // Batch Txn
-
3342 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
3343 auto const [txIDs, batchID] = submitBatch(
-
3344 env,
-
3345 tesSUCCESS,
-
3346 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
-
3347 batch::inner(pay(alice, bob, XRP(1)), aliceSeq + 1),
-
3348 batch::inner(pay(alice, bob, XRP(2)), aliceSeq + 2));
-
3349 env.close();
-
3350
-
3351 {
-
3352 std::vector<TestLedgerData> testCases = {
-
3353 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
3354 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
3355 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
3356 };
-
3357 validateClosedLedger(env, testCases);
-
3358 }
-
3359
-
3360 env.close();
-
3361 {
-
3362 // next ledger is empty
-
3363 std::vector<TestLedgerData> testCases = {};
-
3364 validateClosedLedger(env, testCases);
-
3365 }
-
3366 }
-
3367
-
3368 // After Batch Txn w/ same sequence
-
3369 {
-
3370 // IMPORTANT: The batch txn is applied first, then the noop txn.
-
3371 // Because of this ordering, the noop txn is not applied and is
-
3372 // overwritten by the payment in the batch transaction.
-
3373 test::jtx::Env env{*this, features};
-
3374 env.fund(XRP(10000), alice, bob);
-
3375 env.close();
-
3376
-
3377 auto const aliceSeq = env.seq(alice);
-
3378 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
3379 auto const [txIDs, batchID] = submitBatch(
-
3380 env,
-
3381 tesSUCCESS,
-
3382 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
-
3383 batch::inner(pay(alice, bob, XRP(1)), aliceSeq + 1),
-
3384 batch::inner(pay(alice, bob, XRP(2)), aliceSeq + 2));
-
3385
-
3386 auto const noopTxn = env.jt(noop(alice), seq(aliceSeq + 1));
-
3387 auto const noopTxnID = to_string(noopTxn.stx->getTransactionID());
-
3388 env(noopTxn, ter(tesSUCCESS));
-
3389 env.close();
-
3390
-
3391 {
-
3392 std::vector<TestLedgerData> testCases = {
-
3393 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
3394 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
3395 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
3396 };
-
3397 validateClosedLedger(env, testCases);
-
3398 }
-
3399
-
3400 env.close();
-
3401 {
-
3402 // next ledger is empty
-
3403 std::vector<TestLedgerData> testCases = {};
-
3404 validateClosedLedger(env, testCases);
-
3405 }
-
3406 }
-
3407
-
3408 // Outer Batch terPRE_SEQ
-
3409 {
-
3410 test::jtx::Env env{*this, features};
-
3411 env.fund(XRP(10000), alice, bob, carol);
-
3412 env.close();
-
3413
-
3414 auto const aliceSeq = env.seq(alice);
-
3415 auto const carolSeq = env.seq(carol);
-
3416
-
3417 // Batch Txn
-
3418 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
3419 auto const [txIDs, batchID] = submitBatch(
-
3420 env,
-
3421 terPRE_SEQ,
-
3422 batch::outer(carol, carolSeq + 1, batchFee, tfAllOrNothing),
-
3423 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
-
3424 batch::inner(pay(alice, bob, XRP(2)), aliceSeq + 1),
-
3425 batch::sig(alice));
-
3426
-
3427 // AccountSet Txn
-
3428 auto const noopTxn = env.jt(noop(carol), seq(carolSeq));
-
3429 auto const noopTxnID = to_string(noopTxn.stx->getTransactionID());
-
3430 env(noopTxn, ter(tesSUCCESS));
-
3431 env.close();
-
3432
-
3433 {
-
3434 std::vector<TestLedgerData> testCases = {
-
3435 {0, "AccountSet", "tesSUCCESS", noopTxnID, std::nullopt},
-
3436 {1, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
3437 {2, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
3438 {3, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
3439 };
-
3440 validateClosedLedger(env, testCases);
-
3441 }
-
3442
-
3443 env.close();
-
3444 {
-
3445 // next ledger contains no transactions
-
3446 std::vector<TestLedgerData> testCases = {};
-
3447 validateClosedLedger(env, testCases);
-
3448 }
-
3449 }
-
3450 }
+
3337 auto const aliceSeq = env.seq(alice);
+
3338
+
3339 // AccountSet Txn
+
3340 auto const noopTxn = env.jt(noop(alice), seq(aliceSeq + 1));
+
3341 env(noopTxn, ter(terPRE_SEQ));
+
3342
+
3343 // Batch Txn
+
3344 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
3345 auto const [txIDs, batchID] = submitBatch(
+
3346 env,
+
3347 tesSUCCESS,
+
3348 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
+
3349 batch::inner(pay(alice, bob, XRP(1)), aliceSeq + 1),
+
3350 batch::inner(pay(alice, bob, XRP(2)), aliceSeq + 2));
+
3351 env.close();
+
3352
+
3353 {
+
3354 std::vector<TestLedgerData> testCases = {
+
3355 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
3356 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
3357 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
3358 };
+
3359 validateClosedLedger(env, testCases);
+
3360 }
+
3361
+
3362 env.close();
+
3363 {
+
3364 // next ledger is empty
+
3365 std::vector<TestLedgerData> testCases = {};
+
3366 validateClosedLedger(env, testCases);
+
3367 }
+
3368 }
+
3369
+
3370 // After Batch Txn w/ same sequence
+
3371 {
+
3372 // IMPORTANT: The batch txn is applied first, then the noop txn.
+
3373 // Because of this ordering, the noop txn is not applied and is
+
3374 // overwritten by the payment in the batch transaction.
+
3375 test::jtx::Env env{*this, features};
+
3376 env.fund(XRP(10000), alice, bob);
+
3377 env.close();
+
3378
+
3379 auto const aliceSeq = env.seq(alice);
+
3380 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
3381 auto const [txIDs, batchID] = submitBatch(
+
3382 env,
+
3383 tesSUCCESS,
+
3384 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
+
3385 batch::inner(pay(alice, bob, XRP(1)), aliceSeq + 1),
+
3386 batch::inner(pay(alice, bob, XRP(2)), aliceSeq + 2));
+
3387
+
3388 auto const noopTxn = env.jt(noop(alice), seq(aliceSeq + 1));
+
3389 auto const noopTxnID = to_string(noopTxn.stx->getTransactionID());
+
3390 env(noopTxn, ter(tesSUCCESS));
+
3391 env.close();
+
3392
+
3393 {
+
3394 std::vector<TestLedgerData> testCases = {
+
3395 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
3396 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
3397 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
3398 };
+
3399 validateClosedLedger(env, testCases);
+
3400 }
+
3401
+
3402 env.close();
+
3403 {
+
3404 // next ledger is empty
+
3405 std::vector<TestLedgerData> testCases = {};
+
3406 validateClosedLedger(env, testCases);
+
3407 }
+
3408 }
+
3409
+
3410 // Outer Batch terPRE_SEQ
+
3411 {
+
3412 test::jtx::Env env{*this, features};
+
3413 env.fund(XRP(10000), alice, bob, carol);
+
3414 env.close();
+
3415
+
3416 auto const aliceSeq = env.seq(alice);
+
3417 auto const carolSeq = env.seq(carol);
+
3418
+
3419 // Batch Txn
+
3420 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
3421 auto const [txIDs, batchID] = submitBatch(
+
3422 env,
+
3423 terPRE_SEQ,
+
3424 batch::outer(carol, carolSeq + 1, batchFee, tfAllOrNothing),
+
3425 batch::inner(pay(alice, bob, XRP(1)), aliceSeq),
+
3426 batch::inner(pay(alice, bob, XRP(2)), aliceSeq + 1),
+
3427 batch::sig(alice));
+
3428
+
3429 // AccountSet Txn
+
3430 auto const noopTxn = env.jt(noop(carol), seq(carolSeq));
+
3431 auto const noopTxnID = to_string(noopTxn.stx->getTransactionID());
+
3432 env(noopTxn, ter(tesSUCCESS));
+
3433 env.close();
+
3434
+
3435 {
+
3436 std::vector<TestLedgerData> testCases = {
+
3437 {0, "AccountSet", "tesSUCCESS", noopTxnID, std::nullopt},
+
3438 {1, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
3439 {2, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
3440 {3, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
3441 };
+
3442 validateClosedLedger(env, testCases);
+
3443 }
+
3444
+
3445 env.close();
+
3446 {
+
3447 // next ledger contains no transactions
+
3448 std::vector<TestLedgerData> testCases = {};
+
3449 validateClosedLedger(env, testCases);
+
3450 }
+
3451 }
+
3452 }
-
3451
-
3452 void
-
- -
3454 {
-
3455 testcase("tickets open ledger");
-
3456
-
3457 using namespace test::jtx;
-
3458 using namespace std::literals;
-
3459
-
3460 auto const alice = Account("alice");
-
3461 auto const bob = Account("bob");
-
3462
-
3463 // Before Batch Txn w/ same ticket
-
3464 {
-
3465 // IMPORTANT: The batch txn is applied first, then the noop txn.
-
3466 // Because of this ordering, the noop txn is not applied and is
-
3467 // overwritten by the payment in the batch transaction.
-
3468 test::jtx::Env env{*this, features};
-
3469 env.fund(XRP(10000), alice, bob);
-
3470 env.close();
-
3471
-
3472 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
-
3473 env(ticket::create(alice, 10));
-
3474 env.close();
-
3475
-
3476 auto const aliceSeq = env.seq(alice);
+
3453
+
3454 void
+
+ +
3456 {
+
3457 testcase("tickets open ledger");
+
3458
+
3459 using namespace test::jtx;
+
3460 using namespace std::literals;
+
3461
+
3462 auto const alice = Account("alice");
+
3463 auto const bob = Account("bob");
+
3464
+
3465 // Before Batch Txn w/ same ticket
+
3466 {
+
3467 // IMPORTANT: The batch txn is applied first, then the noop txn.
+
3468 // Because of this ordering, the noop txn is not applied and is
+
3469 // overwritten by the payment in the batch transaction.
+
3470 test::jtx::Env env{*this, features};
+
3471 env.fund(XRP(10000), alice, bob);
+
3472 env.close();
+
3473
+
3474 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
+
3475 env(ticket::create(alice, 10));
+
3476 env.close();
3477
-
3478 // AccountSet Txn
-
3479 auto const noopTxn =
-
3480 env.jt(noop(alice), ticket::use(aliceTicketSeq + 1));
-
3481 auto const noopTxnID = to_string(noopTxn.stx->getTransactionID());
-
3482 env(noopTxn, ter(tesSUCCESS));
-
3483
-
3484 // Batch Txn
-
3485 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
3486 auto const [txIDs, batchID] = submitBatch(
-
3487 env,
-
3488 tesSUCCESS,
-
3489 batch::outer(alice, 0, batchFee, tfAllOrNothing),
-
3490 batch::inner(pay(alice, bob, XRP(1)), 0, aliceTicketSeq + 1),
-
3491 batch::inner(pay(alice, bob, XRP(2)), aliceSeq),
-
3492 ticket::use(aliceTicketSeq));
-
3493 env.close();
-
3494
-
3495 {
-
3496 std::vector<TestLedgerData> testCases = {
-
3497 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
3498 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
3499 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
3500 };
-
3501 validateClosedLedger(env, testCases);
-
3502 }
-
3503
-
3504 env.close();
-
3505 {
-
3506 // next ledger is empty
-
3507 std::vector<TestLedgerData> testCases = {};
-
3508 validateClosedLedger(env, testCases);
-
3509 }
-
3510 }
-
3511
-
3512 // After Batch Txn w/ same ticket
-
3513 {
-
3514 // IMPORTANT: The batch txn is applied first, then the noop txn.
-
3515 // Because of this ordering, the noop txn is not applied and is
-
3516 // overwritten by the payment in the batch transaction.
-
3517 test::jtx::Env env{*this, features};
-
3518 env.fund(XRP(10000), alice, bob);
-
3519 env.close();
-
3520
-
3521 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
-
3522 env(ticket::create(alice, 10));
-
3523 env.close();
-
3524
-
3525 auto const aliceSeq = env.seq(alice);
+
3478 auto const aliceSeq = env.seq(alice);
+
3479
+
3480 // AccountSet Txn
+
3481 auto const noopTxn =
+
3482 env.jt(noop(alice), ticket::use(aliceTicketSeq + 1));
+
3483 auto const noopTxnID = to_string(noopTxn.stx->getTransactionID());
+
3484 env(noopTxn, ter(tesSUCCESS));
+
3485
+
3486 // Batch Txn
+
3487 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
3488 auto const [txIDs, batchID] = submitBatch(
+
3489 env,
+
3490 tesSUCCESS,
+
3491 batch::outer(alice, 0, batchFee, tfAllOrNothing),
+
3492 batch::inner(pay(alice, bob, XRP(1)), 0, aliceTicketSeq + 1),
+
3493 batch::inner(pay(alice, bob, XRP(2)), aliceSeq),
+
3494 ticket::use(aliceTicketSeq));
+
3495 env.close();
+
3496
+
3497 {
+
3498 std::vector<TestLedgerData> testCases = {
+
3499 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
3500 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
3501 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
3502 };
+
3503 validateClosedLedger(env, testCases);
+
3504 }
+
3505
+
3506 env.close();
+
3507 {
+
3508 // next ledger is empty
+
3509 std::vector<TestLedgerData> testCases = {};
+
3510 validateClosedLedger(env, testCases);
+
3511 }
+
3512 }
+
3513
+
3514 // After Batch Txn w/ same ticket
+
3515 {
+
3516 // IMPORTANT: The batch txn is applied first, then the noop txn.
+
3517 // Because of this ordering, the noop txn is not applied and is
+
3518 // overwritten by the payment in the batch transaction.
+
3519 test::jtx::Env env{*this, features};
+
3520 env.fund(XRP(10000), alice, bob);
+
3521 env.close();
+
3522
+
3523 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
+
3524 env(ticket::create(alice, 10));
+
3525 env.close();
3526
-
3527 // Batch Txn
-
3528 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
3529 auto const [txIDs, batchID] = submitBatch(
-
3530 env,
-
3531 tesSUCCESS,
-
3532 batch::outer(alice, 0, batchFee, tfAllOrNothing),
-
3533 batch::inner(pay(alice, bob, XRP(1)), 0, aliceTicketSeq + 1),
-
3534 batch::inner(pay(alice, bob, XRP(2)), aliceSeq),
-
3535 ticket::use(aliceTicketSeq));
-
3536
-
3537 // AccountSet Txn
-
3538 auto const noopTxn =
-
3539 env.jt(noop(alice), ticket::use(aliceTicketSeq + 1));
-
3540 env(noopTxn);
-
3541
-
3542 env.close();
-
3543 {
-
3544 std::vector<TestLedgerData> testCases = {
-
3545 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
3546 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
3547 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
3548 };
-
3549 validateClosedLedger(env, testCases);
-
3550 }
-
3551
-
3552 env.close();
-
3553 {
-
3554 // next ledger is empty
-
3555 std::vector<TestLedgerData> testCases = {};
-
3556 validateClosedLedger(env, testCases);
-
3557 }
-
3558 }
-
3559 }
+
3527 auto const aliceSeq = env.seq(alice);
+
3528
+
3529 // Batch Txn
+
3530 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
3531 auto const [txIDs, batchID] = submitBatch(
+
3532 env,
+
3533 tesSUCCESS,
+
3534 batch::outer(alice, 0, batchFee, tfAllOrNothing),
+
3535 batch::inner(pay(alice, bob, XRP(1)), 0, aliceTicketSeq + 1),
+
3536 batch::inner(pay(alice, bob, XRP(2)), aliceSeq),
+
3537 ticket::use(aliceTicketSeq));
+
3538
+
3539 // AccountSet Txn
+
3540 auto const noopTxn =
+
3541 env.jt(noop(alice), ticket::use(aliceTicketSeq + 1));
+
3542 env(noopTxn);
+
3543
+
3544 env.close();
+
3545 {
+
3546 std::vector<TestLedgerData> testCases = {
+
3547 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
3548 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
3549 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
3550 };
+
3551 validateClosedLedger(env, testCases);
+
3552 }
+
3553
+
3554 env.close();
+
3555 {
+
3556 // next ledger is empty
+
3557 std::vector<TestLedgerData> testCases = {};
+
3558 validateClosedLedger(env, testCases);
+
3559 }
+
3560 }
+
3561 }
-
3560
-
3561 void
-
- -
3563 {
-
3564 testcase("objects open ledger");
-
3565
-
3566 using namespace test::jtx;
-
3567 using namespace std::literals;
-
3568
-
3569 auto const alice = Account("alice");
-
3570 auto const bob = Account("bob");
-
3571
-
3572 // Consume Object Before Batch Txn
-
3573 {
-
3574 // IMPORTANT: The initial result of `CheckCash` is tecNO_ENTRY
-
3575 // because the create transaction has not been applied because the
-
3576 // batch will run in the close ledger process. The batch will be
-
3577 // allied and then retry this transaction in the current ledger.
-
3578
-
3579 test::jtx::Env env{*this, features};
-
3580 env.fund(XRP(10000), alice, bob);
-
3581 env.close();
-
3582
-
3583 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
-
3584 env(ticket::create(alice, 10));
-
3585 env.close();
-
3586
-
3587 auto const aliceSeq = env.seq(alice);
+
3562
+
3563 void
+
+ +
3565 {
+
3566 testcase("objects open ledger");
+
3567
+
3568 using namespace test::jtx;
+
3569 using namespace std::literals;
+
3570
+
3571 auto const alice = Account("alice");
+
3572 auto const bob = Account("bob");
+
3573
+
3574 // Consume Object Before Batch Txn
+
3575 {
+
3576 // IMPORTANT: The initial result of `CheckCash` is tecNO_ENTRY
+
3577 // because the create transaction has not been applied because the
+
3578 // batch will run in the close ledger process. The batch will be
+
3579 // allied and then retry this transaction in the current ledger.
+
3580
+
3581 test::jtx::Env env{*this, features};
+
3582 env.fund(XRP(10000), alice, bob);
+
3583 env.close();
+
3584
+
3585 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
+
3586 env(ticket::create(alice, 10));
+
3587 env.close();
3588
-
3589 // CheckCash Txn
-
3590 uint256 const chkID{getCheckIndex(alice, aliceSeq)};
-
3591 auto const objTxn = env.jt(check::cash(bob, chkID, XRP(10)));
-
3592 auto const objTxnID = to_string(objTxn.stx->getTransactionID());
-
3593 env(objTxn, ter(tecNO_ENTRY));
-
3594
-
3595 // Batch Txn
-
3596 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
3597 auto const [txIDs, batchID] = submitBatch(
-
3598 env,
-
3599 tesSUCCESS,
-
3600 batch::outer(alice, 0, batchFee, tfAllOrNothing),
-
3601 batch::inner(check::create(alice, bob, XRP(10)), aliceSeq),
-
3602 batch::inner(pay(alice, bob, XRP(1)), 0, aliceTicketSeq + 1),
-
3603 ticket::use(aliceTicketSeq));
-
3604
-
3605 env.close();
-
3606 {
-
3607 std::vector<TestLedgerData> testCases = {
-
3608 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
3609 {1, "CheckCreate", "tesSUCCESS", txIDs[0], batchID},
-
3610 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
3611 {3, "CheckCash", "tesSUCCESS", objTxnID, std::nullopt},
-
3612 };
-
3613 validateClosedLedger(env, testCases);
-
3614 }
-
3615
-
3616 env.close();
-
3617 {
-
3618 // next ledger is empty
-
3619 std::vector<TestLedgerData> testCases = {};
-
3620 validateClosedLedger(env, testCases);
-
3621 }
-
3622 }
-
3623
-
3624 // Create Object Before Batch Txn
-
3625 {
-
3626 test::jtx::Env env{*this, features};
-
3627 env.fund(XRP(10000), alice, bob);
-
3628 env.close();
-
3629
-
3630 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
-
3631 env(ticket::create(alice, 10));
-
3632 env.close();
-
3633
-
3634 auto const aliceSeq = env.seq(alice);
-
3635 auto const bobSeq = env.seq(bob);
-
3636
-
3637 // CheckCreate Txn
-
3638 uint256 const chkID{getCheckIndex(alice, aliceSeq)};
-
3639 auto const objTxn = env.jt(check::create(alice, bob, XRP(10)));
-
3640 auto const objTxnID = to_string(objTxn.stx->getTransactionID());
-
3641 env(objTxn, ter(tesSUCCESS));
-
3642
-
3643 // Batch Txn
-
3644 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
3645 auto const [txIDs, batchID] = submitBatch(
-
3646 env,
-
3647 tesSUCCESS,
-
3648 batch::outer(alice, 0, batchFee, tfAllOrNothing),
-
3649 batch::inner(check::cash(bob, chkID, XRP(10)), bobSeq),
-
3650 batch::inner(pay(alice, bob, XRP(1)), 0, aliceTicketSeq + 1),
-
3651 ticket::use(aliceTicketSeq),
-
3652 batch::sig(bob));
-
3653
-
3654 env.close();
-
3655 {
-
3656 std::vector<TestLedgerData> testCases = {
-
3657 {0, "CheckCreate", "tesSUCCESS", objTxnID, std::nullopt},
-
3658 {1, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
3659 {2, "CheckCash", "tesSUCCESS", txIDs[0], batchID},
-
3660 {3, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
3661 };
-
3662 validateClosedLedger(env, testCases);
-
3663 }
-
3664 }
-
3665
-
3666 // After Batch Txn
-
3667 {
-
3668 // IMPORTANT: The initial result of `CheckCash` is tecNO_ENTRY
-
3669 // because the create transaction has not been applied because the
-
3670 // batch will run in the close ledger process. The batch will be
-
3671 // applied and then retry this transaction in the current ledger.
-
3672
-
3673 test::jtx::Env env{*this, features};
-
3674 env.fund(XRP(10000), alice, bob);
-
3675 env.close();
-
3676
-
3677 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
-
3678 env(ticket::create(alice, 10));
-
3679 env.close();
-
3680
-
3681 auto const aliceSeq = env.seq(alice);
+
3589 auto const aliceSeq = env.seq(alice);
+
3590
+
3591 // CheckCash Txn
+
3592 uint256 const chkID{getCheckIndex(alice, aliceSeq)};
+
3593 auto const objTxn = env.jt(check::cash(bob, chkID, XRP(10)));
+
3594 auto const objTxnID = to_string(objTxn.stx->getTransactionID());
+
3595 env(objTxn, ter(tecNO_ENTRY));
+
3596
+
3597 // Batch Txn
+
3598 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
3599 auto const [txIDs, batchID] = submitBatch(
+
3600 env,
+
3601 tesSUCCESS,
+
3602 batch::outer(alice, 0, batchFee, tfAllOrNothing),
+
3603 batch::inner(check::create(alice, bob, XRP(10)), aliceSeq),
+
3604 batch::inner(pay(alice, bob, XRP(1)), 0, aliceTicketSeq + 1),
+
3605 ticket::use(aliceTicketSeq));
+
3606
+
3607 env.close();
+
3608 {
+
3609 std::vector<TestLedgerData> testCases = {
+
3610 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
3611 {1, "CheckCreate", "tesSUCCESS", txIDs[0], batchID},
+
3612 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
3613 {3, "CheckCash", "tesSUCCESS", objTxnID, std::nullopt},
+
3614 };
+
3615 validateClosedLedger(env, testCases);
+
3616 }
+
3617
+
3618 env.close();
+
3619 {
+
3620 // next ledger is empty
+
3621 std::vector<TestLedgerData> testCases = {};
+
3622 validateClosedLedger(env, testCases);
+
3623 }
+
3624 }
+
3625
+
3626 // Create Object Before Batch Txn
+
3627 {
+
3628 test::jtx::Env env{*this, features};
+
3629 env.fund(XRP(10000), alice, bob);
+
3630 env.close();
+
3631
+
3632 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
+
3633 env(ticket::create(alice, 10));
+
3634 env.close();
+
3635
+
3636 auto const aliceSeq = env.seq(alice);
+
3637 auto const bobSeq = env.seq(bob);
+
3638
+
3639 // CheckCreate Txn
+
3640 uint256 const chkID{getCheckIndex(alice, aliceSeq)};
+
3641 auto const objTxn = env.jt(check::create(alice, bob, XRP(10)));
+
3642 auto const objTxnID = to_string(objTxn.stx->getTransactionID());
+
3643 env(objTxn, ter(tesSUCCESS));
+
3644
+
3645 // Batch Txn
+
3646 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
3647 auto const [txIDs, batchID] = submitBatch(
+
3648 env,
+
3649 tesSUCCESS,
+
3650 batch::outer(alice, 0, batchFee, tfAllOrNothing),
+
3651 batch::inner(check::cash(bob, chkID, XRP(10)), bobSeq),
+
3652 batch::inner(pay(alice, bob, XRP(1)), 0, aliceTicketSeq + 1),
+
3653 ticket::use(aliceTicketSeq),
+
3654 batch::sig(bob));
+
3655
+
3656 env.close();
+
3657 {
+
3658 std::vector<TestLedgerData> testCases = {
+
3659 {0, "CheckCreate", "tesSUCCESS", objTxnID, std::nullopt},
+
3660 {1, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
3661 {2, "CheckCash", "tesSUCCESS", txIDs[0], batchID},
+
3662 {3, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
3663 };
+
3664 validateClosedLedger(env, testCases);
+
3665 }
+
3666 }
+
3667
+
3668 // After Batch Txn
+
3669 {
+
3670 // IMPORTANT: The initial result of `CheckCash` is tecNO_ENTRY
+
3671 // because the create transaction has not been applied because the
+
3672 // batch will run in the close ledger process. The batch will be
+
3673 // applied and then retry this transaction in the current ledger.
+
3674
+
3675 test::jtx::Env env{*this, features};
+
3676 env.fund(XRP(10000), alice, bob);
+
3677 env.close();
+
3678
+
3679 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
+
3680 env(ticket::create(alice, 10));
+
3681 env.close();
3682
-
3683 // Batch Txn
-
3684 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
3685 uint256 const chkID{getCheckIndex(alice, aliceSeq)};
-
3686 auto const [txIDs, batchID] = submitBatch(
-
3687 env,
-
3688 tesSUCCESS,
-
3689 batch::outer(alice, 0, batchFee, tfAllOrNothing),
-
3690 batch::inner(check::create(alice, bob, XRP(10)), aliceSeq),
-
3691 batch::inner(pay(alice, bob, XRP(1)), 0, aliceTicketSeq + 1),
-
3692 ticket::use(aliceTicketSeq));
-
3693
-
3694 // CheckCash Txn
-
3695 auto const objTxn = env.jt(check::cash(bob, chkID, XRP(10)));
-
3696 auto const objTxnID = to_string(objTxn.stx->getTransactionID());
-
3697 env(objTxn, ter(tecNO_ENTRY));
-
3698
-
3699 env.close();
-
3700 {
-
3701 std::vector<TestLedgerData> testCases = {
-
3702 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
3703 {1, "CheckCreate", "tesSUCCESS", txIDs[0], batchID},
-
3704 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
3705 {3, "CheckCash", "tesSUCCESS", objTxnID, std::nullopt},
-
3706 };
-
3707 validateClosedLedger(env, testCases);
-
3708 }
-
3709 }
-
3710 }
+
3683 auto const aliceSeq = env.seq(alice);
+
3684
+
3685 // Batch Txn
+
3686 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
3687 uint256 const chkID{getCheckIndex(alice, aliceSeq)};
+
3688 auto const [txIDs, batchID] = submitBatch(
+
3689 env,
+
3690 tesSUCCESS,
+
3691 batch::outer(alice, 0, batchFee, tfAllOrNothing),
+
3692 batch::inner(check::create(alice, bob, XRP(10)), aliceSeq),
+
3693 batch::inner(pay(alice, bob, XRP(1)), 0, aliceTicketSeq + 1),
+
3694 ticket::use(aliceTicketSeq));
+
3695
+
3696 // CheckCash Txn
+
3697 auto const objTxn = env.jt(check::cash(bob, chkID, XRP(10)));
+
3698 auto const objTxnID = to_string(objTxn.stx->getTransactionID());
+
3699 env(objTxn, ter(tecNO_ENTRY));
+
3700
+
3701 env.close();
+
3702 {
+
3703 std::vector<TestLedgerData> testCases = {
+
3704 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
3705 {1, "CheckCreate", "tesSUCCESS", txIDs[0], batchID},
+
3706 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
3707 {3, "CheckCash", "tesSUCCESS", objTxnID, std::nullopt},
+
3708 };
+
3709 validateClosedLedger(env, testCases);
+
3710 }
+
3711 }
+
3712 }
-
3711
-
3712 void
-
- -
3714 {
-
3715 testcase("pseudo txn with tfInnerBatchTxn");
-
3716
-
3717 using namespace test::jtx;
-
3718 using namespace std::literals;
-
3719
-
3720 test::jtx::Env env{*this, features};
+
3713
+
3714 void
+
+ +
3716 {
+
3717 testcase("pseudo txn with tfInnerBatchTxn");
+
3718
+
3719 using namespace test::jtx;
+
3720 using namespace std::literals;
3721
-
3722 auto const alice = Account("alice");
-
3723 auto const bob = Account("bob");
-
3724 env.fund(XRP(10000), alice, bob);
-
3725 env.close();
-
3726
-
3727 STTx const stx = STTx(ttAMENDMENT, [&](auto& obj) {
-
3728 obj.setAccountID(sfAccount, AccountID());
-
3729 obj.setFieldH256(sfAmendment, uint256(2));
-
3730 obj.setFieldU32(sfLedgerSequence, env.seq(alice));
-
3731 obj.setFieldU32(sfFlags, tfInnerBatchTxn);
-
3732 });
-
3733
-
3734 std::string reason;
-
3735 BEAST_EXPECT(isPseudoTx(stx));
-
3736 BEAST_EXPECT(!passesLocalChecks(stx, reason));
-
3737 BEAST_EXPECT(reason == "Cannot submit pseudo transactions.");
-
3738 env.app().openLedger().modify([&](OpenView& view, beast::Journal j) {
-
3739 auto const result = xrpl::apply(env.app(), view, stx, tapNONE, j);
-
3740 BEAST_EXPECT(!result.applied && result.ter == temINVALID_FLAG);
-
3741 return result.applied;
-
3742 });
-
3743 }
+
3722 test::jtx::Env env{*this, features};
+
3723
+
3724 auto const alice = Account("alice");
+
3725 auto const bob = Account("bob");
+
3726 env.fund(XRP(10000), alice, bob);
+
3727 env.close();
+
3728
+
3729 STTx const stx = STTx(ttAMENDMENT, [&](auto& obj) {
+
3730 obj.setAccountID(sfAccount, AccountID());
+
3731 obj.setFieldH256(sfAmendment, uint256(2));
+
3732 obj.setFieldU32(sfLedgerSequence, env.seq(alice));
+
3733 obj.setFieldU32(sfFlags, tfInnerBatchTxn);
+
3734 });
+
3735
+
3736 std::string reason;
+
3737 BEAST_EXPECT(isPseudoTx(stx));
+
3738 BEAST_EXPECT(!passesLocalChecks(stx, reason));
+
3739 BEAST_EXPECT(reason == "Cannot submit pseudo transactions.");
+
3740 env.app().openLedger().modify([&](OpenView& view, beast::Journal j) {
+
3741 auto const result = xrpl::apply(env.app(), view, stx, tapNONE, j);
+
3742 BEAST_EXPECT(!result.applied && result.ter == temINVALID_FLAG);
+
3743 return result.applied;
+
3744 });
+
3745 }
-
3744
-
3745 void
-
- -
3747 {
-
3748 testcase("batch open ledger");
-
3749 // IMPORTANT: When a transaction is submitted outside of a batch and
-
3750 // another transaction is part of the batch, the batch might fail
-
3751 // because the sequence is out of order. This is because the canonical
-
3752 // order of transactions is determined by the account first. So in this
-
3753 // case, alice's batch comes after bobs self submitted transaction even
-
3754 // though the payment was submitted after the batch.
-
3755
-
3756 using namespace test::jtx;
-
3757 using namespace std::literals;
-
3758
-
3759 test::jtx::Env env{*this, features};
-
3760 XRPAmount const baseFee = env.current()->fees().base;
-
3761
-
3762 auto const alice = Account("alice");
-
3763 auto const bob = Account("bob");
-
3764
-
3765 env.fund(XRP(10000), alice, bob);
-
3766 env.close();
-
3767
-
3768 env(noop(bob), ter(tesSUCCESS));
-
3769 env.close();
-
3770
-
3771 auto const aliceSeq = env.seq(alice);
-
3772 auto const preAlice = env.balance(alice);
-
3773 auto const preBob = env.balance(bob);
-
3774 auto const bobSeq = env.seq(bob);
-
3775
-
3776 // Alice Pays Bob (Open Ledger)
-
3777 auto const payTxn1 = env.jt(pay(alice, bob, XRP(10)), seq(aliceSeq));
-
3778 auto const payTxn1ID = to_string(payTxn1.stx->getTransactionID());
-
3779 env(payTxn1, ter(tesSUCCESS));
-
3780
-
3781 // Alice & Bob Atomic Batch
-
3782 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
3783 auto const [txIDs, batchID] = submitBatch(
-
3784 env,
-
3785 tesSUCCESS,
-
3786 batch::outer(alice, aliceSeq + 1, batchFee, tfAllOrNothing),
-
3787 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 2),
-
3788 batch::inner(pay(bob, alice, XRP(5)), bobSeq),
-
3789 batch::sig(bob));
-
3790
-
3791 // Bob pays Alice (Open Ledger)
-
3792 auto const payTxn2 = env.jt(pay(bob, alice, XRP(5)), seq(bobSeq + 1));
-
3793 auto const payTxn2ID = to_string(payTxn2.stx->getTransactionID());
-
3794 env(payTxn2, ter(terPRE_SEQ));
-
3795 env.close();
-
3796
-
3797 std::vector<TestLedgerData> testCases = {
-
3798 {0, "Payment", "tesSUCCESS", payTxn1ID, std::nullopt},
-
3799 {1, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
3800 {2, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
3801 {3, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
3802 };
-
3803 validateClosedLedger(env, testCases);
-
3804
-
3805 env.close();
-
3806 {
-
3807 // next ledger includes the payment txn
-
3808 std::vector<TestLedgerData> testCases = {
-
3809 {0, "Payment", "tesSUCCESS", payTxn2ID, std::nullopt},
-
3810 };
-
3811 validateClosedLedger(env, testCases);
-
3812 }
-
3813
-
3814 // Alice consumes sequences (# of txns)
-
3815 BEAST_EXPECT(env.seq(alice) == aliceSeq + 3);
-
3816
-
3817 // Alice consumes sequences (# of txns)
-
3818 BEAST_EXPECT(env.seq(bob) == bobSeq + 2);
-
3819
-
3820 // Alice pays XRP & Fee; Bob receives XRP & pays Fee
-
3821 BEAST_EXPECT(
-
3822 env.balance(alice) == preAlice - XRP(10) - batchFee - baseFee);
-
3823 BEAST_EXPECT(env.balance(bob) == preBob + XRP(10) - baseFee);
-
3824 }
+
3746
+
3747 void
+
+ +
3749 {
+
3750 testcase("batch open ledger");
+
3751 // IMPORTANT: When a transaction is submitted outside of a batch and
+
3752 // another transaction is part of the batch, the batch might fail
+
3753 // because the sequence is out of order. This is because the canonical
+
3754 // order of transactions is determined by the account first. So in this
+
3755 // case, alice's batch comes after bobs self submitted transaction even
+
3756 // though the payment was submitted after the batch.
+
3757
+
3758 using namespace test::jtx;
+
3759 using namespace std::literals;
+
3760
+
3761 test::jtx::Env env{*this, features};
+
3762 XRPAmount const baseFee = env.current()->fees().base;
+
3763
+
3764 auto const alice = Account("alice");
+
3765 auto const bob = Account("bob");
+
3766
+
3767 env.fund(XRP(10000), alice, bob);
+
3768 env.close();
+
3769
+
3770 env(noop(bob), ter(tesSUCCESS));
+
3771 env.close();
+
3772
+
3773 auto const aliceSeq = env.seq(alice);
+
3774 auto const preAlice = env.balance(alice);
+
3775 auto const preBob = env.balance(bob);
+
3776 auto const bobSeq = env.seq(bob);
+
3777
+
3778 // Alice Pays Bob (Open Ledger)
+
3779 auto const payTxn1 = env.jt(pay(alice, bob, XRP(10)), seq(aliceSeq));
+
3780 auto const payTxn1ID = to_string(payTxn1.stx->getTransactionID());
+
3781 env(payTxn1, ter(tesSUCCESS));
+
3782
+
3783 // Alice & Bob Atomic Batch
+
3784 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
3785 auto const [txIDs, batchID] = submitBatch(
+
3786 env,
+
3787 tesSUCCESS,
+
3788 batch::outer(alice, aliceSeq + 1, batchFee, tfAllOrNothing),
+
3789 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 2),
+
3790 batch::inner(pay(bob, alice, XRP(5)), bobSeq),
+
3791 batch::sig(bob));
+
3792
+
3793 // Bob pays Alice (Open Ledger)
+
3794 auto const payTxn2 = env.jt(pay(bob, alice, XRP(5)), seq(bobSeq + 1));
+
3795 auto const payTxn2ID = to_string(payTxn2.stx->getTransactionID());
+
3796 env(payTxn2, ter(terPRE_SEQ));
+
3797 env.close();
+
3798
+
3799 std::vector<TestLedgerData> testCases = {
+
3800 {0, "Payment", "tesSUCCESS", payTxn1ID, std::nullopt},
+
3801 {1, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
3802 {2, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
3803 {3, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
3804 };
+
3805 validateClosedLedger(env, testCases);
+
3806
+
3807 env.close();
+
3808 {
+
3809 // next ledger includes the payment txn
+
3810 std::vector<TestLedgerData> testCases = {
+
3811 {0, "Payment", "tesSUCCESS", payTxn2ID, std::nullopt},
+
3812 };
+
3813 validateClosedLedger(env, testCases);
+
3814 }
+
3815
+
3816 // Alice consumes sequences (# of txns)
+
3817 BEAST_EXPECT(env.seq(alice) == aliceSeq + 3);
+
3818
+
3819 // Alice consumes sequences (# of txns)
+
3820 BEAST_EXPECT(env.seq(bob) == bobSeq + 2);
+
3821
+
3822 // Alice pays XRP & Fee; Bob receives XRP & pays Fee
+
3823 BEAST_EXPECT(
+
3824 env.balance(alice) == preAlice - XRP(10) - batchFee - baseFee);
+
3825 BEAST_EXPECT(env.balance(bob) == preBob + XRP(10) - baseFee);
+
3826 }
-
3825
-
3826 void
-
- -
3828 {
-
3829 testcase("batch tx queue");
-
3830
-
3831 using namespace test::jtx;
-
3832 using namespace std::literals;
-
3833
-
3834 // only outer batch transactions are counter towards the queue size
-
3835 {
-
3836 test::jtx::Env env{
-
3837 *this,
-
3838 makeSmallQueueConfig(
-
3839 {{"minimum_txn_in_ledger_standalone", "2"}}),
-
3840 features,
-
3841 nullptr,
- -
3843
-
3844 auto alice = Account("alice");
-
3845 auto bob = Account("bob");
-
3846 auto carol = Account("carol");
-
3847
-
3848 // Fund across several ledgers so the TxQ metrics stay restricted.
-
3849 env.fund(XRP(10000), noripple(alice, bob));
-
3850 env.close(env.now() + 5s, 10000ms);
-
3851 env.fund(XRP(10000), noripple(carol));
+
3827
+
3828 void
+
+ +
3830 {
+
3831 testcase("batch tx queue");
+
3832
+
3833 using namespace test::jtx;
+
3834 using namespace std::literals;
+
3835
+
3836 // only outer batch transactions are counter towards the queue size
+
3837 {
+
3838 test::jtx::Env env{
+
3839 *this,
+
3840 makeSmallQueueConfig(
+
3841 {{"minimum_txn_in_ledger_standalone", "2"}}),
+
3842 features,
+
3843 nullptr,
+ +
3845
+
3846 auto alice = Account("alice");
+
3847 auto bob = Account("bob");
+
3848 auto carol = Account("carol");
+
3849
+
3850 // Fund across several ledgers so the TxQ metrics stay restricted.
+
3851 env.fund(XRP(10000), noripple(alice, bob));
3852 env.close(env.now() + 5s, 10000ms);
-
3853
-
3854 // Fill the ledger
-
3855 env(noop(alice));
-
3856 env(noop(alice));
+
3853 env.fund(XRP(10000), noripple(carol));
+
3854 env.close(env.now() + 5s, 10000ms);
+
3855
+
3856 // Fill the ledger
3857 env(noop(alice));
-
3858 checkMetrics(*this, env, 0, std::nullopt, 3, 2);
-
3859
-
3860 env(noop(carol), ter(terQUEUED));
-
3861 checkMetrics(*this, env, 1, std::nullopt, 3, 2);
-
3862
-
3863 auto const aliceSeq = env.seq(alice);
-
3864 auto const bobSeq = env.seq(bob);
-
3865 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
3866
-
3867 // Queue Batch
-
3868 {
-
3869 env(batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
-
3870 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1),
-
3871 batch::inner(pay(bob, alice, XRP(5)), bobSeq),
-
3872 batch::sig(bob),
-
3873 ter(terQUEUED));
-
3874 }
-
3875
-
3876 checkMetrics(*this, env, 2, std::nullopt, 3, 2);
+
3858 env(noop(alice));
+
3859 env(noop(alice));
+
3860 checkMetrics(*this, env, 0, std::nullopt, 3, 2);
+
3861
+
3862 env(noop(carol), ter(terQUEUED));
+
3863 checkMetrics(*this, env, 1, std::nullopt, 3, 2);
+
3864
+
3865 auto const aliceSeq = env.seq(alice);
+
3866 auto const bobSeq = env.seq(bob);
+
3867 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
3868
+
3869 // Queue Batch
+
3870 {
+
3871 env(batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
+
3872 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1),
+
3873 batch::inner(pay(bob, alice, XRP(5)), bobSeq),
+
3874 batch::sig(bob),
+
3875 ter(terQUEUED));
+
3876 }
3877
-
3878 // Replace Queued Batch
-
3879 {
-
3880 env(batch::outer(
-
3881 alice,
-
3882 aliceSeq,
-
3883 openLedgerFee(env, batchFee),
- -
3885 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1),
-
3886 batch::inner(pay(bob, alice, XRP(5)), bobSeq),
-
3887 batch::sig(bob),
-
3888 ter(tesSUCCESS));
-
3889 env.close();
-
3890 }
-
3891
-
3892 checkMetrics(*this, env, 0, 12, 1, 6);
-
3893 }
-
3894
-
3895 // inner batch transactions are counter towards the ledger tx count
-
3896 {
-
3897 test::jtx::Env env{
-
3898 *this,
-
3899 makeSmallQueueConfig(
-
3900 {{"minimum_txn_in_ledger_standalone", "2"}}),
-
3901 features,
-
3902 nullptr,
- -
3904
-
3905 auto alice = Account("alice");
-
3906 auto bob = Account("bob");
-
3907 auto carol = Account("carol");
-
3908
-
3909 // Fund across several ledgers so the TxQ metrics stay restricted.
-
3910 env.fund(XRP(10000), noripple(alice, bob));
-
3911 env.close(env.now() + 5s, 10000ms);
-
3912 env.fund(XRP(10000), noripple(carol));
+
3878 checkMetrics(*this, env, 2, std::nullopt, 3, 2);
+
3879
+
3880 // Replace Queued Batch
+
3881 {
+
3882 env(batch::outer(
+
3883 alice,
+
3884 aliceSeq,
+
3885 openLedgerFee(env, batchFee),
+ +
3887 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1),
+
3888 batch::inner(pay(bob, alice, XRP(5)), bobSeq),
+
3889 batch::sig(bob),
+
3890 ter(tesSUCCESS));
+
3891 env.close();
+
3892 }
+
3893
+
3894 checkMetrics(*this, env, 0, 12, 1, 6);
+
3895 }
+
3896
+
3897 // inner batch transactions are counter towards the ledger tx count
+
3898 {
+
3899 test::jtx::Env env{
+
3900 *this,
+
3901 makeSmallQueueConfig(
+
3902 {{"minimum_txn_in_ledger_standalone", "2"}}),
+
3903 features,
+
3904 nullptr,
+ +
3906
+
3907 auto alice = Account("alice");
+
3908 auto bob = Account("bob");
+
3909 auto carol = Account("carol");
+
3910
+
3911 // Fund across several ledgers so the TxQ metrics stay restricted.
+
3912 env.fund(XRP(10000), noripple(alice, bob));
3913 env.close(env.now() + 5s, 10000ms);
-
3914
-
3915 // Fill the ledger leaving room for 1 queued transaction
-
3916 env(noop(alice));
-
3917 env(noop(alice));
-
3918 checkMetrics(*this, env, 0, std::nullopt, 2, 2);
-
3919
-
3920 auto const aliceSeq = env.seq(alice);
-
3921 auto const bobSeq = env.seq(bob);
-
3922 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
3923
-
3924 // Batch Successful
-
3925 {
-
3926 env(batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
-
3927 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1),
-
3928 batch::inner(pay(bob, alice, XRP(5)), bobSeq),
-
3929 batch::sig(bob),
-
3930 ter(tesSUCCESS));
-
3931 }
-
3932
-
3933 checkMetrics(*this, env, 0, std::nullopt, 3, 2);
+
3914 env.fund(XRP(10000), noripple(carol));
+
3915 env.close(env.now() + 5s, 10000ms);
+
3916
+
3917 // Fill the ledger leaving room for 1 queued transaction
+
3918 env(noop(alice));
+
3919 env(noop(alice));
+
3920 checkMetrics(*this, env, 0, std::nullopt, 2, 2);
+
3921
+
3922 auto const aliceSeq = env.seq(alice);
+
3923 auto const bobSeq = env.seq(bob);
+
3924 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
3925
+
3926 // Batch Successful
+
3927 {
+
3928 env(batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
+
3929 batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1),
+
3930 batch::inner(pay(bob, alice, XRP(5)), bobSeq),
+
3931 batch::sig(bob),
+
3932 ter(tesSUCCESS));
+
3933 }
3934
-
3935 env(noop(carol), ter(terQUEUED));
-
3936 checkMetrics(*this, env, 1, std::nullopt, 3, 2);
-
3937 }
-
3938 }
+
3935 checkMetrics(*this, env, 0, std::nullopt, 3, 2);
+
3936
+
3937 env(noop(carol), ter(terQUEUED));
+
3938 checkMetrics(*this, env, 1, std::nullopt, 3, 2);
+
3939 }
+
3940 }
-
3939
-
3940 void
-
- -
3942 {
-
3943 testcase("batch network ops");
-
3944
-
3945 using namespace test::jtx;
-
3946 using namespace std::literals;
-
3947
-
3948 Env env(
-
3949 *this,
-
3950 envconfig(),
-
3951 features,
-
3952 nullptr,
- -
3954
-
3955 auto alice = Account("alice");
-
3956 auto bob = Account("bob");
-
3957 env.fund(XRP(10000), alice, bob);
-
3958 env.close();
-
3959
-
3960 auto submitTx = [&](std::uint32_t flags) -> uint256 {
-
3961 auto jt = env.jt(pay(alice, bob, XRP(1)), txflags(flags));
-
3962 Serializer s;
-
3963 jt.stx->add(s);
-
3964 env.app().getOPs().submitTransaction(jt.stx);
-
3965 return jt.stx->getTransactionID();
-
3966 };
-
3967
-
3968 auto processTxn = [&](std::uint32_t flags) -> uint256 {
-
3969 auto jt = env.jt(pay(alice, bob, XRP(1)), txflags(flags));
-
3970 Serializer s;
-
3971 jt.stx->add(s);
-
3972 std::string reason;
-
3973 auto transaction =
-
3974 std::make_shared<Transaction>(jt.stx, reason, env.app());
- -
3976 transaction, false, true, NetworkOPs::FailHard::yes);
-
3977 return transaction->getID();
-
3978 };
-
3979
-
3980 // Validate: NetworkOPs::submitTransaction()
-
3981 {
-
3982 // Submit a tx with tfInnerBatchTxn
-
3983 uint256 const txBad = submitTx(tfInnerBatchTxn);
-
3984 BEAST_EXPECT(
-
3985 env.app().getHashRouter().getFlags(txBad) ==
- -
3987 }
-
3988
-
3989 // Validate: NetworkOPs::processTransaction()
-
3990 {
-
3991 uint256 const txid = processTxn(tfInnerBatchTxn);
-
3992 // HashRouter::getFlags() should return LedgerFlags::BAD
-
3993 BEAST_EXPECT(
-
3994 env.app().getHashRouter().getFlags(txid) ==
- -
3996 }
-
3997 }
+
3941
+
3942 void
+
+ +
3944 {
+
3945 testcase("batch network ops");
+
3946
+
3947 using namespace test::jtx;
+
3948 using namespace std::literals;
+
3949
+
3950 Env env(
+
3951 *this,
+
3952 envconfig(),
+
3953 features,
+
3954 nullptr,
+ +
3956
+
3957 auto alice = Account("alice");
+
3958 auto bob = Account("bob");
+
3959 env.fund(XRP(10000), alice, bob);
+
3960 env.close();
+
3961
+
3962 auto submitTx = [&](std::uint32_t flags) -> uint256 {
+
3963 auto jt = env.jt(pay(alice, bob, XRP(1)), txflags(flags));
+
3964 Serializer s;
+
3965 jt.stx->add(s);
+
3966 env.app().getOPs().submitTransaction(jt.stx);
+
3967 return jt.stx->getTransactionID();
+
3968 };
+
3969
+
3970 auto processTxn = [&](std::uint32_t flags) -> uint256 {
+
3971 auto jt = env.jt(pay(alice, bob, XRP(1)), txflags(flags));
+
3972 Serializer s;
+
3973 jt.stx->add(s);
+
3974 std::string reason;
+
3975 auto transaction =
+
3976 std::make_shared<Transaction>(jt.stx, reason, env.app());
+ +
3978 transaction, false, true, NetworkOPs::FailHard::yes);
+
3979 return transaction->getID();
+
3980 };
+
3981
+
3982 // Validate: NetworkOPs::submitTransaction()
+
3983 {
+
3984 // Submit a tx with tfInnerBatchTxn
+
3985 uint256 const txBad = submitTx(tfInnerBatchTxn);
+
3986 BEAST_EXPECT(
+
3987 env.app().getHashRouter().getFlags(txBad) ==
+ +
3989 }
+
3990
+
3991 // Validate: NetworkOPs::processTransaction()
+
3992 {
+
3993 uint256 const txid = processTxn(tfInnerBatchTxn);
+
3994 // HashRouter::getFlags() should return LedgerFlags::BAD
+
3995 BEAST_EXPECT(
+
3996 env.app().getHashRouter().getFlags(txid) ==
+ +
3998 }
+
3999 }
-
3998
-
3999 void
-
- -
4001 {
-
4002 testcase("batch delegate");
-
4003
-
4004 using namespace test::jtx;
-
4005 using namespace std::literals;
-
4006
-
4007 // delegated non atomic inner
-
4008 {
-
4009 test::jtx::Env env{*this, features};
-
4010
-
4011 auto const alice = Account("alice");
-
4012 auto const bob = Account("bob");
-
4013 auto const gw = Account("gw");
-
4014 auto const USD = gw["USD"];
-
4015 env.fund(XRP(10000), alice, bob, gw);
-
4016 env.close();
-
4017
-
4018 env(delegate::set(alice, bob, {"Payment"}));
-
4019 env.close();
-
4020
-
4021 auto const preAlice = env.balance(alice);
-
4022 auto const preBob = env.balance(bob);
-
4023
-
4024 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
4025 auto const seq = env.seq(alice);
-
4026
-
4027 auto tx = batch::inner(pay(alice, bob, XRP(1)), seq + 1);
-
4028 tx[jss::Delegate] = bob.human();
-
4029 auto const [txIDs, batchID] = submitBatch(
-
4030 env,
-
4031 tesSUCCESS,
-
4032 batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
4033 tx,
-
4034 batch::inner(pay(alice, bob, XRP(2)), seq + 2));
-
4035 env.close();
-
4036
-
4037 std::vector<TestLedgerData> testCases = {
-
4038 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
4039 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
4040 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
4041 };
-
4042 validateClosedLedger(env, testCases);
-
4043
-
4044 // Alice consumes sequences (# of txns)
-
4045 BEAST_EXPECT(env.seq(alice) == seq + 3);
-
4046
-
4047 // Alice pays XRP & Fee; Bob receives XRP
-
4048 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(3) - batchFee);
-
4049 BEAST_EXPECT(env.balance(bob) == preBob + XRP(3));
-
4050 }
-
4051
-
4052 // delegated atomic inner
-
4053 {
-
4054 test::jtx::Env env{*this, features};
-
4055
-
4056 auto const alice = Account("alice");
-
4057 auto const bob = Account("bob");
-
4058 auto const carol = Account("carol");
-
4059 auto const gw = Account("gw");
-
4060 auto const USD = gw["USD"];
-
4061 env.fund(XRP(10000), alice, bob, carol, gw);
-
4062 env.close();
-
4063
-
4064 env(delegate::set(bob, carol, {"Payment"}));
-
4065 env.close();
-
4066
-
4067 auto const preAlice = env.balance(alice);
-
4068 auto const preBob = env.balance(bob);
-
4069 auto const preCarol = env.balance(carol);
-
4070
-
4071 auto const batchFee = batch::calcBatchFee(env, 1, 2);
-
4072 auto const aliceSeq = env.seq(alice);
-
4073 auto const bobSeq = env.seq(bob);
-
4074
-
4075 auto tx = batch::inner(pay(bob, alice, XRP(1)), bobSeq);
-
4076 tx[jss::Delegate] = carol.human();
-
4077 auto const [txIDs, batchID] = submitBatch(
-
4078 env,
-
4079 tesSUCCESS,
-
4080 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
-
4081 tx,
-
4082 batch::inner(pay(alice, bob, XRP(2)), aliceSeq + 1),
-
4083 batch::sig(bob));
-
4084 env.close();
-
4085
-
4086 std::vector<TestLedgerData> testCases = {
-
4087 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
4088 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
-
4089 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
4090 };
-
4091 validateClosedLedger(env, testCases);
-
4092
-
4093 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
-
4094 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
-
4095 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(1) - batchFee);
-
4096 BEAST_EXPECT(env.balance(bob) == preBob + XRP(1));
-
4097 // NOTE: Carol would normally pay the fee for delegated txns, but
-
4098 // because the batch is atomic, the fee is paid by the batch
-
4099 BEAST_EXPECT(env.balance(carol) == preCarol);
-
4100 }
-
4101
-
4102 // delegated non atomic inner (AccountSet)
-
4103 // this also makes sure tfInnerBatchTxn won't block delegated AccountSet
-
4104 // with granular permission
-
4105 {
-
4106 test::jtx::Env env{*this, features};
-
4107
-
4108 auto const alice = Account("alice");
-
4109 auto const bob = Account("bob");
-
4110 auto const gw = Account("gw");
-
4111 auto const USD = gw["USD"];
-
4112 env.fund(XRP(10000), alice, bob, gw);
-
4113 env.close();
-
4114
-
4115 env(delegate::set(alice, bob, {"AccountDomainSet"}));
-
4116 env.close();
-
4117
-
4118 auto const preAlice = env.balance(alice);
-
4119 auto const preBob = env.balance(bob);
-
4120
-
4121 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
4122 auto const seq = env.seq(alice);
-
4123
-
4124 auto tx = batch::inner(noop(alice), seq + 1);
-
4125 std::string const domain = "example.com";
-
4126 tx[sfDomain.jsonName] = strHex(domain);
-
4127 tx[jss::Delegate] = bob.human();
-
4128 auto const [txIDs, batchID] = submitBatch(
-
4129 env,
-
4130 tesSUCCESS,
-
4131 batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
4132 tx,
-
4133 batch::inner(pay(alice, bob, XRP(2)), seq + 2));
-
4134 env.close();
-
4135
-
4136 std::vector<TestLedgerData> testCases = {
-
4137 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
4138 {1, "AccountSet", "tesSUCCESS", txIDs[0], batchID},
-
4139 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
-
4140 };
-
4141 validateClosedLedger(env, testCases);
-
4142
-
4143 // Alice consumes sequences (# of txns)
-
4144 BEAST_EXPECT(env.seq(alice) == seq + 3);
-
4145
-
4146 // Alice pays XRP & Fee; Bob receives XRP
-
4147 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(2) - batchFee);
-
4148 BEAST_EXPECT(env.balance(bob) == preBob + XRP(2));
-
4149 }
-
4150
-
4151 // delegated non atomic inner (MPTokenIssuanceSet)
-
4152 // this also makes sure tfInnerBatchTxn won't block delegated
-
4153 // MPTokenIssuanceSet with granular permission
-
4154 {
-
4155 test::jtx::Env env{*this, features};
-
4156 Account alice{"alice"};
-
4157 Account bob{"bob"};
-
4158 env.fund(XRP(100000), alice, bob);
-
4159 env.close();
-
4160
-
4161 auto const mptID = makeMptID(env.seq(alice), alice);
-
4162 MPTTester mpt(env, alice, {.fund = false});
-
4163 env.close();
-
4164 mpt.create({.flags = tfMPTCanLock});
+
4000
+
4001 void
+
+ +
4003 {
+
4004 testcase("batch delegate");
+
4005
+
4006 using namespace test::jtx;
+
4007 using namespace std::literals;
+
4008
+
4009 // delegated non atomic inner
+
4010 {
+
4011 test::jtx::Env env{*this, features};
+
4012
+
4013 auto const alice = Account("alice");
+
4014 auto const bob = Account("bob");
+
4015 auto const gw = Account("gw");
+
4016 auto const USD = gw["USD"];
+
4017 env.fund(XRP(10000), alice, bob, gw);
+
4018 env.close();
+
4019
+
4020 env(delegate::set(alice, bob, {"Payment"}));
+
4021 env.close();
+
4022
+
4023 auto const preAlice = env.balance(alice);
+
4024 auto const preBob = env.balance(bob);
+
4025
+
4026 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
4027 auto const seq = env.seq(alice);
+
4028
+
4029 auto tx = batch::inner(pay(alice, bob, XRP(1)), seq + 1);
+
4030 tx[jss::Delegate] = bob.human();
+
4031 auto const [txIDs, batchID] = submitBatch(
+
4032 env,
+
4033 tesSUCCESS,
+
4034 batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
4035 tx,
+
4036 batch::inner(pay(alice, bob, XRP(2)), seq + 2));
+
4037 env.close();
+
4038
+
4039 std::vector<TestLedgerData> testCases = {
+
4040 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
4041 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
4042 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
4043 };
+
4044 validateClosedLedger(env, testCases);
+
4045
+
4046 // Alice consumes sequences (# of txns)
+
4047 BEAST_EXPECT(env.seq(alice) == seq + 3);
+
4048
+
4049 // Alice pays XRP & Fee; Bob receives XRP
+
4050 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(3) - batchFee);
+
4051 BEAST_EXPECT(env.balance(bob) == preBob + XRP(3));
+
4052 }
+
4053
+
4054 // delegated atomic inner
+
4055 {
+
4056 test::jtx::Env env{*this, features};
+
4057
+
4058 auto const alice = Account("alice");
+
4059 auto const bob = Account("bob");
+
4060 auto const carol = Account("carol");
+
4061 auto const gw = Account("gw");
+
4062 auto const USD = gw["USD"];
+
4063 env.fund(XRP(10000), alice, bob, carol, gw);
+
4064 env.close();
+
4065
+
4066 env(delegate::set(bob, carol, {"Payment"}));
+
4067 env.close();
+
4068
+
4069 auto const preAlice = env.balance(alice);
+
4070 auto const preBob = env.balance(bob);
+
4071 auto const preCarol = env.balance(carol);
+
4072
+
4073 auto const batchFee = batch::calcBatchFee(env, 1, 2);
+
4074 auto const aliceSeq = env.seq(alice);
+
4075 auto const bobSeq = env.seq(bob);
+
4076
+
4077 auto tx = batch::inner(pay(bob, alice, XRP(1)), bobSeq);
+
4078 tx[jss::Delegate] = carol.human();
+
4079 auto const [txIDs, batchID] = submitBatch(
+
4080 env,
+
4081 tesSUCCESS,
+
4082 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
+
4083 tx,
+
4084 batch::inner(pay(alice, bob, XRP(2)), aliceSeq + 1),
+
4085 batch::sig(bob));
+
4086 env.close();
+
4087
+
4088 std::vector<TestLedgerData> testCases = {
+
4089 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
4090 {1, "Payment", "tesSUCCESS", txIDs[0], batchID},
+
4091 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
4092 };
+
4093 validateClosedLedger(env, testCases);
+
4094
+
4095 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
+
4096 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
+
4097 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(1) - batchFee);
+
4098 BEAST_EXPECT(env.balance(bob) == preBob + XRP(1));
+
4099 // NOTE: Carol would normally pay the fee for delegated txns, but
+
4100 // because the batch is atomic, the fee is paid by the batch
+
4101 BEAST_EXPECT(env.balance(carol) == preCarol);
+
4102 }
+
4103
+
4104 // delegated non atomic inner (AccountSet)
+
4105 // this also makes sure tfInnerBatchTxn won't block delegated AccountSet
+
4106 // with granular permission
+
4107 {
+
4108 test::jtx::Env env{*this, features};
+
4109
+
4110 auto const alice = Account("alice");
+
4111 auto const bob = Account("bob");
+
4112 auto const gw = Account("gw");
+
4113 auto const USD = gw["USD"];
+
4114 env.fund(XRP(10000), alice, bob, gw);
+
4115 env.close();
+
4116
+
4117 env(delegate::set(alice, bob, {"AccountDomainSet"}));
+
4118 env.close();
+
4119
+
4120 auto const preAlice = env.balance(alice);
+
4121 auto const preBob = env.balance(bob);
+
4122
+
4123 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
4124 auto const seq = env.seq(alice);
+
4125
+
4126 auto tx = batch::inner(noop(alice), seq + 1);
+
4127 std::string const domain = "example.com";
+
4128 tx[sfDomain.jsonName] = strHex(domain);
+
4129 tx[jss::Delegate] = bob.human();
+
4130 auto const [txIDs, batchID] = submitBatch(
+
4131 env,
+
4132 tesSUCCESS,
+
4133 batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
4134 tx,
+
4135 batch::inner(pay(alice, bob, XRP(2)), seq + 2));
+
4136 env.close();
+
4137
+
4138 std::vector<TestLedgerData> testCases = {
+
4139 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
4140 {1, "AccountSet", "tesSUCCESS", txIDs[0], batchID},
+
4141 {2, "Payment", "tesSUCCESS", txIDs[1], batchID},
+
4142 };
+
4143 validateClosedLedger(env, testCases);
+
4144
+
4145 // Alice consumes sequences (# of txns)
+
4146 BEAST_EXPECT(env.seq(alice) == seq + 3);
+
4147
+
4148 // Alice pays XRP & Fee; Bob receives XRP
+
4149 BEAST_EXPECT(env.balance(alice) == preAlice - XRP(2) - batchFee);
+
4150 BEAST_EXPECT(env.balance(bob) == preBob + XRP(2));
+
4151 }
+
4152
+
4153 // delegated non atomic inner (MPTokenIssuanceSet)
+
4154 // this also makes sure tfInnerBatchTxn won't block delegated
+
4155 // MPTokenIssuanceSet with granular permission
+
4156 {
+
4157 test::jtx::Env env{*this, features};
+
4158 Account alice{"alice"};
+
4159 Account bob{"bob"};
+
4160 env.fund(XRP(100000), alice, bob);
+
4161 env.close();
+
4162
+
4163 auto const mptID = makeMptID(env.seq(alice), alice);
+
4164 MPTTester mpt(env, alice, {.fund = false});
4165 env.close();
-
4166
-
4167 // alice gives granular permission to bob of MPTokenIssuanceLock
-
4168 env(delegate::set(
-
4169 alice, bob, {"MPTokenIssuanceLock", "MPTokenIssuanceUnlock"}));
-
4170 env.close();
-
4171
-
4172 auto const seq = env.seq(alice);
-
4173 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
4174
-
4175 Json::Value jv1;
-
4176 jv1[sfTransactionType] = jss::MPTokenIssuanceSet;
-
4177 jv1[sfAccount] = alice.human();
-
4178 jv1[sfDelegate] = bob.human();
-
4179 jv1[sfSequence] = seq + 1;
-
4180 jv1[sfMPTokenIssuanceID] = to_string(mptID);
-
4181 jv1[sfFlags] = tfMPTLock;
-
4182
-
4183 Json::Value jv2;
-
4184 jv2[sfTransactionType] = jss::MPTokenIssuanceSet;
-
4185 jv2[sfAccount] = alice.human();
-
4186 jv2[sfDelegate] = bob.human();
-
4187 jv2[sfSequence] = seq + 2;
-
4188 jv2[sfMPTokenIssuanceID] = to_string(mptID);
-
4189 jv2[sfFlags] = tfMPTUnlock;
-
4190
-
4191 auto const [txIDs, batchID] = submitBatch(
-
4192 env,
-
4193 tesSUCCESS,
-
4194 batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
4195 batch::inner(jv1, seq + 1),
-
4196 batch::inner(jv2, seq + 2));
-
4197 env.close();
-
4198
-
4199 std::vector<TestLedgerData> testCases = {
-
4200 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
4201 {1, "MPTokenIssuanceSet", "tesSUCCESS", txIDs[0], batchID},
-
4202 {2, "MPTokenIssuanceSet", "tesSUCCESS", txIDs[1], batchID},
-
4203 };
-
4204 validateClosedLedger(env, testCases);
-
4205 }
-
4206
-
4207 // delegated non atomic inner (TrustSet)
-
4208 // this also makes sure tfInnerBatchTxn won't block delegated TrustSet
-
4209 // with granular permission
-
4210 {
-
4211 test::jtx::Env env{*this, features};
-
4212 Account gw{"gw"};
-
4213 Account alice{"alice"};
-
4214 Account bob{"bob"};
-
4215 env.fund(XRP(10000), gw, alice, bob);
-
4216 env(fset(gw, asfRequireAuth));
-
4217 env.close();
-
4218 env(trust(alice, gw["USD"](50)));
+
4166 mpt.create({.flags = tfMPTCanLock});
+
4167 env.close();
+
4168
+
4169 // alice gives granular permission to bob of MPTokenIssuanceLock
+
4170 env(delegate::set(
+
4171 alice, bob, {"MPTokenIssuanceLock", "MPTokenIssuanceUnlock"}));
+
4172 env.close();
+
4173
+
4174 auto const seq = env.seq(alice);
+
4175 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
4176
+
4177 Json::Value jv1;
+
4178 jv1[sfTransactionType] = jss::MPTokenIssuanceSet;
+
4179 jv1[sfAccount] = alice.human();
+
4180 jv1[sfDelegate] = bob.human();
+
4181 jv1[sfSequence] = seq + 1;
+
4182 jv1[sfMPTokenIssuanceID] = to_string(mptID);
+
4183 jv1[sfFlags] = tfMPTLock;
+
4184
+
4185 Json::Value jv2;
+
4186 jv2[sfTransactionType] = jss::MPTokenIssuanceSet;
+
4187 jv2[sfAccount] = alice.human();
+
4188 jv2[sfDelegate] = bob.human();
+
4189 jv2[sfSequence] = seq + 2;
+
4190 jv2[sfMPTokenIssuanceID] = to_string(mptID);
+
4191 jv2[sfFlags] = tfMPTUnlock;
+
4192
+
4193 auto const [txIDs, batchID] = submitBatch(
+
4194 env,
+
4195 tesSUCCESS,
+
4196 batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
4197 batch::inner(jv1, seq + 1),
+
4198 batch::inner(jv2, seq + 2));
+
4199 env.close();
+
4200
+
4201 std::vector<TestLedgerData> testCases = {
+
4202 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
4203 {1, "MPTokenIssuanceSet", "tesSUCCESS", txIDs[0], batchID},
+
4204 {2, "MPTokenIssuanceSet", "tesSUCCESS", txIDs[1], batchID},
+
4205 };
+
4206 validateClosedLedger(env, testCases);
+
4207 }
+
4208
+
4209 // delegated non atomic inner (TrustSet)
+
4210 // this also makes sure tfInnerBatchTxn won't block delegated TrustSet
+
4211 // with granular permission
+
4212 {
+
4213 test::jtx::Env env{*this, features};
+
4214 Account gw{"gw"};
+
4215 Account alice{"alice"};
+
4216 Account bob{"bob"};
+
4217 env.fund(XRP(10000), gw, alice, bob);
+
4218 env(fset(gw, asfRequireAuth));
4219 env.close();
-
4220
-
4221 env(delegate::set(
-
4222 gw, bob, {"TrustlineAuthorize", "TrustlineFreeze"}));
-
4223 env.close();
-
4224
-
4225 auto const seq = env.seq(gw);
-
4226 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
4227
-
4228 auto jv1 = trust(gw, gw["USD"](0), alice, tfSetfAuth);
-
4229 jv1[sfDelegate] = bob.human();
-
4230 auto jv2 = trust(gw, gw["USD"](0), alice, tfSetFreeze);
-
4231 jv2[sfDelegate] = bob.human();
-
4232
-
4233 auto const [txIDs, batchID] = submitBatch(
-
4234 env,
-
4235 tesSUCCESS,
-
4236 batch::outer(gw, seq, batchFee, tfAllOrNothing),
-
4237 batch::inner(jv1, seq + 1),
-
4238 batch::inner(jv2, seq + 2));
-
4239 env.close();
-
4240
-
4241 std::vector<TestLedgerData> testCases = {
-
4242 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
4243 {1, "TrustSet", "tesSUCCESS", txIDs[0], batchID},
-
4244 {2, "TrustSet", "tesSUCCESS", txIDs[1], batchID},
-
4245 };
-
4246 validateClosedLedger(env, testCases);
-
4247 }
-
4248
-
4249 // inner transaction not authorized by the delegating account.
-
4250 {
-
4251 test::jtx::Env env{*this, features};
-
4252 Account gw{"gw"};
-
4253 Account alice{"alice"};
-
4254 Account bob{"bob"};
-
4255 env.fund(XRP(10000), gw, alice, bob);
-
4256 env(fset(gw, asfRequireAuth));
-
4257 env.close();
-
4258 env(trust(alice, gw["USD"](50)));
+
4220 env(trust(alice, gw["USD"](50)));
+
4221 env.close();
+
4222
+
4223 env(delegate::set(
+
4224 gw, bob, {"TrustlineAuthorize", "TrustlineFreeze"}));
+
4225 env.close();
+
4226
+
4227 auto const seq = env.seq(gw);
+
4228 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
4229
+
4230 auto jv1 = trust(gw, gw["USD"](0), alice, tfSetfAuth);
+
4231 jv1[sfDelegate] = bob.human();
+
4232 auto jv2 = trust(gw, gw["USD"](0), alice, tfSetFreeze);
+
4233 jv2[sfDelegate] = bob.human();
+
4234
+
4235 auto const [txIDs, batchID] = submitBatch(
+
4236 env,
+
4237 tesSUCCESS,
+
4238 batch::outer(gw, seq, batchFee, tfAllOrNothing),
+
4239 batch::inner(jv1, seq + 1),
+
4240 batch::inner(jv2, seq + 2));
+
4241 env.close();
+
4242
+
4243 std::vector<TestLedgerData> testCases = {
+
4244 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
4245 {1, "TrustSet", "tesSUCCESS", txIDs[0], batchID},
+
4246 {2, "TrustSet", "tesSUCCESS", txIDs[1], batchID},
+
4247 };
+
4248 validateClosedLedger(env, testCases);
+
4249 }
+
4250
+
4251 // inner transaction not authorized by the delegating account.
+
4252 {
+
4253 test::jtx::Env env{*this, features};
+
4254 Account gw{"gw"};
+
4255 Account alice{"alice"};
+
4256 Account bob{"bob"};
+
4257 env.fund(XRP(10000), gw, alice, bob);
+
4258 env(fset(gw, asfRequireAuth));
4259 env.close();
-
4260
-
4261 env(delegate::set(
-
4262 gw, bob, {"TrustlineAuthorize", "TrustlineFreeze"}));
-
4263 env.close();
-
4264
-
4265 auto const seq = env.seq(gw);
-
4266 auto const batchFee = batch::calcBatchFee(env, 0, 2);
-
4267
-
4268 auto jv1 = trust(gw, gw["USD"](0), alice, tfSetFreeze);
-
4269 jv1[sfDelegate] = bob.human();
-
4270 auto jv2 = trust(gw, gw["USD"](0), alice, tfClearFreeze);
-
4271 jv2[sfDelegate] = bob.human();
-
4272
-
4273 auto const [txIDs, batchID] = submitBatch(
-
4274 env,
-
4275 tesSUCCESS,
-
4276 batch::outer(gw, seq, batchFee, tfIndependent),
-
4277 batch::inner(jv1, seq + 1),
-
4278 // terNO_DELEGATE_PERMISSION: not authorized to clear freeze
-
4279 batch::inner(jv2, seq + 2));
-
4280 env.close();
-
4281
-
4282 std::vector<TestLedgerData> testCases = {
-
4283 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
-
4284 {1, "TrustSet", "tesSUCCESS", txIDs[0], batchID},
-
4285 };
-
4286 validateClosedLedger(env, testCases);
-
4287 }
-
4288 }
+
4260 env(trust(alice, gw["USD"](50)));
+
4261 env.close();
+
4262
+
4263 env(delegate::set(
+
4264 gw, bob, {"TrustlineAuthorize", "TrustlineFreeze"}));
+
4265 env.close();
+
4266
+
4267 auto const seq = env.seq(gw);
+
4268 auto const batchFee = batch::calcBatchFee(env, 0, 2);
+
4269
+
4270 auto jv1 = trust(gw, gw["USD"](0), alice, tfSetFreeze);
+
4271 jv1[sfDelegate] = bob.human();
+
4272 auto jv2 = trust(gw, gw["USD"](0), alice, tfClearFreeze);
+
4273 jv2[sfDelegate] = bob.human();
+
4274
+
4275 auto const [txIDs, batchID] = submitBatch(
+
4276 env,
+
4277 tesSUCCESS,
+
4278 batch::outer(gw, seq, batchFee, tfIndependent),
+
4279 batch::inner(jv1, seq + 1),
+
4280 // terNO_DELEGATE_PERMISSION: not authorized to clear freeze
+
4281 batch::inner(jv2, seq + 2));
+
4282 env.close();
+
4283
+
4284 std::vector<TestLedgerData> testCases = {
+
4285 {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
+
4286 {1, "TrustSet", "tesSUCCESS", txIDs[0], batchID},
+
4287 };
+
4288 validateClosedLedger(env, testCases);
+
4289 }
+
4290 }
-
4289
-
4290 void
-
- -
4292 {
-
4293 // Verifying that the RPC response from submit includes
-
4294 // the account_sequence_available, account_sequence_next,
-
4295 // open_ledger_cost and validated_ledger_index fields.
-
4296 testcase("Validate RPC response");
-
4297
-
4298 using namespace jtx;
-
4299 Env env(*this, features);
-
4300 Account const alice("alice");
-
4301 Account const bob("bob");
-
4302 env.fund(XRP(10000), alice, bob);
-
4303 env.close();
-
4304
-
4305 // tes
-
4306 {
-
4307 auto const baseFee = env.current()->fees().base;
-
4308 auto const aliceSeq = env.seq(alice);
-
4309 auto jtx = env.jt(pay(alice, bob, XRP(1)));
-
4310
-
4311 Serializer s;
-
4312 jtx.stx->add(s);
-
4313 auto const jr = env.rpc("submit", strHex(s.slice()))[jss::result];
-
4314 env.close();
-
4315
-
4316 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
-
4317 BEAST_EXPECT(
-
4318 jr[jss::account_sequence_available].asUInt() == aliceSeq + 1);
-
4319 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
-
4320 BEAST_EXPECT(
-
4321 jr[jss::account_sequence_next].asUInt() == aliceSeq + 1);
-
4322 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
-
4323 BEAST_EXPECT(jr[jss::open_ledger_cost] == to_string(baseFee));
-
4324 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
-
4325 }
-
4326
-
4327 // tec failure
-
4328 {
-
4329 auto const baseFee = env.current()->fees().base;
-
4330 auto const aliceSeq = env.seq(alice);
-
4331 env(fset(bob, asfRequireDest));
-
4332 auto jtx = env.jt(pay(alice, bob, XRP(1)), seq(aliceSeq));
-
4333
-
4334 Serializer s;
-
4335 jtx.stx->add(s);
-
4336 auto const jr = env.rpc("submit", strHex(s.slice()))[jss::result];
-
4337 env.close();
-
4338
-
4339 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
-
4340 BEAST_EXPECT(
-
4341 jr[jss::account_sequence_available].asUInt() == aliceSeq + 1);
-
4342 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
-
4343 BEAST_EXPECT(
-
4344 jr[jss::account_sequence_next].asUInt() == aliceSeq + 1);
-
4345 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
-
4346 BEAST_EXPECT(jr[jss::open_ledger_cost] == to_string(baseFee));
-
4347 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
-
4348 }
-
4349
-
4350 // tem failure
-
4351 {
-
4352 auto const baseFee = env.current()->fees().base;
-
4353 auto const aliceSeq = env.seq(alice);
-
4354 auto jtx = env.jt(pay(alice, bob, XRP(1)), seq(aliceSeq + 1));
-
4355
-
4356 Serializer s;
-
4357 jtx.stx->add(s);
-
4358 auto const jr = env.rpc("submit", strHex(s.slice()))[jss::result];
-
4359 env.close();
-
4360
-
4361 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
-
4362 BEAST_EXPECT(
-
4363 jr[jss::account_sequence_available].asUInt() == aliceSeq);
-
4364 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
-
4365 BEAST_EXPECT(jr[jss::account_sequence_next].asUInt() == aliceSeq);
-
4366 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
-
4367 BEAST_EXPECT(jr[jss::open_ledger_cost] == to_string(baseFee));
-
4368 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
-
4369 }
-
4370 }
+
4291
+
4292 void
+
+ +
4294 {
+
4295 // Verifying that the RPC response from submit includes
+
4296 // the account_sequence_available, account_sequence_next,
+
4297 // open_ledger_cost and validated_ledger_index fields.
+
4298 testcase("Validate RPC response");
+
4299
+
4300 using namespace jtx;
+
4301 Env env(*this, features);
+
4302 Account const alice("alice");
+
4303 Account const bob("bob");
+
4304 env.fund(XRP(10000), alice, bob);
+
4305 env.close();
+
4306
+
4307 // tes
+
4308 {
+
4309 auto const baseFee = env.current()->fees().base;
+
4310 auto const aliceSeq = env.seq(alice);
+
4311 auto jtx = env.jt(pay(alice, bob, XRP(1)));
+
4312
+
4313 Serializer s;
+
4314 jtx.stx->add(s);
+
4315 auto const jr = env.rpc("submit", strHex(s.slice()))[jss::result];
+
4316 env.close();
+
4317
+
4318 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
+
4319 BEAST_EXPECT(
+
4320 jr[jss::account_sequence_available].asUInt() == aliceSeq + 1);
+
4321 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
+
4322 BEAST_EXPECT(
+
4323 jr[jss::account_sequence_next].asUInt() == aliceSeq + 1);
+
4324 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
+
4325 BEAST_EXPECT(jr[jss::open_ledger_cost] == to_string(baseFee));
+
4326 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
+
4327 }
+
4328
+
4329 // tec failure
+
4330 {
+
4331 auto const baseFee = env.current()->fees().base;
+
4332 auto const aliceSeq = env.seq(alice);
+
4333 env(fset(bob, asfRequireDest));
+
4334 auto jtx = env.jt(pay(alice, bob, XRP(1)), seq(aliceSeq));
+
4335
+
4336 Serializer s;
+
4337 jtx.stx->add(s);
+
4338 auto const jr = env.rpc("submit", strHex(s.slice()))[jss::result];
+
4339 env.close();
+
4340
+
4341 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
+
4342 BEAST_EXPECT(
+
4343 jr[jss::account_sequence_available].asUInt() == aliceSeq + 1);
+
4344 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
+
4345 BEAST_EXPECT(
+
4346 jr[jss::account_sequence_next].asUInt() == aliceSeq + 1);
+
4347 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
+
4348 BEAST_EXPECT(jr[jss::open_ledger_cost] == to_string(baseFee));
+
4349 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
+
4350 }
+
4351
+
4352 // tem failure
+
4353 {
+
4354 auto const baseFee = env.current()->fees().base;
+
4355 auto const aliceSeq = env.seq(alice);
+
4356 auto jtx = env.jt(pay(alice, bob, XRP(1)), seq(aliceSeq + 1));
+
4357
+
4358 Serializer s;
+
4359 jtx.stx->add(s);
+
4360 auto const jr = env.rpc("submit", strHex(s.slice()))[jss::result];
+
4361 env.close();
+
4362
+
4363 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
+
4364 BEAST_EXPECT(
+
4365 jr[jss::account_sequence_available].asUInt() == aliceSeq);
+
4366 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
+
4367 BEAST_EXPECT(jr[jss::account_sequence_next].asUInt() == aliceSeq);
+
4368 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
+
4369 BEAST_EXPECT(jr[jss::open_ledger_cost] == to_string(baseFee));
+
4370 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
+
4371 }
+
4372 }
-
4371
-
4372 void
-
- -
4374 {
-
4375 using namespace jtx;
-
4376 Env env(*this, features);
-
4377 Account const alice("alice");
-
4378 Account const bob("bob");
-
4379 Account const carol("carol");
-
4380 env.fund(XRP(10000), alice, bob, carol);
-
4381 env.close();
-
4382
-
4383 auto getBaseFee = [&](JTx const& jtx) -> XRPAmount {
-
4384 Serializer s;
-
4385 jtx.stx->add(s);
-
4386 return Batch::calculateBaseFee(*env.current(), *jtx.stx);
-
4387 };
-
4388
-
4389 // bad: Inner Batch transaction found
-
4390 {
-
4391 auto const seq = env.seq(alice);
-
4392 XRPAmount const batchFee = batch::calcBatchFee(env, 0, 2);
-
4393 auto jtx = env.jt(
-
4394 batch::outer(alice, seq, batchFee, tfAllOrNothing),
- -
4396 batch::outer(alice, seq, batchFee, tfAllOrNothing), seq),
-
4397 batch::inner(pay(alice, bob, XRP(1)), seq + 2));
-
4398 XRPAmount const txBaseFee = getBaseFee(jtx);
-
4399 BEAST_EXPECT(txBaseFee == XRPAmount(INITIAL_XRP));
-
4400 }
-
4401
-
4402 // bad: Raw Transactions array exceeds max entries.
-
4403 {
-
4404 auto const seq = env.seq(alice);
-
4405 XRPAmount const batchFee = batch::calcBatchFee(env, 0, 2);
-
4406
-
4407 auto jtx = env.jt(
-
4408 batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
4409 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
4410 batch::inner(pay(alice, bob, XRP(1)), seq + 2),
-
4411 batch::inner(pay(alice, bob, XRP(1)), seq + 3),
-
4412 batch::inner(pay(alice, bob, XRP(1)), seq + 4),
-
4413 batch::inner(pay(alice, bob, XRP(1)), seq + 5),
-
4414 batch::inner(pay(alice, bob, XRP(1)), seq + 6),
-
4415 batch::inner(pay(alice, bob, XRP(1)), seq + 7),
-
4416 batch::inner(pay(alice, bob, XRP(1)), seq + 8),
-
4417 batch::inner(pay(alice, bob, XRP(1)), seq + 9));
-
4418
-
4419 XRPAmount const txBaseFee = getBaseFee(jtx);
-
4420 BEAST_EXPECT(txBaseFee == XRPAmount(INITIAL_XRP));
-
4421 }
-
4422
-
4423 // bad: Signers array exceeds max entries.
-
4424 {
-
4425 auto const seq = env.seq(alice);
-
4426 XRPAmount const batchFee = batch::calcBatchFee(env, 0, 2);
-
4427
-
4428 auto jtx = env.jt(
-
4429 batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
4430 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
-
4431 batch::inner(pay(alice, bob, XRP(5)), seq + 2),
-
4432 batch::sig(
-
4433 bob,
-
4434 carol,
-
4435 alice,
-
4436 bob,
-
4437 carol,
-
4438 alice,
-
4439 bob,
-
4440 carol,
-
4441 alice,
-
4442 alice));
-
4443 XRPAmount const txBaseFee = getBaseFee(jtx);
-
4444 BEAST_EXPECT(txBaseFee == XRPAmount(INITIAL_XRP));
-
4445 }
-
4446
-
4447 // good:
-
4448 {
-
4449 auto const seq = env.seq(alice);
-
4450 XRPAmount const batchFee = batch::calcBatchFee(env, 0, 2);
-
4451 auto jtx = env.jt(
-
4452 batch::outer(alice, seq, batchFee, tfAllOrNothing),
-
4453 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
-
4454 batch::inner(pay(bob, alice, XRP(2)), seq + 2));
-
4455 XRPAmount const txBaseFee = getBaseFee(jtx);
-
4456 BEAST_EXPECT(txBaseFee == batchFee);
-
4457 }
-
4458 }
+
4373
+
4374 void
+
+ +
4376 {
+
4377 using namespace jtx;
+
4378 Env env(*this, features);
+
4379 Account const alice("alice");
+
4380 Account const bob("bob");
+
4381 Account const carol("carol");
+
4382 env.fund(XRP(10000), alice, bob, carol);
+
4383 env.close();
+
4384
+
4385 auto getBaseFee = [&](JTx const& jtx) -> XRPAmount {
+
4386 Serializer s;
+
4387 jtx.stx->add(s);
+
4388 return Batch::calculateBaseFee(*env.current(), *jtx.stx);
+
4389 };
+
4390
+
4391 // bad: Inner Batch transaction found
+
4392 {
+
4393 auto const seq = env.seq(alice);
+
4394 XRPAmount const batchFee = batch::calcBatchFee(env, 0, 2);
+
4395 auto jtx = env.jt(
+
4396 batch::outer(alice, seq, batchFee, tfAllOrNothing),
+ +
4398 batch::outer(alice, seq, batchFee, tfAllOrNothing), seq),
+
4399 batch::inner(pay(alice, bob, XRP(1)), seq + 2));
+
4400 XRPAmount const txBaseFee = getBaseFee(jtx);
+
4401 BEAST_EXPECT(txBaseFee == XRPAmount(INITIAL_XRP));
+
4402 }
+
4403
+
4404 // bad: Raw Transactions array exceeds max entries.
+
4405 {
+
4406 auto const seq = env.seq(alice);
+
4407 XRPAmount const batchFee = batch::calcBatchFee(env, 0, 2);
+
4408
+
4409 auto jtx = env.jt(
+
4410 batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
4411 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
4412 batch::inner(pay(alice, bob, XRP(1)), seq + 2),
+
4413 batch::inner(pay(alice, bob, XRP(1)), seq + 3),
+
4414 batch::inner(pay(alice, bob, XRP(1)), seq + 4),
+
4415 batch::inner(pay(alice, bob, XRP(1)), seq + 5),
+
4416 batch::inner(pay(alice, bob, XRP(1)), seq + 6),
+
4417 batch::inner(pay(alice, bob, XRP(1)), seq + 7),
+
4418 batch::inner(pay(alice, bob, XRP(1)), seq + 8),
+
4419 batch::inner(pay(alice, bob, XRP(1)), seq + 9));
+
4420
+
4421 XRPAmount const txBaseFee = getBaseFee(jtx);
+
4422 BEAST_EXPECT(txBaseFee == XRPAmount(INITIAL_XRP));
+
4423 }
+
4424
+
4425 // bad: Signers array exceeds max entries.
+
4426 {
+
4427 auto const seq = env.seq(alice);
+
4428 XRPAmount const batchFee = batch::calcBatchFee(env, 0, 2);
+
4429
+
4430 auto jtx = env.jt(
+
4431 batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
4432 batch::inner(pay(alice, bob, XRP(10)), seq + 1),
+
4433 batch::inner(pay(alice, bob, XRP(5)), seq + 2),
+
4434 batch::sig(
+
4435 bob,
+
4436 carol,
+
4437 alice,
+
4438 bob,
+
4439 carol,
+
4440 alice,
+
4441 bob,
+
4442 carol,
+
4443 alice,
+
4444 alice));
+
4445 XRPAmount const txBaseFee = getBaseFee(jtx);
+
4446 BEAST_EXPECT(txBaseFee == XRPAmount(INITIAL_XRP));
+
4447 }
+
4448
+
4449 // good:
+
4450 {
+
4451 auto const seq = env.seq(alice);
+
4452 XRPAmount const batchFee = batch::calcBatchFee(env, 0, 2);
+
4453 auto jtx = env.jt(
+
4454 batch::outer(alice, seq, batchFee, tfAllOrNothing),
+
4455 batch::inner(pay(alice, bob, XRP(1)), seq + 1),
+
4456 batch::inner(pay(bob, alice, XRP(2)), seq + 2));
+
4457 XRPAmount const txBaseFee = getBaseFee(jtx);
+
4458 BEAST_EXPECT(txBaseFee == batchFee);
+
4459 }
+
4460 }
-
4459
-
4460 void
-
- -
4462 {
-
4463 testEnable(features);
-
4464 testPreflight(features);
-
4465 testPreclaim(features);
-
4466 testBadRawTxn(features);
-
4467 testBadSequence(features);
-
4468 testBadOuterFee(features);
-
4469 testCalculateBaseFee(features);
-
4470 testAllOrNothing(features);
-
4471 testOnlyOne(features);
-
4472 testUntilFailure(features);
-
4473 testIndependent(features);
-
4474 testInnerSubmitRPC(features);
-
4475 testAccountActivation(features);
-
4476 testAccountSet(features);
-
4477 testAccountDelete(features);
-
4478 testLoan(features);
-
4479 testObjectCreateSequence(features);
-
4480 testObjectCreateTicket(features);
-
4481 testObjectCreate3rdParty(features);
-
4482 testTickets(features);
-
4483 testSequenceOpenLedger(features);
-
4484 testTicketsOpenLedger(features);
-
4485 testObjectsOpenLedger(features);
-
4486 testPseudoTxn(features);
-
4487 testOpenLedger(features);
-
4488 testBatchTxQueue(features);
-
4489 testBatchNetworkOps(features);
-
4490 testBatchDelegate(features);
-
4491 testValidateRPCResponse(features);
-
4492 testBatchCalculateBaseFee(features);
-
4493 }
+
4461
+
4462 void
+
+ +
4464 {
+
4465 testEnable(features);
+
4466 testPreflight(features);
+
4467 testPreclaim(features);
+
4468 testBadRawTxn(features);
+
4469 testBadSequence(features);
+
4470 testBadOuterFee(features);
+
4471 testCalculateBaseFee(features);
+
4472 testAllOrNothing(features);
+
4473 testOnlyOne(features);
+
4474 testUntilFailure(features);
+
4475 testIndependent(features);
+
4476 testInnerSubmitRPC(features);
+
4477 testAccountActivation(features);
+
4478 testAccountSet(features);
+
4479 testAccountDelete(features);
+
4480 testLoan(features);
+
4481 testObjectCreateSequence(features);
+
4482 testObjectCreateTicket(features);
+
4483 testObjectCreate3rdParty(features);
+
4484 testTickets(features);
+
4485 testSequenceOpenLedger(features);
+
4486 testTicketsOpenLedger(features);
+
4487 testObjectsOpenLedger(features);
+
4488 testPseudoTxn(features);
+
4489 testOpenLedger(features);
+
4490 testBatchTxQueue(features);
+
4491 testBatchNetworkOps(features);
+
4492 testBatchDelegate(features);
+
4493 testValidateRPCResponse(features);
+
4494 testBatchCalculateBaseFee(features);
+
4495 }
-
4494
-
4495public:
-
4496 void
-
-
4497 run() override
-
4498 {
-
4499 using namespace test::jtx;
-
4500 auto const sa = testable_amendments();
-
4501 testWithFeats(sa - fixBatchInnerSigs);
-
4502 testWithFeats(sa);
-
4503 }
+
4496
+
4497public:
+
4498 void
+
+
4499 run() override
+
4500 {
+
4501 using namespace test::jtx;
+
4502 auto const sa = testable_amendments();
+
4503 testWithFeats(sa - fixBatchInnerSigs);
+
4504 testWithFeats(sa);
+
4505 }
-
4504};
+
4506};
-
4505
-
4506BEAST_DEFINE_TESTSUITE(Batch, app, xrpl);
4507
-
4508} // namespace test
-
4509} // namespace xrpl
+
4508BEAST_DEFINE_TESTSUITE(Batch, app, xrpl);
+
4509
+
4510} // namespace test
+
4511} // namespace xrpl
T any_of(T... args)
@@ -4711,47 +4713,47 @@ $(document).ready(function() { init_codefold(0); }); -
void testOpenLedger(FeatureBitset features)
-
void testTicketsOpenLedger(FeatureBitset features)
-
void run() override
Runs the suite.
-
void testBadRawTxn(FeatureBitset features)
-
void testObjectsOpenLedger(FeatureBitset features)
-
void testSequenceOpenLedger(FeatureBitset features)
+
void testOpenLedger(FeatureBitset features)
+
void testTicketsOpenLedger(FeatureBitset features)
+
void run() override
Runs the suite.
+
void testBadRawTxn(FeatureBitset features)
+
void testObjectsOpenLedger(FeatureBitset features)
+
void testSequenceOpenLedger(FeatureBitset features)
void testEnable(FeatureBitset features)
void testPreflight(FeatureBitset features)
-
void testObjectCreate3rdParty(FeatureBitset features)
+
void testObjectCreate3rdParty(FeatureBitset features)
auto openLedgerFee(jtx::Env &env, XRPAmount const &batchFee)
-
void testIndependent(FeatureBitset features)
-
void doTestInnerSubmitRPC(FeatureBitset features, bool withBatch)
-
void testBatchDelegate(FeatureBitset features)
-
void testBadSequence(FeatureBitset features)
-
void testTickets(FeatureBitset features)
-
void testAccountSet(FeatureBitset features)
+
void testIndependent(FeatureBitset features)
+
void doTestInnerSubmitRPC(FeatureBitset features, bool withBatch)
+
void testBatchDelegate(FeatureBitset features)
+
void testBadSequence(FeatureBitset features)
+
void testTickets(FeatureBitset features)
+
void testAccountSet(FeatureBitset features)
std::pair< std::vector< std::string >, std::string > submitBatch(jtx::Env &env, TER const &result, Args &&... args)
-
void testPreclaim(FeatureBitset features)
-
void testBatchTxQueue(FeatureBitset features)
-
void testAllOrNothing(FeatureBitset features)
-
void testValidateRPCResponse(FeatureBitset features)
-
void testWithFeats(FeatureBitset features)
-
void testBatchCalculateBaseFee(FeatureBitset features)
-
void testLoan(FeatureBitset features)
-
void testBatchNetworkOps(FeatureBitset features)
-
void testObjectCreateTicket(FeatureBitset features)
-
void testInnerSubmitRPC(FeatureBitset features)
+
void testPreclaim(FeatureBitset features)
+
void testBatchTxQueue(FeatureBitset features)
+
void testAllOrNothing(FeatureBitset features)
+
void testValidateRPCResponse(FeatureBitset features)
+
void testWithFeats(FeatureBitset features)
+
void testBatchCalculateBaseFee(FeatureBitset features)
+
void testLoan(FeatureBitset features)
+
void testBatchNetworkOps(FeatureBitset features)
+
void testObjectCreateTicket(FeatureBitset features)
+
void testInnerSubmitRPC(FeatureBitset features)
void validateClosedLedger(jtx::Env &env, std::vector< TestLedgerData > const &ledgerResults)
-
void testCalculateBaseFee(FeatureBitset features)
-
void testAccountActivation(FeatureBitset features)
-
void testUntilFailure(FeatureBitset features)
+
void testCalculateBaseFee(FeatureBitset features)
+
void testAccountActivation(FeatureBitset features)
+
void testUntilFailure(FeatureBitset features)
static uint256 getCheckIndex(AccountID const &account, std::uint32_t uSequence)
void validateInnerTxn(jtx::Env &env, std::string const &batchID, TestLedgerData const &ledgerResult)
Json::Value getTxByIndex(Json::Value const &jrr, int const index)
Json::Value getLastLedger(jtx::Env &env)
-
void testObjectCreateSequence(FeatureBitset features)
-
void testOnlyOne(FeatureBitset features)
+
void testObjectCreateSequence(FeatureBitset features)
+
void testOnlyOne(FeatureBitset features)
static std::unique_ptr< Config > makeSmallQueueConfig(std::map< std::string, std::string > extraTxQ={}, std::map< std::string, std::string > extraVoting={})
-
void testAccountDelete(FeatureBitset features)
-
void testPseudoTxn(FeatureBitset features)
-
void testBadOuterFee(FeatureBitset features)
+
void testAccountDelete(FeatureBitset features)
+
void testPseudoTxn(FeatureBitset features)
+
void testBadOuterFee(FeatureBitset features)
Immutable cryptographic account descriptor.
Definition Account.h:20
A transaction testing environment.
Definition Env.h:102
Application & app()
Definition Env.h:244
diff --git a/RangeSet_8cpp_source.html b/RangeSet_8cpp_source.html index 2bcc89aa2a..34f15f312e 100644 --- a/RangeSet_8cpp_source.html +++ b/RangeSet_8cpp_source.html @@ -83,114 +83,110 @@ $(document).ready(function() { init_codefold(0); });
1#include <xrpl/basics/RangeSet.h>
2
-
3#include <doctest/doctest.h>
+
3#include <gtest/gtest.h>
4
5#include <cstdint>
6#include <optional>
7
8using namespace xrpl;
9
-
10TEST_SUITE_BEGIN("RangeSet");
-
11
-
12TEST_CASE("prevMissing")
-
13{
-
14 // Set will include:
-
15 // [ 0, 5]
-
16 // [10,15]
-
17 // [20,25]
-
18 // etc...
-
19
- -
21 for (std::uint32_t i = 0; i < 10; ++i)
-
22 set.insert(range(10 * i, 10 * i + 5));
-
23
-
24 for (std::uint32_t i = 1; i < 100; ++i)
-
25 {
- -
27 // no prev missing in domain for i <= 6
-
28 if (i > 6)
-
29 {
-
30 std::uint32_t const oneBelowRange = (10 * (i / 10)) - 1;
-
31
-
32 expected = ((i % 10) > 6) ? (i - 1) : oneBelowRange;
-
33 }
-
34 CHECK(prevMissing(set, i) == expected);
-
35 }
-
36}
-
37
-
38TEST_CASE("toString")
-
39{
- -
41 CHECK(to_string(set) == "empty");
-
42
-
43 set.insert(1);
-
44 CHECK(to_string(set) == "1");
-
45
-
46 set.insert(range(4u, 6u));
-
47 CHECK(to_string(set) == "1,4-6");
-
48
-
49 set.insert(2);
-
50 CHECK(to_string(set) == "1-2,4-6");
-
51
-
52 set.erase(range(4u, 5u));
-
53 CHECK(to_string(set) == "1-2,6");
-
54}
-
55
-
56TEST_CASE("fromString")
-
57{
- -
59
-
60 CHECK(!from_string(set, ""));
-
61 CHECK(boost::icl::length(set) == 0);
-
62
-
63 CHECK(!from_string(set, "#"));
-
64 CHECK(boost::icl::length(set) == 0);
-
65
-
66 CHECK(!from_string(set, ","));
-
67 CHECK(boost::icl::length(set) == 0);
-
68
-
69 CHECK(!from_string(set, ",-"));
-
70 CHECK(boost::icl::length(set) == 0);
-
71
-
72 CHECK(!from_string(set, "1,,2"));
-
73 CHECK(boost::icl::length(set) == 0);
-
74
-
75 CHECK(from_string(set, "1"));
-
76 CHECK(boost::icl::length(set) == 1);
-
77 CHECK(boost::icl::first(set) == 1);
-
78
-
79 CHECK(from_string(set, "1,1"));
-
80 CHECK(boost::icl::length(set) == 1);
-
81 CHECK(boost::icl::first(set) == 1);
-
82
-
83 CHECK(from_string(set, "1-1"));
-
84 CHECK(boost::icl::length(set) == 1);
-
85 CHECK(boost::icl::first(set) == 1);
-
86
-
87 CHECK(from_string(set, "1,4-6"));
-
88 CHECK(boost::icl::length(set) == 4);
-
89 CHECK(boost::icl::first(set) == 1);
-
90 CHECK(!boost::icl::contains(set, 2));
-
91 CHECK(!boost::icl::contains(set, 3));
-
92 CHECK(boost::icl::contains(set, 4));
-
93 CHECK(boost::icl::contains(set, 5));
-
94 CHECK(boost::icl::last(set) == 6);
-
95
-
96 CHECK(from_string(set, "1-2,4-6"));
-
97 CHECK(boost::icl::length(set) == 5);
-
98 CHECK(boost::icl::first(set) == 1);
-
99 CHECK(boost::icl::contains(set, 2));
-
100 CHECK(boost::icl::contains(set, 4));
-
101 CHECK(boost::icl::last(set) == 6);
-
102
-
103 CHECK(from_string(set, "1-2,6"));
-
104 CHECK(boost::icl::length(set) == 3);
-
105 CHECK(boost::icl::first(set) == 1);
-
106 CHECK(boost::icl::contains(set, 2));
-
107 CHECK(boost::icl::last(set) == 6);
-
108}
-
109
-
110TEST_SUITE_END();
+ +
11{
+
12 // Set will include:
+
13 // [ 0, 5]
+
14 // [10,15]
+
15 // [20,25]
+
16 // etc...
+
17
+ +
19 for (std::uint32_t i = 0; i < 10; ++i)
+
20 set.insert(range(10 * i, 10 * i + 5));
+
21
+
22 for (std::uint32_t i = 1; i < 100; ++i)
+
23 {
+ +
25 // no prev missing in domain for i <= 6
+
26 if (i > 6)
+
27 {
+
28 std::uint32_t const oneBelowRange = (10 * (i / 10)) - 1;
+
29
+
30 expected = ((i % 10) > 6) ? (i - 1) : oneBelowRange;
+
31 }
+
32 EXPECT_EQ(prevMissing(set, i), expected);
+
33 }
+
34}
+
35
+
36TEST(RangeSet, toString)
+
37{
+ +
39 EXPECT_EQ(to_string(set), "empty");
+
40
+
41 set.insert(1);
+
42 EXPECT_EQ(to_string(set), "1");
+
43
+
44 set.insert(range(4u, 6u));
+
45 EXPECT_EQ(to_string(set), "1,4-6");
+
46
+
47 set.insert(2);
+
48 EXPECT_EQ(to_string(set), "1-2,4-6");
+
49
+
50 set.erase(range(4u, 5u));
+
51 EXPECT_EQ(to_string(set), "1-2,6");
+
52}
+
53
+
54TEST(RangeSet, fromString)
+
55{
+ +
57
+
58 EXPECT_FALSE(from_string(set, ""));
+
59 EXPECT_EQ(boost::icl::length(set), 0);
+
60
+
61 EXPECT_FALSE(from_string(set, "#"));
+
62 EXPECT_EQ(boost::icl::length(set), 0);
+
63
+
64 EXPECT_FALSE(from_string(set, ","));
+
65 EXPECT_EQ(boost::icl::length(set), 0);
+
66
+
67 EXPECT_FALSE(from_string(set, ",-"));
+
68 EXPECT_EQ(boost::icl::length(set), 0);
+
69
+
70 EXPECT_FALSE(from_string(set, "1,,2"));
+
71 EXPECT_EQ(boost::icl::length(set), 0);
+
72
+
73 EXPECT_TRUE(from_string(set, "1"));
+
74 EXPECT_EQ(boost::icl::length(set), 1);
+
75 EXPECT_EQ(boost::icl::first(set), 1);
+
76
+
77 EXPECT_TRUE(from_string(set, "1,1"));
+
78 EXPECT_EQ(boost::icl::length(set), 1);
+
79 EXPECT_EQ(boost::icl::first(set), 1);
+
80
+
81 EXPECT_TRUE(from_string(set, "1-1"));
+
82 EXPECT_EQ(boost::icl::length(set), 1);
+
83 EXPECT_EQ(boost::icl::first(set), 1);
+
84
+
85 EXPECT_TRUE(from_string(set, "1,4-6"));
+
86 EXPECT_EQ(boost::icl::length(set), 4);
+
87 EXPECT_EQ(boost::icl::first(set), 1);
+
88 EXPECT_FALSE(boost::icl::contains(set, 2));
+
89 EXPECT_FALSE(boost::icl::contains(set, 3));
+
90 EXPECT_TRUE(boost::icl::contains(set, 4));
+
91 EXPECT_TRUE(boost::icl::contains(set, 5));
+
92 EXPECT_EQ(boost::icl::last(set), 6);
+
93
+
94 EXPECT_TRUE(from_string(set, "1-2,4-6"));
+
95 EXPECT_EQ(boost::icl::length(set), 5);
+
96 EXPECT_EQ(boost::icl::first(set), 1);
+
97 EXPECT_TRUE(boost::icl::contains(set, 2));
+
98 EXPECT_TRUE(boost::icl::contains(set, 4));
+
99 EXPECT_EQ(boost::icl::last(set), 6);
+
100
+
101 EXPECT_TRUE(from_string(set, "1-2,6"));
+
102 EXPECT_EQ(boost::icl::length(set), 3);
+
103 EXPECT_EQ(boost::icl::first(set), 1);
+
104 EXPECT_TRUE(boost::icl::contains(set, 2));
+
105 EXPECT_EQ(boost::icl::last(set), 6);
+
106}
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
@@ -200,7 +196,6 @@ $(document).ready(function() { init_codefold(0); });
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
Definition RangeSet.h:35
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611
boost::icl::interval_set< T, std::less, ClosedInterval< T > > RangeSet
A set of closed intervals over the domain T.
Definition RangeSet.h:51
-
diff --git a/Slice_8cpp_source.html b/Slice_8cpp_source.html index 5f32038b0b..09111d206c 100644 --- a/Slice_8cpp_source.html +++ b/Slice_8cpp_source.html @@ -83,7 +83,7 @@ $(document).ready(function() { init_codefold(0); });
1#include <xrpl/basics/Slice.h>
2
-
3#include <doctest/doctest.h>
+
3#include <gtest/gtest.h>
4
5#include <array>
6#include <cstdint>
@@ -95,85 +95,80 @@ $(document).ready(function() { init_codefold(0); });
12 0x18, 0xb4, 0x70, 0xcb, 0xf5, 0xac, 0x2d, 0x89, 0x4d, 0x19, 0x9c,
13 0xf0, 0x2c, 0x15, 0xd1, 0xf9, 0x9b, 0x66, 0xd2, 0x30, 0xd3};
14
-
15TEST_SUITE_BEGIN("Slice");
-
16
-
17TEST_CASE("equality & inequality")
-
18{
-
19 Slice const s0{};
-
20
-
21 CHECK(s0.size() == 0);
-
22 CHECK(s0.data() == nullptr);
-
23 CHECK(s0 == s0);
-
24
-
25 // Test slices of equal and unequal size pointing to same data:
-
26 for (std::size_t i = 0; i != sizeof(data); ++i)
-
27 {
-
28 Slice const s1{data, i};
-
29
-
30 CHECK(s1.size() == i);
-
31 CHECK(s1.data() != nullptr);
-
32
-
33 if (i == 0)
-
34 CHECK(s1 == s0);
-
35 else
-
36 CHECK(s1 != s0);
-
37
-
38 for (std::size_t j = 0; j != sizeof(data); ++j)
-
39 {
-
40 Slice const s2{data, j};
-
41
-
42 if (i == j)
-
43 CHECK(s1 == s2);
-
44 else
-
45 CHECK(s1 != s2);
-
46 }
-
47 }
-
48
-
49 // Test slices of equal size but pointing to different data:
-
50 std::array<std::uint8_t, sizeof(data)> a;
-
51 std::array<std::uint8_t, sizeof(data)> b;
-
52
-
53 for (std::size_t i = 0; i != sizeof(data); ++i)
-
54 a[i] = b[i] = data[i];
-
55
-
56 CHECK(makeSlice(a) == makeSlice(b));
-
57 b[7]++;
-
58 CHECK(makeSlice(a) != makeSlice(b));
-
59 a[7]++;
-
60 CHECK(makeSlice(a) == makeSlice(b));
-
61}
-
62
-
63TEST_CASE("indexing")
-
64{
-
65 Slice const s{data, sizeof(data)};
-
66
-
67 for (std::size_t i = 0; i != sizeof(data); ++i)
-
68 CHECK(s[i] == data[i]);
-
69}
-
70
-
71TEST_CASE("advancing")
-
72{
-
73 for (std::size_t i = 0; i < sizeof(data); ++i)
-
74 {
-
75 for (std::size_t j = 0; i + j < sizeof(data); ++j)
-
76 {
-
77 Slice s(data + i, sizeof(data) - i);
-
78 s += j;
-
79
-
80 CHECK(s.data() == data + i + j);
-
81 CHECK(s.size() == sizeof(data) - i - j);
-
82 }
-
83 }
-
84}
-
85
-
86TEST_SUITE_END();
+
15TEST(Slice, equality_and_inequality)
+
16{
+
17 Slice const s0{};
+
18
+
19 EXPECT_EQ(s0.size(), 0);
+
20 EXPECT_EQ(s0.data(), nullptr);
+
21 EXPECT_EQ(s0, s0);
+
22
+
23 // Test slices of equal and unequal size pointing to same data:
+
24 for (std::size_t i = 0; i != sizeof(data); ++i)
+
25 {
+
26 Slice const s1{data, i};
+
27
+
28 EXPECT_EQ(s1.size(), i);
+
29 EXPECT_NE(s1.data(), nullptr);
+
30
+
31 if (i == 0)
+
32 EXPECT_EQ(s1, s0);
+
33 else
+
34 EXPECT_NE(s1, s0);
+
35
+
36 for (std::size_t j = 0; j != sizeof(data); ++j)
+
37 {
+
38 Slice const s2{data, j};
+
39
+
40 if (i == j)
+
41 EXPECT_EQ(s1, s2);
+
42 else
+
43 EXPECT_NE(s1, s2);
+
44 }
+
45 }
+
46
+
47 // Test slices of equal size but pointing to different data:
+
48 std::array<std::uint8_t, sizeof(data)> a;
+
49 std::array<std::uint8_t, sizeof(data)> b;
+
50
+
51 for (std::size_t i = 0; i != sizeof(data); ++i)
+
52 a[i] = b[i] = data[i];
+
53
+
54 EXPECT_EQ(makeSlice(a), makeSlice(b));
+
55 b[7]++;
+
56 EXPECT_NE(makeSlice(a), makeSlice(b));
+
57 a[7]++;
+
58 EXPECT_EQ(makeSlice(a), makeSlice(b));
+
59}
+
60
+
61TEST(Slice, indexing)
+
62{
+
63 Slice const s{data, sizeof(data)};
+
64
+
65 for (std::size_t i = 0; i != sizeof(data); ++i)
+
66 EXPECT_EQ(s[i], data[i]);
+
67}
+
68
+
69TEST(Slice, advancing)
+
70{
+
71 for (std::size_t i = 0; i < sizeof(data); ++i)
+
72 {
+
73 for (std::size_t j = 0; i + j < sizeof(data); ++j)
+
74 {
+
75 Slice s(data + i, sizeof(data) - i);
+
76 s += j;
+
77
+
78 EXPECT_EQ(s.data(), data + i + j);
+
79 EXPECT_EQ(s.size(), sizeof(data) - i - j);
+
80 }
+
81 }
+
82}
An immutable linear range of bytes.
Definition Slice.h:27
auto const data
General field definitions, or fields used in multiple transaction namespaces.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
-
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition Slice.h:225
diff --git a/Value_8cpp_source.html b/Value_8cpp_source.html index 5dfb4870aa..f40a4fff42 100644 --- a/Value_8cpp_source.html +++ b/Value_8cpp_source.html @@ -87,7 +87,7 @@ $(document).ready(function() { init_codefold(0); });
4#include <xrpl/json/json_value.h>
5#include <xrpl/json/json_writer.h>
6
-
7#include <doctest/doctest.h>
+
7#include <gtest/gtest.h>
8
9#include <algorithm>
10#include <cmath>
@@ -97,1390 +97,1385 @@ $(document).ready(function() { init_codefold(0); });
14
15namespace xrpl {
16
-
17TEST_SUITE_BEGIN("json_value");
-
18
-
-
19TEST_CASE("limits")
-
20{
-
21 using namespace Json;
-
22 static_assert(Value::minInt == Int(~(UInt(-1) / 2)));
-
23 static_assert(Value::maxInt == Int(UInt(-1) / 2));
-
24 static_assert(Value::maxUInt == UInt(-1));
-
25}
+
+
17TEST(json_value, limits)
+
18{
+
19 using namespace Json;
+
20 static_assert(Value::minInt == Int(~(UInt(-1) / 2)));
+
21 static_assert(Value::maxInt == Int(UInt(-1) / 2));
+
22 static_assert(Value::maxUInt == UInt(-1));
+
23}
-
26
-
-
27TEST_CASE("construct and compare Json::StaticString")
-
28{
-
29 static constexpr char sample[]{"Contents of a Json::StaticString"};
-
30
-
31 static constexpr Json::StaticString test1(sample);
-
32 char const* addrTest1{test1};
-
33
-
34 CHECK(addrTest1 == &sample[0]);
-
35 CHECK(test1.c_str() == &sample[0]);
-
36
-
37 static constexpr Json::StaticString test2{
-
38 "Contents of a Json::StaticString"};
-
39 static constexpr Json::StaticString test3{"Another StaticString"};
-
40
-
41 CHECK(test1 == test2);
-
42 CHECK(test1 != test3);
-
43
-
44 std::string str{sample};
-
45 CHECK(str == test2);
-
46 CHECK(str != test3);
-
47 CHECK(test2 == str);
-
48 CHECK(test3 != str);
-
49}
+
24
+
+
25TEST(json_value, construct_and_compare_Json_StaticString)
+
26{
+
27 static constexpr char sample[]{"Contents of a Json::StaticString"};
+
28
+
29 static constexpr Json::StaticString test1(sample);
+
30 char const* addrTest1{test1};
+
31
+
32 EXPECT_EQ(addrTest1, &sample[0]);
+
33 EXPECT_EQ(test1.c_str(), &sample[0]);
+
34
+
35 static constexpr Json::StaticString test2{
+
36 "Contents of a Json::StaticString"};
+
37 static constexpr Json::StaticString test3{"Another StaticString"};
+
38
+
39 EXPECT_EQ(test1, test2);
+
40 EXPECT_NE(test1, test3);
+
41
+
42 std::string str{sample};
+
43 EXPECT_EQ(str, test2);
+
44 EXPECT_NE(str, test3);
+
45 EXPECT_EQ(test2, str);
+
46 EXPECT_NE(test3, str);
+
47}
-
50
-
-
51TEST_CASE("different types")
-
52{
-
53 // Exercise ValueType constructor
-
54 static constexpr Json::StaticString staticStr{"staticStr"};
-
55
-
56 auto testCopy = [](Json::ValueType typ) {
-
57 Json::Value val{typ};
-
58 Json::Value cpy{val};
-
59 CHECK(val.type() == typ);
-
60 CHECK(cpy.type() == typ);
-
61 return val;
-
62 };
-
63 {
-
64 Json::Value const nullV{testCopy(Json::nullValue)};
-
65 CHECK(nullV.isNull());
-
66 CHECK(!nullV.isBool());
-
67 CHECK(!nullV.isInt());
-
68 CHECK(!nullV.isUInt());
-
69 CHECK(!nullV.isIntegral());
-
70 CHECK(!nullV.isDouble());
-
71 CHECK(!nullV.isNumeric());
-
72 CHECK(!nullV.isString());
-
73 CHECK(!nullV.isArray());
-
74 CHECK(nullV.isArrayOrNull());
-
75 CHECK(!nullV.isObject());
-
76 CHECK(nullV.isObjectOrNull());
-
77 }
-
78 {
-
79 Json::Value const intV{testCopy(Json::intValue)};
-
80 CHECK(!intV.isNull());
-
81 CHECK(!intV.isBool());
-
82 CHECK(intV.isInt());
-
83 CHECK(!intV.isUInt());
-
84 CHECK(intV.isIntegral());
-
85 CHECK(!intV.isDouble());
-
86 CHECK(intV.isNumeric());
-
87 CHECK(!intV.isString());
-
88 CHECK(!intV.isArray());
-
89 CHECK(!intV.isArrayOrNull());
-
90 CHECK(!intV.isObject());
-
91 CHECK(!intV.isObjectOrNull());
-
92 }
-
93 {
-
94 Json::Value const uintV{testCopy(Json::uintValue)};
-
95 CHECK(!uintV.isNull());
-
96 CHECK(!uintV.isBool());
-
97 CHECK(!uintV.isInt());
-
98 CHECK(uintV.isUInt());
-
99 CHECK(uintV.isIntegral());
-
100 CHECK(!uintV.isDouble());
-
101 CHECK(uintV.isNumeric());
-
102 CHECK(!uintV.isString());
-
103 CHECK(!uintV.isArray());
-
104 CHECK(!uintV.isArrayOrNull());
-
105 CHECK(!uintV.isObject());
-
106 CHECK(!uintV.isObjectOrNull());
-
107 }
-
108 {
-
109 Json::Value const realV{testCopy(Json::realValue)};
-
110 CHECK(!realV.isNull());
-
111 CHECK(!realV.isBool());
-
112 CHECK(!realV.isInt());
-
113 CHECK(!realV.isUInt());
-
114 CHECK(!realV.isIntegral());
-
115 CHECK(realV.isDouble());
-
116 CHECK(realV.isNumeric());
-
117 CHECK(!realV.isString());
-
118 CHECK(!realV.isArray());
-
119 CHECK(!realV.isArrayOrNull());
-
120 CHECK(!realV.isObject());
-
121 CHECK(!realV.isObjectOrNull());
-
122 }
-
123 {
-
124 Json::Value const stringV{testCopy(Json::stringValue)};
-
125 CHECK(!stringV.isNull());
-
126 CHECK(!stringV.isBool());
-
127 CHECK(!stringV.isInt());
-
128 CHECK(!stringV.isUInt());
-
129 CHECK(!stringV.isIntegral());
-
130 CHECK(!stringV.isDouble());
-
131 CHECK(!stringV.isNumeric());
-
132 CHECK(stringV.isString());
-
133 CHECK(!stringV.isArray());
-
134 CHECK(!stringV.isArrayOrNull());
-
135 CHECK(!stringV.isObject());
-
136 CHECK(!stringV.isObjectOrNull());
-
137 }
-
138 {
-
139 Json::Value const staticStrV{staticStr};
-
140 {
-
141 Json::Value cpy{staticStrV};
-
142 CHECK(staticStrV.type() == Json::stringValue);
-
143 CHECK(cpy.type() == Json::stringValue);
-
144 }
-
145 CHECK(!staticStrV.isNull());
-
146 CHECK(!staticStrV.isBool());
-
147 CHECK(!staticStrV.isInt());
-
148 CHECK(!staticStrV.isUInt());
-
149 CHECK(!staticStrV.isIntegral());
-
150 CHECK(!staticStrV.isDouble());
-
151 CHECK(!staticStrV.isNumeric());
-
152 CHECK(staticStrV.isString());
-
153 CHECK(!staticStrV.isArray());
-
154 CHECK(!staticStrV.isArrayOrNull());
-
155 CHECK(!staticStrV.isObject());
-
156 CHECK(!staticStrV.isObjectOrNull());
-
157 }
-
158 {
-
159 Json::Value const boolV{testCopy(Json::booleanValue)};
-
160 CHECK(!boolV.isNull());
-
161 CHECK(boolV.isBool());
-
162 CHECK(!boolV.isInt());
-
163 CHECK(!boolV.isUInt());
-
164 CHECK(boolV.isIntegral());
-
165 CHECK(!boolV.isDouble());
-
166 CHECK(boolV.isNumeric());
-
167 CHECK(!boolV.isString());
-
168 CHECK(!boolV.isArray());
-
169 CHECK(!boolV.isArrayOrNull());
-
170 CHECK(!boolV.isObject());
-
171 CHECK(!boolV.isObjectOrNull());
-
172 }
-
173 {
-
174 Json::Value const arrayV{testCopy(Json::arrayValue)};
-
175 CHECK(!arrayV.isNull());
-
176 CHECK(!arrayV.isBool());
-
177 CHECK(!arrayV.isInt());
-
178 CHECK(!arrayV.isUInt());
-
179 CHECK(!arrayV.isIntegral());
-
180 CHECK(!arrayV.isDouble());
-
181 CHECK(!arrayV.isNumeric());
-
182 CHECK(!arrayV.isString());
-
183 CHECK(arrayV.isArray());
-
184 CHECK(arrayV.isArrayOrNull());
-
185 CHECK(!arrayV.isObject());
-
186 CHECK(!arrayV.isObjectOrNull());
-
187 }
-
188 {
-
189 Json::Value const objectV{testCopy(Json::objectValue)};
-
190 CHECK(!objectV.isNull());
-
191 CHECK(!objectV.isBool());
-
192 CHECK(!objectV.isInt());
-
193 CHECK(!objectV.isUInt());
-
194 CHECK(!objectV.isIntegral());
-
195 CHECK(!objectV.isDouble());
-
196 CHECK(!objectV.isNumeric());
-
197 CHECK(!objectV.isString());
-
198 CHECK(!objectV.isArray());
-
199 CHECK(!objectV.isArrayOrNull());
-
200 CHECK(objectV.isObject());
-
201 CHECK(objectV.isObjectOrNull());
-
202 }
-
203}
+
48
+
+
49TEST(json_value, different_types)
+
50{
+
51 // Exercise ValueType constructor
+
52 static constexpr Json::StaticString staticStr{"staticStr"};
+
53
+
54 auto testCopy = [](Json::ValueType typ) {
+
55 Json::Value val{typ};
+
56 Json::Value cpy{val};
+
57 EXPECT_EQ(val.type(), typ);
+
58 EXPECT_EQ(cpy.type(), typ);
+
59 return val;
+
60 };
+
61 {
+
62 Json::Value const nullV{testCopy(Json::nullValue)};
+
63 EXPECT_TRUE(nullV.isNull());
+
64 EXPECT_FALSE(nullV.isBool());
+
65 EXPECT_FALSE(nullV.isInt());
+
66 EXPECT_FALSE(nullV.isUInt());
+
67 EXPECT_FALSE(nullV.isIntegral());
+
68 EXPECT_FALSE(nullV.isDouble());
+
69 EXPECT_FALSE(nullV.isNumeric());
+
70 EXPECT_FALSE(nullV.isString());
+
71 EXPECT_FALSE(nullV.isArray());
+
72 EXPECT_TRUE(nullV.isArrayOrNull());
+
73 EXPECT_FALSE(nullV.isObject());
+
74 EXPECT_TRUE(nullV.isObjectOrNull());
+
75 }
+
76 {
+
77 Json::Value const intV{testCopy(Json::intValue)};
+
78 EXPECT_FALSE(intV.isNull());
+
79 EXPECT_FALSE(intV.isBool());
+
80 EXPECT_TRUE(intV.isInt());
+
81 EXPECT_FALSE(intV.isUInt());
+
82 EXPECT_TRUE(intV.isIntegral());
+
83 EXPECT_FALSE(intV.isDouble());
+
84 EXPECT_TRUE(intV.isNumeric());
+
85 EXPECT_FALSE(intV.isString());
+
86 EXPECT_FALSE(intV.isArray());
+
87 EXPECT_FALSE(intV.isArrayOrNull());
+
88 EXPECT_FALSE(intV.isObject());
+
89 EXPECT_FALSE(intV.isObjectOrNull());
+
90 }
+
91 {
+
92 Json::Value const uintV{testCopy(Json::uintValue)};
+
93 EXPECT_FALSE(uintV.isNull());
+
94 EXPECT_FALSE(uintV.isBool());
+
95 EXPECT_FALSE(uintV.isInt());
+
96 EXPECT_TRUE(uintV.isUInt());
+
97 EXPECT_TRUE(uintV.isIntegral());
+
98 EXPECT_FALSE(uintV.isDouble());
+
99 EXPECT_TRUE(uintV.isNumeric());
+
100 EXPECT_FALSE(uintV.isString());
+
101 EXPECT_FALSE(uintV.isArray());
+
102 EXPECT_FALSE(uintV.isArrayOrNull());
+
103 EXPECT_FALSE(uintV.isObject());
+
104 EXPECT_FALSE(uintV.isObjectOrNull());
+
105 }
+
106 {
+
107 Json::Value const realV{testCopy(Json::realValue)};
+
108 EXPECT_FALSE(realV.isNull());
+
109 EXPECT_FALSE(realV.isBool());
+
110 EXPECT_FALSE(realV.isInt());
+
111 EXPECT_FALSE(realV.isUInt());
+
112 EXPECT_FALSE(realV.isIntegral());
+
113 EXPECT_TRUE(realV.isDouble());
+
114 EXPECT_TRUE(realV.isNumeric());
+
115 EXPECT_FALSE(realV.isString());
+
116 EXPECT_FALSE(realV.isArray());
+
117 EXPECT_FALSE(realV.isArrayOrNull());
+
118 EXPECT_FALSE(realV.isObject());
+
119 EXPECT_FALSE(realV.isObjectOrNull());
+
120 }
+
121 {
+
122 Json::Value const stringV{testCopy(Json::stringValue)};
+
123 EXPECT_FALSE(stringV.isNull());
+
124 EXPECT_FALSE(stringV.isBool());
+
125 EXPECT_FALSE(stringV.isInt());
+
126 EXPECT_FALSE(stringV.isUInt());
+
127 EXPECT_FALSE(stringV.isIntegral());
+
128 EXPECT_FALSE(stringV.isDouble());
+
129 EXPECT_FALSE(stringV.isNumeric());
+
130 EXPECT_TRUE(stringV.isString());
+
131 EXPECT_FALSE(stringV.isArray());
+
132 EXPECT_FALSE(stringV.isArrayOrNull());
+
133 EXPECT_FALSE(stringV.isObject());
+
134 EXPECT_FALSE(stringV.isObjectOrNull());
+
135 }
+
136 {
+
137 Json::Value const staticStrV{staticStr};
+
138 {
+
139 Json::Value cpy{staticStrV};
+
140 EXPECT_EQ(staticStrV.type(), Json::stringValue);
+
141 EXPECT_EQ(cpy.type(), Json::stringValue);
+
142 }
+
143 EXPECT_FALSE(staticStrV.isNull());
+
144 EXPECT_FALSE(staticStrV.isBool());
+
145 EXPECT_FALSE(staticStrV.isInt());
+
146 EXPECT_FALSE(staticStrV.isUInt());
+
147 EXPECT_FALSE(staticStrV.isIntegral());
+
148 EXPECT_FALSE(staticStrV.isDouble());
+
149 EXPECT_FALSE(staticStrV.isNumeric());
+
150 EXPECT_TRUE(staticStrV.isString());
+
151 EXPECT_FALSE(staticStrV.isArray());
+
152 EXPECT_FALSE(staticStrV.isArrayOrNull());
+
153 EXPECT_FALSE(staticStrV.isObject());
+
154 EXPECT_FALSE(staticStrV.isObjectOrNull());
+
155 }
+
156 {
+
157 Json::Value const boolV{testCopy(Json::booleanValue)};
+
158 EXPECT_FALSE(boolV.isNull());
+
159 EXPECT_TRUE(boolV.isBool());
+
160 EXPECT_FALSE(boolV.isInt());
+
161 EXPECT_FALSE(boolV.isUInt());
+
162 EXPECT_TRUE(boolV.isIntegral());
+
163 EXPECT_FALSE(boolV.isDouble());
+
164 EXPECT_TRUE(boolV.isNumeric());
+
165 EXPECT_FALSE(boolV.isString());
+
166 EXPECT_FALSE(boolV.isArray());
+
167 EXPECT_FALSE(boolV.isArrayOrNull());
+
168 EXPECT_FALSE(boolV.isObject());
+
169 EXPECT_FALSE(boolV.isObjectOrNull());
+
170 }
+
171 {
+
172 Json::Value const arrayV{testCopy(Json::arrayValue)};
+
173 EXPECT_FALSE(arrayV.isNull());
+
174 EXPECT_FALSE(arrayV.isBool());
+
175 EXPECT_FALSE(arrayV.isInt());
+
176 EXPECT_FALSE(arrayV.isUInt());
+
177 EXPECT_FALSE(arrayV.isIntegral());
+
178 EXPECT_FALSE(arrayV.isDouble());
+
179 EXPECT_FALSE(arrayV.isNumeric());
+
180 EXPECT_FALSE(arrayV.isString());
+
181 EXPECT_TRUE(arrayV.isArray());
+
182 EXPECT_TRUE(arrayV.isArrayOrNull());
+
183 EXPECT_FALSE(arrayV.isObject());
+
184 EXPECT_FALSE(arrayV.isObjectOrNull());
+
185 }
+
186 {
+
187 Json::Value const objectV{testCopy(Json::objectValue)};
+
188 EXPECT_FALSE(objectV.isNull());
+
189 EXPECT_FALSE(objectV.isBool());
+
190 EXPECT_FALSE(objectV.isInt());
+
191 EXPECT_FALSE(objectV.isUInt());
+
192 EXPECT_FALSE(objectV.isIntegral());
+
193 EXPECT_FALSE(objectV.isDouble());
+
194 EXPECT_FALSE(objectV.isNumeric());
+
195 EXPECT_FALSE(objectV.isString());
+
196 EXPECT_FALSE(objectV.isArray());
+
197 EXPECT_FALSE(objectV.isArrayOrNull());
+
198 EXPECT_TRUE(objectV.isObject());
+
199 EXPECT_TRUE(objectV.isObjectOrNull());
+
200 }
+
201}
-
204
-
-
205TEST_CASE("compare strings")
-
206{
-
207 auto doCompare = [&](Json::Value const& lhs,
-
208 Json::Value const& rhs,
-
209 bool lhsEqRhs,
-
210 bool lhsLtRhs,
-
211 int line) {
-
212 CAPTURE(line);
-
213 CHECK((lhs == rhs) == lhsEqRhs);
-
214 CHECK((lhs != rhs) != lhsEqRhs);
-
215 CHECK((lhs < rhs) == (!(lhsEqRhs || !lhsLtRhs)));
-
216 CHECK((lhs <= rhs) == (lhsEqRhs || lhsLtRhs));
-
217 CHECK((lhs >= rhs) == (lhsEqRhs || !lhsLtRhs));
-
218 CHECK((lhs > rhs) == (!(lhsEqRhs || lhsLtRhs)));
-
219 };
-
220
-
221 Json::Value const null0;
-
222 Json::Value const intNeg1{-1};
-
223 Json::Value const int0{Json::intValue};
-
224 Json::Value const intPos1{1};
-
225 Json::Value const uint0{Json::uintValue};
-
226 Json::Value const uint1{1u};
-
227 Json::Value const realNeg1{-1.0};
-
228 Json::Value const real0{Json::realValue};
-
229 Json::Value const realPos1{1.0};
-
230 Json::Value const str0{Json::stringValue};
-
231 Json::Value const str1{"1"};
-
232 Json::Value const boolF{false};
-
233 Json::Value const boolT{true};
-
234 Json::Value const array0{Json::arrayValue};
-
235 Json::Value const array1{[]() {
-
236 Json::Value array1;
-
237 array1[0u] = 1;
-
238 return array1;
-
239 }()};
-
240 Json::Value const obj0{Json::objectValue};
-
241 Json::Value const obj1{[]() {
-
242 Json::Value obj1;
-
243 obj1["one"] = 1;
-
244 return obj1;
-
245 }()};
-
246
-
247#pragma push_macro("DO_COMPARE")
-
248 // DO_COMPARE(lhs, rhs, lhsEqualsToRhs lhsLessThanRhs)
-
249#define DO_COMPARE(lhs, rhs, eq, lt) doCompare(lhs, rhs, eq, lt, __LINE__)
-
250 DO_COMPARE(null0, Json::Value{}, true, false);
-
251 DO_COMPARE(null0, intNeg1, false, true);
-
252 DO_COMPARE(null0, int0, false, true);
-
253 DO_COMPARE(null0, intPos1, false, true);
-
254 DO_COMPARE(null0, uint0, false, true);
-
255 DO_COMPARE(null0, uint1, false, true);
-
256 DO_COMPARE(null0, realNeg1, false, true);
-
257 DO_COMPARE(null0, real0, false, true);
-
258 DO_COMPARE(null0, realPos1, false, true);
-
259 DO_COMPARE(null0, str0, false, true);
-
260 DO_COMPARE(null0, str1, false, true);
-
261 DO_COMPARE(null0, boolF, false, true);
-
262 DO_COMPARE(null0, boolT, false, true);
-
263 DO_COMPARE(null0, array0, false, true);
-
264 DO_COMPARE(null0, array1, false, true);
-
265 DO_COMPARE(null0, obj0, false, true);
-
266 DO_COMPARE(null0, obj1, false, true);
-
267
-
268 DO_COMPARE(intNeg1, null0, false, false);
-
269 DO_COMPARE(intNeg1, intNeg1, true, false);
-
270 DO_COMPARE(intNeg1, int0, false, true);
-
271 DO_COMPARE(intNeg1, intPos1, false, true);
-
272 DO_COMPARE(intNeg1, uint0, false, true);
-
273 DO_COMPARE(intNeg1, uint1, false, true);
-
274 DO_COMPARE(intNeg1, realNeg1, false, true);
-
275 DO_COMPARE(intNeg1, real0, false, true);
-
276 DO_COMPARE(intNeg1, realPos1, false, true);
-
277 DO_COMPARE(intNeg1, str0, false, true);
-
278 DO_COMPARE(intNeg1, str1, false, true);
-
279 DO_COMPARE(intNeg1, boolF, false, true);
-
280 DO_COMPARE(intNeg1, boolT, false, true);
-
281 DO_COMPARE(intNeg1, array0, false, true);
-
282 DO_COMPARE(intNeg1, array1, false, true);
-
283 DO_COMPARE(intNeg1, obj0, false, true);
-
284 DO_COMPARE(intNeg1, obj1, false, true);
-
285
-
286 DO_COMPARE(int0, null0, false, false);
-
287 DO_COMPARE(int0, intNeg1, false, false);
-
288 DO_COMPARE(int0, int0, true, false);
-
289 DO_COMPARE(int0, intPos1, false, true);
-
290 DO_COMPARE(int0, uint0, true, false);
-
291 DO_COMPARE(int0, uint1, false, true);
-
292 DO_COMPARE(int0, realNeg1, false, true);
-
293 DO_COMPARE(int0, real0, false, true);
-
294 DO_COMPARE(int0, realPos1, false, true);
-
295 DO_COMPARE(int0, str0, false, true);
-
296 DO_COMPARE(int0, str1, false, true);
-
297 DO_COMPARE(int0, boolF, false, true);
-
298 DO_COMPARE(int0, boolT, false, true);
-
299 DO_COMPARE(int0, array0, false, true);
-
300 DO_COMPARE(int0, array1, false, true);
-
301 DO_COMPARE(int0, obj0, false, true);
-
302 DO_COMPARE(int0, obj1, false, true);
-
303
-
304 DO_COMPARE(intPos1, null0, false, false);
-
305 DO_COMPARE(intPos1, intNeg1, false, false);
-
306 DO_COMPARE(intPos1, int0, false, false);
-
307 DO_COMPARE(intPos1, intPos1, true, false);
-
308 DO_COMPARE(intPos1, uint0, false, false);
-
309 DO_COMPARE(intPos1, uint1, true, false);
-
310 DO_COMPARE(intPos1, realNeg1, false, true);
-
311 DO_COMPARE(intPos1, real0, false, true);
-
312 DO_COMPARE(intPos1, realPos1, false, true);
-
313 DO_COMPARE(intPos1, str0, false, true);
-
314 DO_COMPARE(intPos1, str1, false, true);
-
315 DO_COMPARE(intPos1, boolF, false, true);
-
316 DO_COMPARE(intPos1, boolT, false, true);
-
317 DO_COMPARE(intPos1, array0, false, true);
-
318 DO_COMPARE(intPos1, array1, false, true);
-
319 DO_COMPARE(intPos1, obj0, false, true);
-
320 DO_COMPARE(intPos1, obj1, false, true);
-
321
-
322 DO_COMPARE(uint0, null0, false, false);
-
323 DO_COMPARE(uint0, intNeg1, false, false);
-
324 DO_COMPARE(uint0, int0, true, false);
-
325 DO_COMPARE(uint0, intPos1, false, true);
-
326 DO_COMPARE(uint0, uint0, true, false);
-
327 DO_COMPARE(uint0, uint1, false, true);
-
328 DO_COMPARE(uint0, realNeg1, false, true);
-
329 DO_COMPARE(uint0, real0, false, true);
-
330 DO_COMPARE(uint0, realPos1, false, true);
-
331 DO_COMPARE(uint0, str0, false, true);
-
332 DO_COMPARE(uint0, str1, false, true);
-
333 DO_COMPARE(uint0, boolF, false, true);
-
334 DO_COMPARE(uint0, boolT, false, true);
-
335 DO_COMPARE(uint0, array0, false, true);
-
336 DO_COMPARE(uint0, array1, false, true);
-
337 DO_COMPARE(uint0, obj0, false, true);
-
338 DO_COMPARE(uint0, obj1, false, true);
-
339
-
340 DO_COMPARE(uint1, null0, false, false);
-
341 DO_COMPARE(uint1, intNeg1, false, false);
-
342 DO_COMPARE(uint1, int0, false, false);
-
343 DO_COMPARE(uint1, intPos1, true, false);
-
344 DO_COMPARE(uint1, uint0, false, false);
-
345 DO_COMPARE(uint1, uint1, true, false);
-
346 DO_COMPARE(uint1, realNeg1, false, true);
-
347 DO_COMPARE(uint1, real0, false, true);
-
348 DO_COMPARE(uint1, realPos1, false, true);
-
349 DO_COMPARE(uint1, str0, false, true);
-
350 DO_COMPARE(uint1, str1, false, true);
-
351 DO_COMPARE(uint1, boolF, false, true);
-
352 DO_COMPARE(uint1, boolT, false, true);
-
353 DO_COMPARE(uint1, array0, false, true);
-
354 DO_COMPARE(uint1, array1, false, true);
-
355 DO_COMPARE(uint1, obj0, false, true);
-
356 DO_COMPARE(uint1, obj1, false, true);
-
357
-
358 DO_COMPARE(realNeg1, null0, false, false);
-
359 DO_COMPARE(realNeg1, intNeg1, false, false);
-
360 DO_COMPARE(realNeg1, int0, false, false);
-
361 DO_COMPARE(realNeg1, intPos1, false, false);
-
362 DO_COMPARE(realNeg1, uint0, false, false);
-
363 DO_COMPARE(realNeg1, uint1, false, false);
-
364 DO_COMPARE(realNeg1, realNeg1, true, false);
-
365 DO_COMPARE(realNeg1, real0, false, true);
-
366 DO_COMPARE(realNeg1, realPos1, false, true);
-
367 DO_COMPARE(realNeg1, str0, false, true);
-
368 DO_COMPARE(realNeg1, str1, false, true);
-
369 DO_COMPARE(realNeg1, boolF, false, true);
-
370 DO_COMPARE(realNeg1, boolT, false, true);
-
371 DO_COMPARE(realNeg1, array0, false, true);
-
372 DO_COMPARE(realNeg1, array1, false, true);
-
373 DO_COMPARE(realNeg1, obj0, false, true);
-
374 DO_COMPARE(realNeg1, obj1, false, true);
-
375
-
376 DO_COMPARE(real0, null0, false, false);
-
377 DO_COMPARE(real0, intNeg1, false, false);
-
378 DO_COMPARE(real0, int0, false, false);
-
379 DO_COMPARE(real0, intPos1, false, false);
-
380 DO_COMPARE(real0, uint0, false, false);
-
381 DO_COMPARE(real0, uint1, false, false);
-
382 DO_COMPARE(real0, realNeg1, false, false);
-
383 DO_COMPARE(real0, real0, true, false);
-
384 DO_COMPARE(real0, realPos1, false, true);
-
385 DO_COMPARE(real0, str0, false, true);
-
386 DO_COMPARE(real0, str1, false, true);
-
387 DO_COMPARE(real0, boolF, false, true);
-
388 DO_COMPARE(real0, boolT, false, true);
-
389 DO_COMPARE(real0, array0, false, true);
-
390 DO_COMPARE(real0, array1, false, true);
-
391 DO_COMPARE(real0, obj0, false, true);
-
392 DO_COMPARE(real0, obj1, false, true);
-
393
-
394 DO_COMPARE(realPos1, null0, false, false);
-
395 DO_COMPARE(realPos1, intNeg1, false, false);
-
396 DO_COMPARE(realPos1, int0, false, false);
-
397 DO_COMPARE(realPos1, intPos1, false, false);
-
398 DO_COMPARE(realPos1, uint0, false, false);
-
399 DO_COMPARE(realPos1, uint1, false, false);
-
400 DO_COMPARE(realPos1, realNeg1, false, false);
-
401 DO_COMPARE(realPos1, real0, false, false);
-
402 DO_COMPARE(realPos1, realPos1, true, false);
-
403 DO_COMPARE(realPos1, str0, false, true);
-
404 DO_COMPARE(realPos1, str1, false, true);
-
405 DO_COMPARE(realPos1, boolF, false, true);
-
406 DO_COMPARE(realPos1, boolT, false, true);
-
407 DO_COMPARE(realPos1, array0, false, true);
-
408 DO_COMPARE(realPos1, array1, false, true);
-
409 DO_COMPARE(realPos1, obj0, false, true);
-
410 DO_COMPARE(realPos1, obj1, false, true);
-
411
-
412 DO_COMPARE(str0, null0, false, false);
-
413 DO_COMPARE(str0, intNeg1, false, false);
-
414 DO_COMPARE(str0, int0, false, false);
-
415 DO_COMPARE(str0, intPos1, false, false);
-
416 DO_COMPARE(str0, uint0, false, false);
-
417 DO_COMPARE(str0, uint1, false, false);
-
418 DO_COMPARE(str0, realNeg1, false, false);
-
419 DO_COMPARE(str0, real0, false, false);
-
420 DO_COMPARE(str0, realPos1, false, false);
-
421 DO_COMPARE(str0, str0, true, false);
-
422 DO_COMPARE(str0, str1, false, true);
-
423 DO_COMPARE(str0, boolF, false, true);
-
424 DO_COMPARE(str0, boolT, false, true);
-
425 DO_COMPARE(str0, array0, false, true);
-
426 DO_COMPARE(str0, array1, false, true);
-
427 DO_COMPARE(str0, obj0, false, true);
-
428 DO_COMPARE(str0, obj1, false, true);
-
429
-
430 DO_COMPARE(str1, null0, false, false);
-
431 DO_COMPARE(str1, intNeg1, false, false);
-
432 DO_COMPARE(str1, int0, false, false);
-
433 DO_COMPARE(str1, intPos1, false, false);
-
434 DO_COMPARE(str1, uint0, false, false);
-
435 DO_COMPARE(str1, uint1, false, false);
-
436 DO_COMPARE(str1, realNeg1, false, false);
-
437 DO_COMPARE(str1, real0, false, false);
-
438 DO_COMPARE(str1, realPos1, false, false);
-
439 DO_COMPARE(str1, str0, false, false);
-
440 DO_COMPARE(str1, str1, true, false);
-
441 DO_COMPARE(str1, boolF, false, true);
-
442 DO_COMPARE(str1, boolT, false, true);
-
443 DO_COMPARE(str1, array0, false, true);
-
444 DO_COMPARE(str1, array1, false, true);
-
445 DO_COMPARE(str1, obj0, false, true);
-
446 DO_COMPARE(str1, obj1, false, true);
-
447
-
448 DO_COMPARE(boolF, null0, false, false);
-
449 DO_COMPARE(boolF, intNeg1, false, false);
-
450 DO_COMPARE(boolF, int0, false, false);
-
451 DO_COMPARE(boolF, intPos1, false, false);
-
452 DO_COMPARE(boolF, uint0, false, false);
-
453 DO_COMPARE(boolF, uint1, false, false);
-
454 DO_COMPARE(boolF, realNeg1, false, false);
-
455 DO_COMPARE(boolF, real0, false, false);
-
456 DO_COMPARE(boolF, realPos1, false, false);
-
457 DO_COMPARE(boolF, str0, false, false);
-
458 DO_COMPARE(boolF, str1, false, false);
-
459 DO_COMPARE(boolF, boolF, true, false);
-
460 DO_COMPARE(boolF, boolT, false, true);
-
461 DO_COMPARE(boolF, array0, false, true);
-
462 DO_COMPARE(boolF, array1, false, true);
-
463 DO_COMPARE(boolF, obj0, false, true);
-
464 DO_COMPARE(boolF, obj1, false, true);
-
465
-
466 DO_COMPARE(boolT, null0, false, false);
-
467 DO_COMPARE(boolT, intNeg1, false, false);
-
468 DO_COMPARE(boolT, int0, false, false);
-
469 DO_COMPARE(boolT, intPos1, false, false);
-
470 DO_COMPARE(boolT, uint0, false, false);
-
471 DO_COMPARE(boolT, uint1, false, false);
-
472 DO_COMPARE(boolT, realNeg1, false, false);
-
473 DO_COMPARE(boolT, real0, false, false);
-
474 DO_COMPARE(boolT, realPos1, false, false);
-
475 DO_COMPARE(boolT, str0, false, false);
-
476 DO_COMPARE(boolT, str1, false, false);
-
477 DO_COMPARE(boolT, boolF, false, false);
-
478 DO_COMPARE(boolT, boolT, true, false);
-
479 DO_COMPARE(boolT, array0, false, true);
-
480 DO_COMPARE(boolT, array1, false, true);
-
481 DO_COMPARE(boolT, obj0, false, true);
-
482 DO_COMPARE(boolT, obj1, false, true);
-
483
-
484 DO_COMPARE(array0, null0, false, false);
-
485 DO_COMPARE(array0, intNeg1, false, false);
-
486 DO_COMPARE(array0, int0, false, false);
-
487 DO_COMPARE(array0, intPos1, false, false);
-
488 DO_COMPARE(array0, uint0, false, false);
-
489 DO_COMPARE(array0, uint1, false, false);
-
490 DO_COMPARE(array0, realNeg1, false, false);
-
491 DO_COMPARE(array0, real0, false, false);
-
492 DO_COMPARE(array0, realPos1, false, false);
-
493 DO_COMPARE(array0, str0, false, false);
-
494 DO_COMPARE(array0, str1, false, false);
-
495 DO_COMPARE(array0, boolF, false, false);
-
496 DO_COMPARE(array0, boolT, false, false);
-
497 DO_COMPARE(array0, array0, true, false);
-
498 DO_COMPARE(array0, array1, false, true);
-
499 DO_COMPARE(array0, obj0, false, true);
-
500 DO_COMPARE(array0, obj1, false, true);
-
501
-
502 DO_COMPARE(array1, null0, false, false);
-
503 DO_COMPARE(array1, intNeg1, false, false);
-
504 DO_COMPARE(array1, int0, false, false);
-
505 DO_COMPARE(array1, intPos1, false, false);
-
506 DO_COMPARE(array1, uint0, false, false);
-
507 DO_COMPARE(array1, uint1, false, false);
-
508 DO_COMPARE(array1, realNeg1, false, false);
-
509 DO_COMPARE(array1, real0, false, false);
-
510 DO_COMPARE(array1, realPos1, false, false);
-
511 DO_COMPARE(array1, str0, false, false);
-
512 DO_COMPARE(array1, str1, false, false);
-
513 DO_COMPARE(array1, boolF, false, false);
-
514 DO_COMPARE(array1, boolT, false, false);
-
515 DO_COMPARE(array1, array0, false, false);
-
516 DO_COMPARE(array1, array1, true, false);
-
517 DO_COMPARE(array1, obj0, false, true);
-
518 DO_COMPARE(array1, obj1, false, true);
-
519
-
520 DO_COMPARE(obj0, null0, false, false);
-
521 DO_COMPARE(obj0, intNeg1, false, false);
-
522 DO_COMPARE(obj0, int0, false, false);
-
523 DO_COMPARE(obj0, intPos1, false, false);
-
524 DO_COMPARE(obj0, uint0, false, false);
-
525 DO_COMPARE(obj0, uint1, false, false);
-
526 DO_COMPARE(obj0, realNeg1, false, false);
-
527 DO_COMPARE(obj0, real0, false, false);
-
528 DO_COMPARE(obj0, realPos1, false, false);
-
529 DO_COMPARE(obj0, str0, false, false);
-
530 DO_COMPARE(obj0, str1, false, false);
-
531 DO_COMPARE(obj0, boolF, false, false);
-
532 DO_COMPARE(obj0, boolT, false, false);
-
533 DO_COMPARE(obj0, array0, false, false);
-
534 DO_COMPARE(obj0, array1, false, false);
-
535 DO_COMPARE(obj0, obj0, true, false);
-
536 DO_COMPARE(obj0, obj1, false, true);
-
537
-
538 DO_COMPARE(obj1, null0, false, false);
-
539 DO_COMPARE(obj1, intNeg1, false, false);
-
540 DO_COMPARE(obj1, int0, false, false);
-
541 DO_COMPARE(obj1, intPos1, false, false);
-
542 DO_COMPARE(obj1, uint0, false, false);
-
543 DO_COMPARE(obj1, uint1, false, false);
-
544 DO_COMPARE(obj1, realNeg1, false, false);
-
545 DO_COMPARE(obj1, real0, false, false);
-
546 DO_COMPARE(obj1, realPos1, false, false);
-
547 DO_COMPARE(obj1, str0, false, false);
-
548 DO_COMPARE(obj1, str1, false, false);
-
549 DO_COMPARE(obj1, boolF, false, false);
-
550 DO_COMPARE(obj1, boolT, false, false);
-
551 DO_COMPARE(obj1, array0, false, false);
-
552 DO_COMPARE(obj1, array1, false, false);
-
553 DO_COMPARE(obj1, obj0, false, false);
-
554 DO_COMPARE(obj1, obj1, true, false);
-
555#undef DO_COMPARE
-
556#pragma pop_macro("DO_COMPARE")
-
557}
+
202
+
+
203TEST(json_value, compare_strings)
+
204{
+
205 auto doCompare = [&](Json::Value const& lhs,
+
206 Json::Value const& rhs,
+
207 bool lhsEqRhs,
+
208 bool lhsLtRhs,
+
209 int line) {
+
210 SCOPED_TRACE(line);
+
211 EXPECT_EQ((lhs == rhs), lhsEqRhs);
+
212 EXPECT_NE((lhs != rhs), lhsEqRhs);
+
213 EXPECT_EQ((lhs < rhs), (!(lhsEqRhs || !lhsLtRhs)));
+
214 EXPECT_EQ((lhs <= rhs), (lhsEqRhs || lhsLtRhs));
+
215 EXPECT_EQ((lhs >= rhs), (lhsEqRhs || !lhsLtRhs));
+
216 EXPECT_EQ((lhs > rhs), (!(lhsEqRhs || lhsLtRhs)));
+
217 };
+
218
+
219 Json::Value const null0;
+
220 Json::Value const intNeg1{-1};
+
221 Json::Value const int0{Json::intValue};
+
222 Json::Value const intPos1{1};
+
223 Json::Value const uint0{Json::uintValue};
+
224 Json::Value const uint1{1u};
+
225 Json::Value const realNeg1{-1.0};
+
226 Json::Value const real0{Json::realValue};
+
227 Json::Value const realPos1{1.0};
+
228 Json::Value const str0{Json::stringValue};
+
229 Json::Value const str1{"1"};
+
230 Json::Value const boolF{false};
+
231 Json::Value const boolT{true};
+
232 Json::Value const array0{Json::arrayValue};
+
233 Json::Value const array1{[]() {
+
234 Json::Value array1;
+
235 array1[0u] = 1;
+
236 return array1;
+
237 }()};
+
238 Json::Value const obj0{Json::objectValue};
+
239 Json::Value const obj1{[]() {
+
240 Json::Value obj1;
+
241 obj1["one"] = 1;
+
242 return obj1;
+
243 }()};
+
244
+
245#pragma push_macro("DO_COMPARE")
+
246 // DO_COMPARE(lhs, rhs, lhsEqualsToRhs lhsLessThanRhs)
+
247#define DO_COMPARE(lhs, rhs, eq, lt) doCompare(lhs, rhs, eq, lt, __LINE__)
+
248 DO_COMPARE(null0, Json::Value{}, true, false);
+
249 DO_COMPARE(null0, intNeg1, false, true);
+
250 DO_COMPARE(null0, int0, false, true);
+
251 DO_COMPARE(null0, intPos1, false, true);
+
252 DO_COMPARE(null0, uint0, false, true);
+
253 DO_COMPARE(null0, uint1, false, true);
+
254 DO_COMPARE(null0, realNeg1, false, true);
+
255 DO_COMPARE(null0, real0, false, true);
+
256 DO_COMPARE(null0, realPos1, false, true);
+
257 DO_COMPARE(null0, str0, false, true);
+
258 DO_COMPARE(null0, str1, false, true);
+
259 DO_COMPARE(null0, boolF, false, true);
+
260 DO_COMPARE(null0, boolT, false, true);
+
261 DO_COMPARE(null0, array0, false, true);
+
262 DO_COMPARE(null0, array1, false, true);
+
263 DO_COMPARE(null0, obj0, false, true);
+
264 DO_COMPARE(null0, obj1, false, true);
+
265
+
266 DO_COMPARE(intNeg1, null0, false, false);
+
267 DO_COMPARE(intNeg1, intNeg1, true, false);
+
268 DO_COMPARE(intNeg1, int0, false, true);
+
269 DO_COMPARE(intNeg1, intPos1, false, true);
+
270 DO_COMPARE(intNeg1, uint0, false, true);
+
271 DO_COMPARE(intNeg1, uint1, false, true);
+
272 DO_COMPARE(intNeg1, realNeg1, false, true);
+
273 DO_COMPARE(intNeg1, real0, false, true);
+
274 DO_COMPARE(intNeg1, realPos1, false, true);
+
275 DO_COMPARE(intNeg1, str0, false, true);
+
276 DO_COMPARE(intNeg1, str1, false, true);
+
277 DO_COMPARE(intNeg1, boolF, false, true);
+
278 DO_COMPARE(intNeg1, boolT, false, true);
+
279 DO_COMPARE(intNeg1, array0, false, true);
+
280 DO_COMPARE(intNeg1, array1, false, true);
+
281 DO_COMPARE(intNeg1, obj0, false, true);
+
282 DO_COMPARE(intNeg1, obj1, false, true);
+
283
+
284 DO_COMPARE(int0, null0, false, false);
+
285 DO_COMPARE(int0, intNeg1, false, false);
+
286 DO_COMPARE(int0, int0, true, false);
+
287 DO_COMPARE(int0, intPos1, false, true);
+
288 DO_COMPARE(int0, uint0, true, false);
+
289 DO_COMPARE(int0, uint1, false, true);
+
290 DO_COMPARE(int0, realNeg1, false, true);
+
291 DO_COMPARE(int0, real0, false, true);
+
292 DO_COMPARE(int0, realPos1, false, true);
+
293 DO_COMPARE(int0, str0, false, true);
+
294 DO_COMPARE(int0, str1, false, true);
+
295 DO_COMPARE(int0, boolF, false, true);
+
296 DO_COMPARE(int0, boolT, false, true);
+
297 DO_COMPARE(int0, array0, false, true);
+
298 DO_COMPARE(int0, array1, false, true);
+
299 DO_COMPARE(int0, obj0, false, true);
+
300 DO_COMPARE(int0, obj1, false, true);
+
301
+
302 DO_COMPARE(intPos1, null0, false, false);
+
303 DO_COMPARE(intPos1, intNeg1, false, false);
+
304 DO_COMPARE(intPos1, int0, false, false);
+
305 DO_COMPARE(intPos1, intPos1, true, false);
+
306 DO_COMPARE(intPos1, uint0, false, false);
+
307 DO_COMPARE(intPos1, uint1, true, false);
+
308 DO_COMPARE(intPos1, realNeg1, false, true);
+
309 DO_COMPARE(intPos1, real0, false, true);
+
310 DO_COMPARE(intPos1, realPos1, false, true);
+
311 DO_COMPARE(intPos1, str0, false, true);
+
312 DO_COMPARE(intPos1, str1, false, true);
+
313 DO_COMPARE(intPos1, boolF, false, true);
+
314 DO_COMPARE(intPos1, boolT, false, true);
+
315 DO_COMPARE(intPos1, array0, false, true);
+
316 DO_COMPARE(intPos1, array1, false, true);
+
317 DO_COMPARE(intPos1, obj0, false, true);
+
318 DO_COMPARE(intPos1, obj1, false, true);
+
319
+
320 DO_COMPARE(uint0, null0, false, false);
+
321 DO_COMPARE(uint0, intNeg1, false, false);
+
322 DO_COMPARE(uint0, int0, true, false);
+
323 DO_COMPARE(uint0, intPos1, false, true);
+
324 DO_COMPARE(uint0, uint0, true, false);
+
325 DO_COMPARE(uint0, uint1, false, true);
+
326 DO_COMPARE(uint0, realNeg1, false, true);
+
327 DO_COMPARE(uint0, real0, false, true);
+
328 DO_COMPARE(uint0, realPos1, false, true);
+
329 DO_COMPARE(uint0, str0, false, true);
+
330 DO_COMPARE(uint0, str1, false, true);
+
331 DO_COMPARE(uint0, boolF, false, true);
+
332 DO_COMPARE(uint0, boolT, false, true);
+
333 DO_COMPARE(uint0, array0, false, true);
+
334 DO_COMPARE(uint0, array1, false, true);
+
335 DO_COMPARE(uint0, obj0, false, true);
+
336 DO_COMPARE(uint0, obj1, false, true);
+
337
+
338 DO_COMPARE(uint1, null0, false, false);
+
339 DO_COMPARE(uint1, intNeg1, false, false);
+
340 DO_COMPARE(uint1, int0, false, false);
+
341 DO_COMPARE(uint1, intPos1, true, false);
+
342 DO_COMPARE(uint1, uint0, false, false);
+
343 DO_COMPARE(uint1, uint1, true, false);
+
344 DO_COMPARE(uint1, realNeg1, false, true);
+
345 DO_COMPARE(uint1, real0, false, true);
+
346 DO_COMPARE(uint1, realPos1, false, true);
+
347 DO_COMPARE(uint1, str0, false, true);
+
348 DO_COMPARE(uint1, str1, false, true);
+
349 DO_COMPARE(uint1, boolF, false, true);
+
350 DO_COMPARE(uint1, boolT, false, true);
+
351 DO_COMPARE(uint1, array0, false, true);
+
352 DO_COMPARE(uint1, array1, false, true);
+
353 DO_COMPARE(uint1, obj0, false, true);
+
354 DO_COMPARE(uint1, obj1, false, true);
+
355
+
356 DO_COMPARE(realNeg1, null0, false, false);
+
357 DO_COMPARE(realNeg1, intNeg1, false, false);
+
358 DO_COMPARE(realNeg1, int0, false, false);
+
359 DO_COMPARE(realNeg1, intPos1, false, false);
+
360 DO_COMPARE(realNeg1, uint0, false, false);
+
361 DO_COMPARE(realNeg1, uint1, false, false);
+
362 DO_COMPARE(realNeg1, realNeg1, true, false);
+
363 DO_COMPARE(realNeg1, real0, false, true);
+
364 DO_COMPARE(realNeg1, realPos1, false, true);
+
365 DO_COMPARE(realNeg1, str0, false, true);
+
366 DO_COMPARE(realNeg1, str1, false, true);
+
367 DO_COMPARE(realNeg1, boolF, false, true);
+
368 DO_COMPARE(realNeg1, boolT, false, true);
+
369 DO_COMPARE(realNeg1, array0, false, true);
+
370 DO_COMPARE(realNeg1, array1, false, true);
+
371 DO_COMPARE(realNeg1, obj0, false, true);
+
372 DO_COMPARE(realNeg1, obj1, false, true);
+
373
+
374 DO_COMPARE(real0, null0, false, false);
+
375 DO_COMPARE(real0, intNeg1, false, false);
+
376 DO_COMPARE(real0, int0, false, false);
+
377 DO_COMPARE(real0, intPos1, false, false);
+
378 DO_COMPARE(real0, uint0, false, false);
+
379 DO_COMPARE(real0, uint1, false, false);
+
380 DO_COMPARE(real0, realNeg1, false, false);
+
381 DO_COMPARE(real0, real0, true, false);
+
382 DO_COMPARE(real0, realPos1, false, true);
+
383 DO_COMPARE(real0, str0, false, true);
+
384 DO_COMPARE(real0, str1, false, true);
+
385 DO_COMPARE(real0, boolF, false, true);
+
386 DO_COMPARE(real0, boolT, false, true);
+
387 DO_COMPARE(real0, array0, false, true);
+
388 DO_COMPARE(real0, array1, false, true);
+
389 DO_COMPARE(real0, obj0, false, true);
+
390 DO_COMPARE(real0, obj1, false, true);
+
391
+
392 DO_COMPARE(realPos1, null0, false, false);
+
393 DO_COMPARE(realPos1, intNeg1, false, false);
+
394 DO_COMPARE(realPos1, int0, false, false);
+
395 DO_COMPARE(realPos1, intPos1, false, false);
+
396 DO_COMPARE(realPos1, uint0, false, false);
+
397 DO_COMPARE(realPos1, uint1, false, false);
+
398 DO_COMPARE(realPos1, realNeg1, false, false);
+
399 DO_COMPARE(realPos1, real0, false, false);
+
400 DO_COMPARE(realPos1, realPos1, true, false);
+
401 DO_COMPARE(realPos1, str0, false, true);
+
402 DO_COMPARE(realPos1, str1, false, true);
+
403 DO_COMPARE(realPos1, boolF, false, true);
+
404 DO_COMPARE(realPos1, boolT, false, true);
+
405 DO_COMPARE(realPos1, array0, false, true);
+
406 DO_COMPARE(realPos1, array1, false, true);
+
407 DO_COMPARE(realPos1, obj0, false, true);
+
408 DO_COMPARE(realPos1, obj1, false, true);
+
409
+
410 DO_COMPARE(str0, null0, false, false);
+
411 DO_COMPARE(str0, intNeg1, false, false);
+
412 DO_COMPARE(str0, int0, false, false);
+
413 DO_COMPARE(str0, intPos1, false, false);
+
414 DO_COMPARE(str0, uint0, false, false);
+
415 DO_COMPARE(str0, uint1, false, false);
+
416 DO_COMPARE(str0, realNeg1, false, false);
+
417 DO_COMPARE(str0, real0, false, false);
+
418 DO_COMPARE(str0, realPos1, false, false);
+
419 DO_COMPARE(str0, str0, true, false);
+
420 DO_COMPARE(str0, str1, false, true);
+
421 DO_COMPARE(str0, boolF, false, true);
+
422 DO_COMPARE(str0, boolT, false, true);
+
423 DO_COMPARE(str0, array0, false, true);
+
424 DO_COMPARE(str0, array1, false, true);
+
425 DO_COMPARE(str0, obj0, false, true);
+
426 DO_COMPARE(str0, obj1, false, true);
+
427
+
428 DO_COMPARE(str1, null0, false, false);
+
429 DO_COMPARE(str1, intNeg1, false, false);
+
430 DO_COMPARE(str1, int0, false, false);
+
431 DO_COMPARE(str1, intPos1, false, false);
+
432 DO_COMPARE(str1, uint0, false, false);
+
433 DO_COMPARE(str1, uint1, false, false);
+
434 DO_COMPARE(str1, realNeg1, false, false);
+
435 DO_COMPARE(str1, real0, false, false);
+
436 DO_COMPARE(str1, realPos1, false, false);
+
437 DO_COMPARE(str1, str0, false, false);
+
438 DO_COMPARE(str1, str1, true, false);
+
439 DO_COMPARE(str1, boolF, false, true);
+
440 DO_COMPARE(str1, boolT, false, true);
+
441 DO_COMPARE(str1, array0, false, true);
+
442 DO_COMPARE(str1, array1, false, true);
+
443 DO_COMPARE(str1, obj0, false, true);
+
444 DO_COMPARE(str1, obj1, false, true);
+
445
+
446 DO_COMPARE(boolF, null0, false, false);
+
447 DO_COMPARE(boolF, intNeg1, false, false);
+
448 DO_COMPARE(boolF, int0, false, false);
+
449 DO_COMPARE(boolF, intPos1, false, false);
+
450 DO_COMPARE(boolF, uint0, false, false);
+
451 DO_COMPARE(boolF, uint1, false, false);
+
452 DO_COMPARE(boolF, realNeg1, false, false);
+
453 DO_COMPARE(boolF, real0, false, false);
+
454 DO_COMPARE(boolF, realPos1, false, false);
+
455 DO_COMPARE(boolF, str0, false, false);
+
456 DO_COMPARE(boolF, str1, false, false);
+
457 DO_COMPARE(boolF, boolF, true, false);
+
458 DO_COMPARE(boolF, boolT, false, true);
+
459 DO_COMPARE(boolF, array0, false, true);
+
460 DO_COMPARE(boolF, array1, false, true);
+
461 DO_COMPARE(boolF, obj0, false, true);
+
462 DO_COMPARE(boolF, obj1, false, true);
+
463
+
464 DO_COMPARE(boolT, null0, false, false);
+
465 DO_COMPARE(boolT, intNeg1, false, false);
+
466 DO_COMPARE(boolT, int0, false, false);
+
467 DO_COMPARE(boolT, intPos1, false, false);
+
468 DO_COMPARE(boolT, uint0, false, false);
+
469 DO_COMPARE(boolT, uint1, false, false);
+
470 DO_COMPARE(boolT, realNeg1, false, false);
+
471 DO_COMPARE(boolT, real0, false, false);
+
472 DO_COMPARE(boolT, realPos1, false, false);
+
473 DO_COMPARE(boolT, str0, false, false);
+
474 DO_COMPARE(boolT, str1, false, false);
+
475 DO_COMPARE(boolT, boolF, false, false);
+
476 DO_COMPARE(boolT, boolT, true, false);
+
477 DO_COMPARE(boolT, array0, false, true);
+
478 DO_COMPARE(boolT, array1, false, true);
+
479 DO_COMPARE(boolT, obj0, false, true);
+
480 DO_COMPARE(boolT, obj1, false, true);
+
481
+
482 DO_COMPARE(array0, null0, false, false);
+
483 DO_COMPARE(array0, intNeg1, false, false);
+
484 DO_COMPARE(array0, int0, false, false);
+
485 DO_COMPARE(array0, intPos1, false, false);
+
486 DO_COMPARE(array0, uint0, false, false);
+
487 DO_COMPARE(array0, uint1, false, false);
+
488 DO_COMPARE(array0, realNeg1, false, false);
+
489 DO_COMPARE(array0, real0, false, false);
+
490 DO_COMPARE(array0, realPos1, false, false);
+
491 DO_COMPARE(array0, str0, false, false);
+
492 DO_COMPARE(array0, str1, false, false);
+
493 DO_COMPARE(array0, boolF, false, false);
+
494 DO_COMPARE(array0, boolT, false, false);
+
495 DO_COMPARE(array0, array0, true, false);
+
496 DO_COMPARE(array0, array1, false, true);
+
497 DO_COMPARE(array0, obj0, false, true);
+
498 DO_COMPARE(array0, obj1, false, true);
+
499
+
500 DO_COMPARE(array1, null0, false, false);
+
501 DO_COMPARE(array1, intNeg1, false, false);
+
502 DO_COMPARE(array1, int0, false, false);
+
503 DO_COMPARE(array1, intPos1, false, false);
+
504 DO_COMPARE(array1, uint0, false, false);
+
505 DO_COMPARE(array1, uint1, false, false);
+
506 DO_COMPARE(array1, realNeg1, false, false);
+
507 DO_COMPARE(array1, real0, false, false);
+
508 DO_COMPARE(array1, realPos1, false, false);
+
509 DO_COMPARE(array1, str0, false, false);
+
510 DO_COMPARE(array1, str1, false, false);
+
511 DO_COMPARE(array1, boolF, false, false);
+
512 DO_COMPARE(array1, boolT, false, false);
+
513 DO_COMPARE(array1, array0, false, false);
+
514 DO_COMPARE(array1, array1, true, false);
+
515 DO_COMPARE(array1, obj0, false, true);
+
516 DO_COMPARE(array1, obj1, false, true);
+
517
+
518 DO_COMPARE(obj0, null0, false, false);
+
519 DO_COMPARE(obj0, intNeg1, false, false);
+
520 DO_COMPARE(obj0, int0, false, false);
+
521 DO_COMPARE(obj0, intPos1, false, false);
+
522 DO_COMPARE(obj0, uint0, false, false);
+
523 DO_COMPARE(obj0, uint1, false, false);
+
524 DO_COMPARE(obj0, realNeg1, false, false);
+
525 DO_COMPARE(obj0, real0, false, false);
+
526 DO_COMPARE(obj0, realPos1, false, false);
+
527 DO_COMPARE(obj0, str0, false, false);
+
528 DO_COMPARE(obj0, str1, false, false);
+
529 DO_COMPARE(obj0, boolF, false, false);
+
530 DO_COMPARE(obj0, boolT, false, false);
+
531 DO_COMPARE(obj0, array0, false, false);
+
532 DO_COMPARE(obj0, array1, false, false);
+
533 DO_COMPARE(obj0, obj0, true, false);
+
534 DO_COMPARE(obj0, obj1, false, true);
+
535
+
536 DO_COMPARE(obj1, null0, false, false);
+
537 DO_COMPARE(obj1, intNeg1, false, false);
+
538 DO_COMPARE(obj1, int0, false, false);
+
539 DO_COMPARE(obj1, intPos1, false, false);
+
540 DO_COMPARE(obj1, uint0, false, false);
+
541 DO_COMPARE(obj1, uint1, false, false);
+
542 DO_COMPARE(obj1, realNeg1, false, false);
+
543 DO_COMPARE(obj1, real0, false, false);
+
544 DO_COMPARE(obj1, realPos1, false, false);
+
545 DO_COMPARE(obj1, str0, false, false);
+
546 DO_COMPARE(obj1, str1, false, false);
+
547 DO_COMPARE(obj1, boolF, false, false);
+
548 DO_COMPARE(obj1, boolT, false, false);
+
549 DO_COMPARE(obj1, array0, false, false);
+
550 DO_COMPARE(obj1, array1, false, false);
+
551 DO_COMPARE(obj1, obj0, false, false);
+
552 DO_COMPARE(obj1, obj1, true, false);
+
553#undef DO_COMPARE
+
554#pragma pop_macro("DO_COMPARE")
+
555}
-
558
-
- -
560{
-
561 CHECK(!Json::Value());
+
556
+
+
557TEST(json_value, bool)
+
558{
+
559 EXPECT_FALSE(Json::Value());
+
560
+
561 EXPECT_FALSE(Json::Value(""));
562
-
563 CHECK(!Json::Value(""));
-
564
-
565 CHECK(bool(Json::Value("empty")));
-
566 CHECK(bool(Json::Value(false)));
-
567 CHECK(bool(Json::Value(true)));
-
568 CHECK(bool(Json::Value(0)));
-
569 CHECK(bool(Json::Value(1)));
-
570
- -
572 CHECK(!array);
-
573 array.append(0);
-
574 CHECK(bool(array));
-
575
- -
577 CHECK(!object);
-
578 object[""] = false;
-
579 CHECK(bool(object));
-
580}
+
563 EXPECT_TRUE(bool(Json::Value("empty")));
+
564 EXPECT_TRUE(bool(Json::Value(false)));
+
565 EXPECT_TRUE(bool(Json::Value(true)));
+
566 EXPECT_TRUE(bool(Json::Value(0)));
+
567 EXPECT_TRUE(bool(Json::Value(1)));
+
568
+ +
570 EXPECT_FALSE(array);
+
571 array.append(0);
+
572 EXPECT_TRUE(bool(array));
+
573
+ +
575 EXPECT_FALSE(object);
+
576 object[""] = false;
+
577 EXPECT_TRUE(bool(object));
+
578}
-
581
-
-
582TEST_CASE("bad json")
-
583{
-
584 char const* s(R"({"method":"ledger","params":[{"ledger_index":1e300}]})");
-
585
-
586 Json::Value j;
-
587 Json::Reader r;
-
588
-
589 CHECK(r.parse(s, j));
-
590}
+
579
+
+
580TEST(json_value, bad_json)
+
581{
+
582 char const* s(R"({"method":"ledger","params":[{"ledger_index":1e300}]})");
+
583
+
584 Json::Value j;
+
585 Json::Reader r;
+
586
+
587 EXPECT_TRUE(r.parse(s, j));
+
588}
-
591
-
-
592TEST_CASE("edge cases")
-
593{
- - - -
597
-
598 std::uint32_t a_uint = max_uint - 1978;
-
599 std::int32_t a_large_int = max_int - 1978;
-
600 std::int32_t a_small_int = min_int + 1978;
-
601
-
602 {
-
603 std::string json = "{\"max_uint\":" + std::to_string(max_uint);
-
604 json += ",\"max_int\":" + std::to_string(max_int);
-
605 json += ",\"min_int\":" + std::to_string(min_int);
-
606 json += ",\"a_uint\":" + std::to_string(a_uint);
-
607 json += ",\"a_large_int\":" + std::to_string(a_large_int);
-
608 json += ",\"a_small_int\":" + std::to_string(a_small_int);
-
609 json += "}";
-
610
-
611 Json::Value j1;
-
612 Json::Reader r1;
-
613
-
614 CHECK(r1.parse(json, j1));
-
615 CHECK(j1["max_uint"].asUInt() == max_uint);
-
616 CHECK(j1["max_uint"].asAbsUInt() == max_uint);
-
617 CHECK(j1["max_int"].asInt() == max_int);
-
618 CHECK(j1["max_int"].asAbsUInt() == max_int);
-
619 CHECK(j1["min_int"].asInt() == min_int);
-
620 CHECK(
-
621 j1["min_int"].asAbsUInt() ==
-
622 static_cast<std::int64_t>(min_int) * -1);
-
623 CHECK(j1["a_uint"].asUInt() == a_uint);
-
624 CHECK(j1["a_uint"].asAbsUInt() == a_uint);
-
625 CHECK(j1["a_uint"] > a_large_int);
-
626 CHECK(j1["a_uint"] > a_small_int);
-
627 CHECK(j1["a_large_int"].asInt() == a_large_int);
-
628 CHECK(j1["a_large_int"].asAbsUInt() == a_large_int);
-
629 CHECK(j1["a_large_int"].asUInt() == a_large_int);
-
630 CHECK(j1["a_large_int"] < a_uint);
-
631 CHECK(j1["a_small_int"].asInt() == a_small_int);
-
632 CHECK(
-
633 j1["a_small_int"].asAbsUInt() ==
-
634 static_cast<std::int64_t>(a_small_int) * -1);
-
635 CHECK(j1["a_small_int"] < a_uint);
-
636 }
-
637
-
638 std::uint64_t overflow = std::uint64_t(max_uint) + 1;
-
639 {
-
640 std::string json = "{\"overflow\":";
-
641 json += std::to_string(overflow);
-
642 json += "}";
+
589
+
+
590TEST(json_value, edge_cases)
+
591{
+ + + +
595
+
596 std::uint32_t a_uint = max_uint - 1978;
+
597 std::int32_t a_large_int = max_int - 1978;
+
598 std::int32_t a_small_int = min_int + 1978;
+
599
+
600 {
+
601 std::string json = "{\"max_uint\":" + std::to_string(max_uint);
+
602 json += ",\"max_int\":" + std::to_string(max_int);
+
603 json += ",\"min_int\":" + std::to_string(min_int);
+
604 json += ",\"a_uint\":" + std::to_string(a_uint);
+
605 json += ",\"a_large_int\":" + std::to_string(a_large_int);
+
606 json += ",\"a_small_int\":" + std::to_string(a_small_int);
+
607 json += "}";
+
608
+
609 Json::Value j1;
+
610 Json::Reader r1;
+
611
+
612 EXPECT_TRUE(r1.parse(json, j1));
+
613 EXPECT_EQ(j1["max_uint"].asUInt(), max_uint);
+
614 EXPECT_EQ(j1["max_uint"].asAbsUInt(), max_uint);
+
615 EXPECT_EQ(j1["max_int"].asInt(), max_int);
+
616 EXPECT_EQ(j1["max_int"].asAbsUInt(), max_int);
+
617 EXPECT_EQ(j1["min_int"].asInt(), min_int);
+
618 EXPECT_EQ(
+
619 j1["min_int"].asAbsUInt(), static_cast<std::int64_t>(min_int) * -1);
+
620 EXPECT_EQ(j1["a_uint"].asUInt(), a_uint);
+
621 EXPECT_EQ(j1["a_uint"].asAbsUInt(), a_uint);
+
622 EXPECT_GT(j1["a_uint"], a_large_int);
+
623 EXPECT_GT(j1["a_uint"], a_small_int);
+
624 EXPECT_EQ(j1["a_large_int"].asInt(), a_large_int);
+
625 EXPECT_EQ(j1["a_large_int"].asAbsUInt(), a_large_int);
+
626 EXPECT_EQ(j1["a_large_int"].asUInt(), a_large_int);
+
627 EXPECT_LT(j1["a_large_int"], a_uint);
+
628 EXPECT_EQ(j1["a_small_int"].asInt(), a_small_int);
+
629 EXPECT_EQ(
+
630 j1["a_small_int"].asAbsUInt(),
+
631 static_cast<std::int64_t>(a_small_int) * -1);
+
632 EXPECT_LT(j1["a_small_int"], a_uint);
+
633 }
+
634
+
635 std::uint64_t overflow = std::uint64_t(max_uint) + 1;
+
636 {
+
637 std::string json = "{\"overflow\":";
+
638 json += std::to_string(overflow);
+
639 json += "}";
+
640
+
641 Json::Value j2;
+
642 Json::Reader r2;
643
-
644 Json::Value j2;
-
645 Json::Reader r2;
+
644 EXPECT_FALSE(r2.parse(json, j2));
+
645 }
646
-
647 CHECK(!r2.parse(json, j2));
-
648 }
-
649
-
650 std::int64_t underflow = std::int64_t(min_int) - 1;
-
651 {
-
652 std::string json = "{\"underflow\":";
-
653 json += std::to_string(underflow);
-
654 json += "}";
+
647 std::int64_t underflow = std::int64_t(min_int) - 1;
+
648 {
+
649 std::string json = "{\"underflow\":";
+
650 json += std::to_string(underflow);
+
651 json += "}";
+
652
+
653 Json::Value j3;
+
654 Json::Reader r3;
655
-
656 Json::Value j3;
-
657 Json::Reader r3;
+
656 EXPECT_FALSE(r3.parse(json, j3));
+
657 }
658
-
659 CHECK(!r3.parse(json, j3));
-
660 }
-
661
-
662 {
-
663 Json::Value intString{std::to_string(overflow)};
-
664 CHECK_THROWS_AS(intString.asUInt(), beast::BadLexicalCast);
-
665 CHECK_THROWS_AS(intString.asAbsUInt(), Json::error);
-
666
-
667 intString = "4294967295";
-
668 CHECK(intString.asUInt() == 4294967295u);
-
669 CHECK(intString.asAbsUInt() == 4294967295u);
-
670
-
671 intString = "0";
-
672 CHECK(intString.asUInt() == 0);
-
673 CHECK(intString.asAbsUInt() == 0);
-
674
-
675 intString = "-1";
-
676 CHECK_THROWS_AS(intString.asUInt(), beast::BadLexicalCast);
-
677 CHECK(intString.asAbsUInt() == 1);
+
659 {
+
660 Json::Value intString{std::to_string(overflow)};
+
661 EXPECT_THROW(intString.asUInt(), beast::BadLexicalCast);
+
662 EXPECT_THROW(intString.asAbsUInt(), Json::error);
+
663
+
664 intString = "4294967295";
+
665 EXPECT_EQ(intString.asUInt(), 4294967295u);
+
666 EXPECT_EQ(intString.asAbsUInt(), 4294967295u);
+
667
+
668 intString = "0";
+
669 EXPECT_EQ(intString.asUInt(), 0);
+
670 EXPECT_EQ(intString.asAbsUInt(), 0);
+
671
+
672 intString = "-1";
+
673 EXPECT_THROW(intString.asUInt(), beast::BadLexicalCast);
+
674 EXPECT_EQ(intString.asAbsUInt(), 1);
+
675
+
676 intString = "-4294967295";
+
677 EXPECT_EQ(intString.asAbsUInt(), 4294967295);
678
-
679 intString = "-4294967295";
-
680 CHECK(intString.asAbsUInt() == 4294967295);
+
679 intString = "-4294967296";
+
680 EXPECT_THROW(intString.asAbsUInt(), Json::error);
681
-
682 intString = "-4294967296";
-
683 CHECK_THROWS_AS(intString.asAbsUInt(), Json::error);
-
684
-
685 intString = "2147483648";
-
686 CHECK_THROWS_AS(intString.asInt(), beast::BadLexicalCast);
-
687 CHECK(intString.asAbsUInt() == 2147483648);
-
688
-
689 intString = "2147483647";
-
690 CHECK(intString.asInt() == 2147483647);
-
691 CHECK(intString.asAbsUInt() == 2147483647);
-
692
-
693 intString = "-2147483648";
-
694 CHECK(intString.asInt() == -2147483648LL); // MSVC wants the LL
-
695 CHECK(intString.asAbsUInt() == 2147483648LL);
-
696
-
697 intString = "-2147483649";
-
698 CHECK_THROWS_AS(intString.asInt(), beast::BadLexicalCast);
-
699 CHECK(intString.asAbsUInt() == 2147483649);
-
700 }
-
701
-
702 {
-
703 Json::Value intReal{4294967297.0};
-
704 CHECK_THROWS_AS(intReal.asUInt(), Json::error);
-
705 CHECK_THROWS_AS(intReal.asAbsUInt(), Json::error);
-
706
-
707 intReal = 4294967295.0;
-
708 CHECK(intReal.asUInt() == 4294967295u);
-
709 CHECK(intReal.asAbsUInt() == 4294967295u);
-
710
-
711 intReal = 0.0;
-
712 CHECK(intReal.asUInt() == 0);
-
713 CHECK(intReal.asAbsUInt() == 0);
-
714
-
715 intReal = -1.0;
-
716 CHECK_THROWS_AS(intReal.asUInt(), Json::error);
-
717 CHECK(intReal.asAbsUInt() == 1);
+
682 intString = "2147483648";
+
683 EXPECT_THROW(intString.asInt(), beast::BadLexicalCast);
+
684 EXPECT_EQ(intString.asAbsUInt(), 2147483648);
+
685
+
686 intString = "2147483647";
+
687 EXPECT_EQ(intString.asInt(), 2147483647);
+
688 EXPECT_EQ(intString.asAbsUInt(), 2147483647);
+
689
+
690 intString = "-2147483648";
+
691 EXPECT_EQ(intString.asInt(), -2147483648LL); // MSVC wants the LL
+
692 EXPECT_EQ(intString.asAbsUInt(), 2147483648LL);
+
693
+
694 intString = "-2147483649";
+
695 EXPECT_THROW(intString.asInt(), beast::BadLexicalCast);
+
696 EXPECT_EQ(intString.asAbsUInt(), 2147483649);
+
697 }
+
698
+
699 {
+
700 Json::Value intReal{4294967297.0};
+
701 EXPECT_THROW(intReal.asUInt(), Json::error);
+
702 EXPECT_THROW(intReal.asAbsUInt(), Json::error);
+
703
+
704 intReal = 4294967295.0;
+
705 EXPECT_EQ(intReal.asUInt(), 4294967295u);
+
706 EXPECT_EQ(intReal.asAbsUInt(), 4294967295u);
+
707
+
708 intReal = 0.0;
+
709 EXPECT_EQ(intReal.asUInt(), 0);
+
710 EXPECT_EQ(intReal.asAbsUInt(), 0);
+
711
+
712 intReal = -1.0;
+
713 EXPECT_THROW(intReal.asUInt(), Json::error);
+
714 EXPECT_EQ(intReal.asAbsUInt(), 1);
+
715
+
716 intReal = -4294967295.0;
+
717 EXPECT_EQ(intReal.asAbsUInt(), 4294967295);
718
-
719 intReal = -4294967295.0;
-
720 CHECK(intReal.asAbsUInt() == 4294967295);
+
719 intReal = -4294967296.0;
+
720 EXPECT_THROW(intReal.asAbsUInt(), Json::error);
721
-
722 intReal = -4294967296.0;
-
723 CHECK_THROWS_AS(intReal.asAbsUInt(), Json::error);
-
724
-
725 intReal = 2147483648.0;
-
726 CHECK_THROWS_AS(intReal.asInt(), Json::error);
-
727 CHECK(intReal.asAbsUInt() == 2147483648);
-
728
-
729 intReal = 2147483647.0;
-
730 CHECK(intReal.asInt() == 2147483647);
-
731 CHECK(intReal.asAbsUInt() == 2147483647);
-
732
-
733 intReal = -2147483648.0;
-
734 CHECK(intReal.asInt() == -2147483648LL); // MSVC wants the LL
-
735 CHECK(intReal.asAbsUInt() == 2147483648LL);
-
736
-
737 intReal = -2147483649.0;
-
738 CHECK_THROWS_AS(intReal.asInt(), Json::error);
-
739 CHECK(intReal.asAbsUInt() == 2147483649);
-
740 }
-
741}
+
722 intReal = 2147483648.0;
+
723 EXPECT_THROW(intReal.asInt(), Json::error);
+
724 EXPECT_EQ(intReal.asAbsUInt(), 2147483648);
+
725
+
726 intReal = 2147483647.0;
+
727 EXPECT_EQ(intReal.asInt(), 2147483647);
+
728 EXPECT_EQ(intReal.asAbsUInt(), 2147483647);
+
729
+
730 intReal = -2147483648.0;
+
731 EXPECT_EQ(intReal.asInt(), -2147483648LL); // MSVC wants the LL
+
732 EXPECT_EQ(intReal.asAbsUInt(), 2147483648LL);
+
733
+
734 intReal = -2147483649.0;
+
735 EXPECT_THROW(intReal.asInt(), Json::error);
+
736 EXPECT_EQ(intReal.asAbsUInt(), 2147483649);
+
737 }
+
738}
-
742
-
- -
744{
-
745 Json::Value v1{2.5};
-
746 CHECK(v1.isDouble());
-
747 CHECK(v1.asDouble() == 2.5);
-
748
-
749 Json::Value v2 = v1;
-
750 CHECK(v1.isDouble());
-
751 CHECK(v1.asDouble() == 2.5);
-
752 CHECK(v2.isDouble());
-
753 CHECK(v2.asDouble() == 2.5);
-
754 CHECK(v1 == v2);
-
755
-
756 v1 = v2;
-
757 CHECK(v1.isDouble());
-
758 CHECK(v1.asDouble() == 2.5);
-
759 CHECK(v2.isDouble());
-
760 CHECK(v2.asDouble() == 2.5);
-
761 CHECK(v1 == v2);
-
762}
+
739
+
+
740TEST(json_value, copy)
+
741{
+
742 Json::Value v1{2.5};
+
743 EXPECT_TRUE(v1.isDouble());
+
744 EXPECT_EQ(v1.asDouble(), 2.5);
+
745
+
746 Json::Value v2 = v1;
+
747 EXPECT_TRUE(v1.isDouble());
+
748 EXPECT_EQ(v1.asDouble(), 2.5);
+
749 EXPECT_TRUE(v2.isDouble());
+
750 EXPECT_EQ(v2.asDouble(), 2.5);
+
751 EXPECT_EQ(v1, v2);
+
752
+
753 v1 = v2;
+
754 EXPECT_TRUE(v1.isDouble());
+
755 EXPECT_EQ(v1.asDouble(), 2.5);
+
756 EXPECT_TRUE(v2.isDouble());
+
757 EXPECT_EQ(v2.asDouble(), 2.5);
+
758 EXPECT_EQ(v1, v2);
+
759}
-
763
-
- -
765{
-
766 Json::Value v1{2.5};
-
767 CHECK(v1.isDouble());
-
768 CHECK(v1.asDouble() == 2.5);
-
769
-
770 Json::Value v2 = std::move(v1);
-
771 CHECK(!v1);
-
772 CHECK(v2.isDouble());
-
773 CHECK(v2.asDouble() == 2.5);
-
774 CHECK(v1 != v2);
-
775
-
776 v1 = std::move(v2);
-
777 CHECK(v1.isDouble());
-
778 CHECK(v1.asDouble() == 2.5);
-
779 CHECK(!v2);
-
780 CHECK(v1 != v2);
-
781}
+
760
+
+
761TEST(json_value, move)
+
762{
+
763 Json::Value v1{2.5};
+
764 EXPECT_TRUE(v1.isDouble());
+
765 EXPECT_EQ(v1.asDouble(), 2.5);
+
766
+
767 Json::Value v2 = std::move(v1);
+
768 EXPECT_FALSE(v1);
+
769 EXPECT_TRUE(v2.isDouble());
+
770 EXPECT_EQ(v2.asDouble(), 2.5);
+
771 EXPECT_NE(v1, v2);
+
772
+
773 v1 = std::move(v2);
+
774 EXPECT_TRUE(v1.isDouble());
+
775 EXPECT_EQ(v1.asDouble(), 2.5);
+
776 EXPECT_FALSE(v2);
+
777 EXPECT_NE(v1, v2);
+
778}
-
782
-
-
783TEST_CASE("comparisons")
-
784{
-
785 Json::Value a, b;
-
786 auto testEquals = [&](std::string const& name) {
-
787 CHECK(a == b);
-
788 CHECK(a <= b);
-
789 CHECK(a >= b);
-
790
-
791 CHECK(!(a != b));
-
792 CHECK(!(a < b));
-
793 CHECK(!(a > b));
-
794
-
795 CHECK(b == a);
-
796 CHECK(b <= a);
-
797 CHECK(b >= a);
-
798
-
799 CHECK(!(b != a));
-
800 CHECK(!(b < a));
-
801 CHECK(!(b > a));
-
802 };
-
803
-
804 auto testGreaterThan = [&](std::string const& name) {
-
805 CHECK(!(a == b));
-
806 CHECK(!(a <= b));
-
807 CHECK(a >= b);
-
808
-
809 CHECK(a != b);
-
810 CHECK(!(a < b));
-
811 CHECK(a > b);
-
812
-
813 CHECK(!(b == a));
-
814 CHECK(b <= a);
-
815 CHECK(!(b >= a));
-
816
-
817 CHECK(b != a);
-
818 CHECK(b < a);
-
819 CHECK(!(b > a));
-
820 };
-
821
-
822 a["a"] = Json::UInt(0);
-
823 b["a"] = Json::Int(0);
-
824 testEquals("zero");
+
779
+
+
780TEST(json_value, comparisons)
+
781{
+
782 Json::Value a, b;
+
783 auto testEquals = [&](std::string const& name) {
+
784 EXPECT_TRUE(a == b);
+
785 EXPECT_TRUE(a <= b);
+
786 EXPECT_TRUE(a >= b);
+
787
+
788 EXPECT_FALSE(a != b);
+
789 EXPECT_FALSE(a < b);
+
790 EXPECT_FALSE(a > b);
+
791
+
792 EXPECT_TRUE(b == a);
+
793 EXPECT_TRUE(b <= a);
+
794 EXPECT_TRUE(b >= a);
+
795
+
796 EXPECT_FALSE(b != a);
+
797 EXPECT_FALSE(b < a);
+
798 EXPECT_FALSE(b > a);
+
799 };
+
800
+
801 auto testGreaterThan = [&](std::string const& name) {
+
802 EXPECT_FALSE(a == b);
+
803 EXPECT_FALSE(a <= b);
+
804 EXPECT_TRUE(a >= b);
+
805
+
806 EXPECT_TRUE(a != b);
+
807 EXPECT_FALSE(a < b);
+
808 EXPECT_TRUE(a > b);
+
809
+
810 EXPECT_FALSE(b == a);
+
811 EXPECT_TRUE(b <= a);
+
812 EXPECT_FALSE(b >= a);
+
813
+
814 EXPECT_TRUE(b != a);
+
815 EXPECT_TRUE(b < a);
+
816 EXPECT_FALSE(b > a);
+
817 };
+
818
+
819 a["a"] = Json::UInt(0);
+
820 b["a"] = Json::Int(0);
+
821 testEquals("zero");
+
822
+
823 b["a"] = Json::Int(-1);
+
824 testGreaterThan("negative");
825
-
826 b["a"] = Json::Int(-1);
-
827 testGreaterThan("negative");
-
828
- -
830 Json::UInt bigger = big;
-
831 bigger++;
-
832
-
833 a["a"] = bigger;
-
834 b["a"] = big;
-
835 testGreaterThan("big");
-
836}
+ +
827 Json::UInt bigger = big;
+
828 bigger++;
+
829
+
830 a["a"] = bigger;
+
831 b["a"] = big;
+
832 testGreaterThan("big");
+
833}
-
837
-
-
838TEST_CASE("compact")
-
839{
-
840 Json::Value j;
-
841 Json::Reader r;
-
842 char const* s("{\"array\":[{\"12\":23},{},null,false,0.5]}");
-
843
-
844 auto countLines = [](std::string const& str) {
-
845 return 1 + std::count_if(str.begin(), str.end(), [](char c) {
-
846 return c == '\n';
-
847 });
-
848 };
-
849
-
850 CHECK(r.parse(s, j));
-
851 {
- -
853 ss << j;
-
854 CHECK(countLines(ss.str()) > 1);
-
855 }
-
856 {
- -
858 ss << Json::Compact(std::move(j));
-
859 CHECK(countLines(ss.str()) == 1);
-
860 }
-
861}
+
834
+
+
835TEST(json_value, compact)
+
836{
+
837 Json::Value j;
+
838 Json::Reader r;
+
839 char const* s("{\"array\":[{\"12\":23},{},null,false,0.5]}");
+
840
+
841 auto countLines = [](std::string const& str) {
+
842 return 1 + std::count_if(str.begin(), str.end(), [](char c) {
+
843 return c == '\n';
+
844 });
+
845 };
+
846
+
847 EXPECT_TRUE(r.parse(s, j));
+
848 {
+ +
850 ss << j;
+
851 EXPECT_GT(countLines(ss.str()), 1);
+
852 }
+
853 {
+ +
855 ss << Json::Compact(std::move(j));
+
856 EXPECT_EQ(countLines(ss.str()), 1);
+
857 }
+
858}
-
862
-
-
863TEST_CASE("conversions")
-
864{
-
865 // We have Json::Int, but not Json::Double or Json::Real.
-
866 // We have Json::Int, Json::Value::Int, and Json::ValueType::intValue.
-
867 // We have Json::ValueType::realValue but Json::Value::asDouble.
-
868 // TODO: What's the thinking here?
-
869 {
-
870 // null
-
871 Json::Value val;
-
872 CHECK(val.isNull());
-
873 // val.asCString() should trigger an assertion failure
-
874 CHECK(val.asString() == "");
-
875 CHECK(val.asInt() == 0);
-
876 CHECK(val.asUInt() == 0);
-
877 CHECK(val.asAbsUInt() == 0);
-
878 CHECK(val.asDouble() == 0.0);
-
879 CHECK(val.asBool() == false);
-
880
- - - - - - - - -
889 }
-
890 {
-
891 // int
-
892 Json::Value val = -1234;
-
893 CHECK(val.isInt());
-
894 // val.asCString() should trigger an assertion failure
-
895 CHECK(val.asString() == "-1234");
-
896 CHECK(val.asInt() == -1234);
-
897 CHECK_THROWS_AS(val.asUInt(), Json::error);
-
898 CHECK(val.asAbsUInt() == 1234u);
-
899 CHECK(val.asDouble() == -1234.0);
-
900 CHECK(val.asBool() == true);
-
901
- - - - - - - - -
910 }
-
911 {
-
912 // uint
-
913 Json::Value val = 1234U;
-
914 CHECK(val.isUInt());
-
915 // val.asCString() should trigger an assertion failure
-
916 CHECK(val.asString() == "1234");
-
917 CHECK(val.asInt() == 1234);
-
918 CHECK(val.asUInt() == 1234u);
-
919 CHECK(val.asAbsUInt() == 1234u);
-
920 CHECK(val.asDouble() == 1234.0);
-
921 CHECK(val.asBool() == true);
-
922
- - - - - - - - -
931 }
-
932 {
-
933 // real
-
934 Json::Value val = 2.0;
-
935 CHECK(val.isDouble());
-
936 // val.asCString() should trigger an assertion failure
-
937 CHECK(std::regex_match(val.asString(), std::regex("^2\\.0*$")));
-
938 CHECK(val.asInt() == 2);
-
939 CHECK(val.asUInt() == 2u);
-
940 CHECK(val.asAbsUInt() == 2u);
-
941 CHECK(val.asDouble() == 2.0);
-
942 CHECK(val.asBool() == true);
-
943
- - - - - - - - -
952 }
-
953 {
-
954 // numeric string
-
955 Json::Value val = "54321";
-
956 CHECK(val.isString());
-
957 CHECK(strcmp(val.asCString(), "54321") == 0);
-
958 CHECK(val.asString() == "54321");
-
959 CHECK(val.asInt() == 54321);
-
960 CHECK(val.asUInt() == 54321u);
-
961 CHECK(val.asAbsUInt() == 54321);
-
962 CHECK_THROWS_AS(val.asDouble(), Json::error);
-
963 CHECK(val.asBool() == true);
-
964
- - - - - - - - -
973 }
-
974 {
-
975 // non-numeric string
- -
977 CHECK(val.isString());
-
978 CHECK(val.asCString() == nullptr);
-
979 CHECK(val.asString() == "");
-
980 CHECK_THROWS_AS(val.asInt(), std::exception);
-
981 CHECK_THROWS_AS(val.asUInt(), std::exception);
-
982 CHECK_THROWS_AS(val.asAbsUInt(), std::exception);
-
983 CHECK_THROWS_AS(val.asDouble(), std::exception);
-
984 CHECK(val.asBool() == false);
-
985
- - - - - - - - -
994 }
-
995 {
-
996 // bool false
-
997 Json::Value val = false;
-
998 CHECK(val.isBool());
-
999 // val.asCString() should trigger an assertion failure
-
1000 CHECK(val.asString() == "false");
-
1001 CHECK(val.asInt() == 0);
-
1002 CHECK(val.asUInt() == 0);
-
1003 CHECK(val.asAbsUInt() == 0);
-
1004 CHECK(val.asDouble() == 0.0);
-
1005 CHECK(val.asBool() == false);
-
1006
- - - - - - - - -
1015 }
-
1016 {
-
1017 // bool true
-
1018 Json::Value val = true;
-
1019 CHECK(val.isBool());
-
1020 // val.asCString() should trigger an assertion failure
-
1021 CHECK(val.asString() == "true");
-
1022 CHECK(val.asInt() == 1);
-
1023 CHECK(val.asUInt() == 1);
-
1024 CHECK(val.asAbsUInt() == 1);
-
1025 CHECK(val.asDouble() == 1.0);
-
1026 CHECK(val.asBool() == true);
-
1027
- - - - - - - - -
1036 }
-
1037 {
-
1038 // array type
- -
1040 CHECK(val.isArray());
-
1041 // val.asCString should trigger an assertion failure
-
1042 CHECK_THROWS_AS(val.asString(), Json::error);
-
1043 CHECK_THROWS_AS(val.asInt(), Json::error);
-
1044 CHECK_THROWS_AS(val.asUInt(), Json::error);
-
1045 CHECK_THROWS_AS(val.asAbsUInt(), Json::error);
-
1046 CHECK_THROWS_AS(val.asDouble(), Json::error);
-
1047 CHECK(val.asBool() == false); // empty or not
-
1048
- - - - - - - - -
1057 }
-
1058 {
-
1059 // object type
- -
1061 CHECK(val.isObject());
-
1062 // val.asCString should trigger an assertion failure
-
1063 CHECK_THROWS_AS(val.asString(), Json::error);
-
1064 CHECK_THROWS_AS(val.asInt(), Json::error);
-
1065 CHECK_THROWS_AS(val.asUInt(), Json::error);
-
1066 CHECK_THROWS_AS(val.asAbsUInt(), Json::error);
-
1067 CHECK_THROWS_AS(val.asDouble(), Json::error);
-
1068 CHECK(val.asBool() == false); // empty or not
-
1069
- - - - - - - - -
1078 }
-
1079}
+
859
+
+
860TEST(json_value, conversions)
+
861{
+
862 // We have Json::Int, but not Json::Double or Json::Real.
+
863 // We have Json::Int, Json::Value::Int, and Json::ValueType::intValue.
+
864 // We have Json::ValueType::realValue but Json::Value::asDouble.
+
865 // TODO: What's the thinking here?
+
866 {
+
867 // null
+
868 Json::Value val;
+
869 EXPECT_TRUE(val.isNull());
+
870 // val.asCString() should trigger an assertion failure
+
871 EXPECT_EQ(val.asString(), "");
+
872 EXPECT_EQ(val.asInt(), 0);
+
873 EXPECT_EQ(val.asUInt(), 0);
+
874 EXPECT_EQ(val.asAbsUInt(), 0);
+
875 EXPECT_EQ(val.asDouble(), 0.0);
+
876 EXPECT_FALSE(val.asBool());
+
877
+
878 EXPECT_TRUE(val.isConvertibleTo(Json::nullValue));
+
879 EXPECT_TRUE(val.isConvertibleTo(Json::intValue));
+
880 EXPECT_TRUE(val.isConvertibleTo(Json::uintValue));
+
881 EXPECT_TRUE(val.isConvertibleTo(Json::realValue));
+
882 EXPECT_TRUE(val.isConvertibleTo(Json::stringValue));
+
883 EXPECT_TRUE(val.isConvertibleTo(Json::booleanValue));
+
884 EXPECT_TRUE(val.isConvertibleTo(Json::arrayValue));
+
885 EXPECT_TRUE(val.isConvertibleTo(Json::objectValue));
+
886 }
+
887 {
+
888 // int
+
889 Json::Value val = -1234;
+
890 EXPECT_TRUE(val.isInt());
+
891 // val.asCString() should trigger an assertion failure
+
892 EXPECT_EQ(val.asString(), "-1234");
+
893 EXPECT_EQ(val.asInt(), -1234);
+
894 EXPECT_THROW(val.asUInt(), Json::error);
+
895 EXPECT_EQ(val.asAbsUInt(), 1234u);
+
896 EXPECT_EQ(val.asDouble(), -1234.0);
+
897 EXPECT_TRUE(val.asBool());
+
898
+
899 EXPECT_FALSE(val.isConvertibleTo(Json::nullValue));
+
900 EXPECT_TRUE(val.isConvertibleTo(Json::intValue));
+
901 EXPECT_FALSE(val.isConvertibleTo(Json::uintValue));
+
902 EXPECT_TRUE(val.isConvertibleTo(Json::realValue));
+
903 EXPECT_TRUE(val.isConvertibleTo(Json::stringValue));
+
904 EXPECT_TRUE(val.isConvertibleTo(Json::booleanValue));
+
905 EXPECT_FALSE(val.isConvertibleTo(Json::arrayValue));
+
906 EXPECT_FALSE(val.isConvertibleTo(Json::objectValue));
+
907 }
+
908 {
+
909 // uint
+
910 Json::Value val = 1234U;
+
911 EXPECT_TRUE(val.isUInt());
+
912 // val.asCString() should trigger an assertion failure
+
913 EXPECT_EQ(val.asString(), "1234");
+
914 EXPECT_EQ(val.asInt(), 1234);
+
915 EXPECT_EQ(val.asUInt(), 1234u);
+
916 EXPECT_EQ(val.asAbsUInt(), 1234u);
+
917 EXPECT_EQ(val.asDouble(), 1234.0);
+
918 EXPECT_TRUE(val.asBool());
+
919
+
920 EXPECT_FALSE(val.isConvertibleTo(Json::nullValue));
+
921 EXPECT_TRUE(val.isConvertibleTo(Json::intValue));
+
922 EXPECT_TRUE(val.isConvertibleTo(Json::uintValue));
+
923 EXPECT_TRUE(val.isConvertibleTo(Json::realValue));
+
924 EXPECT_TRUE(val.isConvertibleTo(Json::stringValue));
+
925 EXPECT_TRUE(val.isConvertibleTo(Json::booleanValue));
+
926 EXPECT_FALSE(val.isConvertibleTo(Json::arrayValue));
+
927 EXPECT_FALSE(val.isConvertibleTo(Json::objectValue));
+
928 }
+
929 {
+
930 // real
+
931 Json::Value val = 2.0;
+
932 EXPECT_TRUE(val.isDouble());
+
933 // val.asCString() should trigger an assertion failure
+
934 EXPECT_TRUE(std::regex_match(val.asString(), std::regex("^2\\.0*$")));
+
935 EXPECT_EQ(val.asInt(), 2);
+
936 EXPECT_EQ(val.asUInt(), 2u);
+
937 EXPECT_EQ(val.asAbsUInt(), 2u);
+
938 EXPECT_EQ(val.asDouble(), 2.0);
+
939 EXPECT_TRUE(val.asBool());
+
940
+
941 EXPECT_FALSE(val.isConvertibleTo(Json::nullValue));
+
942 EXPECT_TRUE(val.isConvertibleTo(Json::intValue));
+
943 EXPECT_TRUE(val.isConvertibleTo(Json::uintValue));
+
944 EXPECT_TRUE(val.isConvertibleTo(Json::realValue));
+
945 EXPECT_TRUE(val.isConvertibleTo(Json::stringValue));
+
946 EXPECT_TRUE(val.isConvertibleTo(Json::booleanValue));
+
947 EXPECT_FALSE(val.isConvertibleTo(Json::arrayValue));
+
948 EXPECT_FALSE(val.isConvertibleTo(Json::objectValue));
+
949 }
+
950 {
+
951 // numeric string
+
952 Json::Value val = "54321";
+
953 EXPECT_TRUE(val.isString());
+
954 EXPECT_EQ(strcmp(val.asCString(), "54321"), 0);
+
955 EXPECT_EQ(val.asString(), "54321");
+
956 EXPECT_EQ(val.asInt(), 54321);
+
957 EXPECT_EQ(val.asUInt(), 54321u);
+
958 EXPECT_EQ(val.asAbsUInt(), 54321);
+
959 EXPECT_THROW(val.asDouble(), Json::error);
+
960 EXPECT_TRUE(val.asBool());
+
961
+
962 EXPECT_FALSE(val.isConvertibleTo(Json::nullValue));
+
963 EXPECT_FALSE(val.isConvertibleTo(Json::intValue));
+
964 EXPECT_FALSE(val.isConvertibleTo(Json::uintValue));
+
965 EXPECT_FALSE(val.isConvertibleTo(Json::realValue));
+
966 EXPECT_TRUE(val.isConvertibleTo(Json::stringValue));
+
967 EXPECT_FALSE(val.isConvertibleTo(Json::booleanValue));
+
968 EXPECT_FALSE(val.isConvertibleTo(Json::arrayValue));
+
969 EXPECT_FALSE(val.isConvertibleTo(Json::objectValue));
+
970 }
+
971 {
+
972 // non-numeric string
+ +
974 EXPECT_TRUE(val.isString());
+
975 EXPECT_EQ(val.asCString(), nullptr);
+
976 EXPECT_EQ(val.asString(), "");
+
977 EXPECT_THROW(val.asInt(), std::exception);
+
978 EXPECT_THROW(val.asUInt(), std::exception);
+
979 EXPECT_THROW(val.asAbsUInt(), std::exception);
+
980 EXPECT_THROW(val.asDouble(), std::exception);
+
981 EXPECT_TRUE(val.asBool() == false);
+
982
+
983 EXPECT_TRUE(val.isConvertibleTo(Json::nullValue));
+
984 EXPECT_FALSE(val.isConvertibleTo(Json::intValue));
+
985 EXPECT_FALSE(val.isConvertibleTo(Json::uintValue));
+
986 EXPECT_FALSE(val.isConvertibleTo(Json::realValue));
+
987 EXPECT_TRUE(val.isConvertibleTo(Json::stringValue));
+
988 EXPECT_FALSE(val.isConvertibleTo(Json::booleanValue));
+
989 EXPECT_FALSE(val.isConvertibleTo(Json::arrayValue));
+
990 EXPECT_FALSE(val.isConvertibleTo(Json::objectValue));
+
991 }
+
992 {
+
993 // bool false
+
994 Json::Value val = false;
+
995 EXPECT_TRUE(val.isBool());
+
996 // val.asCString() should trigger an assertion failure
+
997 EXPECT_EQ(val.asString(), "false");
+
998 EXPECT_EQ(val.asInt(), 0);
+
999 EXPECT_EQ(val.asUInt(), 0);
+
1000 EXPECT_EQ(val.asAbsUInt(), 0);
+
1001 EXPECT_EQ(val.asDouble(), 0.0);
+
1002 EXPECT_FALSE(val.asBool());
+
1003
+
1004 EXPECT_TRUE(val.isConvertibleTo(Json::nullValue));
+
1005 EXPECT_TRUE(val.isConvertibleTo(Json::intValue));
+
1006 EXPECT_TRUE(val.isConvertibleTo(Json::uintValue));
+
1007 EXPECT_TRUE(val.isConvertibleTo(Json::realValue));
+
1008 EXPECT_TRUE(val.isConvertibleTo(Json::stringValue));
+
1009 EXPECT_TRUE(val.isConvertibleTo(Json::booleanValue));
+
1010 EXPECT_FALSE(val.isConvertibleTo(Json::arrayValue));
+
1011 EXPECT_FALSE(val.isConvertibleTo(Json::objectValue));
+
1012 }
+
1013 {
+
1014 // bool true
+
1015 Json::Value val = true;
+
1016 EXPECT_TRUE(val.isBool());
+
1017 // val.asCString() should trigger an assertion failure
+
1018 EXPECT_EQ(val.asString(), "true");
+
1019 EXPECT_EQ(val.asInt(), 1);
+
1020 EXPECT_EQ(val.asUInt(), 1);
+
1021 EXPECT_EQ(val.asAbsUInt(), 1);
+
1022 EXPECT_EQ(val.asDouble(), 1.0);
+
1023 EXPECT_TRUE(val.asBool());
+
1024
+
1025 EXPECT_FALSE(val.isConvertibleTo(Json::nullValue));
+
1026 EXPECT_TRUE(val.isConvertibleTo(Json::intValue));
+
1027 EXPECT_TRUE(val.isConvertibleTo(Json::uintValue));
+
1028 EXPECT_TRUE(val.isConvertibleTo(Json::realValue));
+
1029 EXPECT_TRUE(val.isConvertibleTo(Json::stringValue));
+
1030 EXPECT_TRUE(val.isConvertibleTo(Json::booleanValue));
+
1031 EXPECT_FALSE(val.isConvertibleTo(Json::arrayValue));
+
1032 EXPECT_FALSE(val.isConvertibleTo(Json::objectValue));
+
1033 }
+
1034 {
+
1035 // array type
+ +
1037 EXPECT_TRUE(val.isArray());
+
1038 // val.asCString should trigger an assertion failure
+
1039 EXPECT_THROW(val.asString(), Json::error);
+
1040 EXPECT_THROW(val.asInt(), Json::error);
+
1041 EXPECT_THROW(val.asUInt(), Json::error);
+
1042 EXPECT_THROW(val.asAbsUInt(), Json::error);
+
1043 EXPECT_THROW(val.asDouble(), Json::error);
+
1044 EXPECT_FALSE(val.asBool()); // empty or not
+
1045
+
1046 EXPECT_TRUE(val.isConvertibleTo(Json::nullValue));
+
1047 EXPECT_FALSE(val.isConvertibleTo(Json::intValue));
+
1048 EXPECT_FALSE(val.isConvertibleTo(Json::uintValue));
+
1049 EXPECT_FALSE(val.isConvertibleTo(Json::realValue));
+
1050 EXPECT_FALSE(val.isConvertibleTo(Json::stringValue));
+
1051 EXPECT_FALSE(val.isConvertibleTo(Json::booleanValue));
+
1052 EXPECT_TRUE(val.isConvertibleTo(Json::arrayValue));
+
1053 EXPECT_FALSE(val.isConvertibleTo(Json::objectValue));
+
1054 }
+
1055 {
+
1056 // object type
+ +
1058 EXPECT_TRUE(val.isObject());
+
1059 // val.asCString should trigger an assertion failure
+
1060 EXPECT_THROW(val.asString(), Json::error);
+
1061 EXPECT_THROW(val.asInt(), Json::error);
+
1062 EXPECT_THROW(val.asUInt(), Json::error);
+
1063 EXPECT_THROW(val.asAbsUInt(), Json::error);
+
1064 EXPECT_THROW(val.asDouble(), Json::error);
+
1065 EXPECT_FALSE(val.asBool()); // empty or not
+
1066
+
1067 EXPECT_TRUE(val.isConvertibleTo(Json::nullValue));
+
1068 EXPECT_FALSE(val.isConvertibleTo(Json::intValue));
+
1069 EXPECT_FALSE(val.isConvertibleTo(Json::uintValue));
+
1070 EXPECT_FALSE(val.isConvertibleTo(Json::realValue));
+
1071 EXPECT_FALSE(val.isConvertibleTo(Json::stringValue));
+
1072 EXPECT_FALSE(val.isConvertibleTo(Json::booleanValue));
+
1073 EXPECT_FALSE(val.isConvertibleTo(Json::arrayValue));
+
1074 EXPECT_TRUE(val.isConvertibleTo(Json::objectValue));
+
1075 }
+
1076}
-
1080
-
-
1081TEST_CASE("access members")
-
1082{
-
1083 Json::Value val;
-
1084 CHECK(val.type() == Json::nullValue);
-
1085 CHECK(val.size() == 0);
-
1086 CHECK(!val.isValidIndex(0));
-
1087 CHECK(!val.isMember("key"));
-
1088 {
-
1089 Json::Value const constVal = val;
-
1090 CHECK(constVal[7u].type() == Json::nullValue);
-
1091 CHECK(!constVal.isMember("key"));
-
1092 CHECK(constVal["key"].type() == Json::nullValue);
-
1093 CHECK(constVal.getMemberNames().empty());
-
1094 CHECK(constVal.get(1u, "default0") == "default0");
-
1095 CHECK(constVal.get(std::string("not"), "oh") == "oh");
-
1096 CHECK(constVal.get("missing", "default2") == "default2");
-
1097 }
-
1098
-
1099 val = -7;
-
1100 CHECK(val.type() == Json::intValue);
-
1101 CHECK(val.size() == 0);
-
1102 CHECK(!val.isValidIndex(0));
-
1103 CHECK(!val.isMember("key"));
-
1104
-
1105 val = 42u;
-
1106 CHECK(val.type() == Json::uintValue);
-
1107 CHECK(val.size() == 0);
-
1108 CHECK(!val.isValidIndex(0));
-
1109 CHECK(!val.isMember("key"));
-
1110
-
1111 val = 3.14159;
-
1112 CHECK(val.type() == Json::realValue);
-
1113 CHECK(val.size() == 0);
-
1114 CHECK(!val.isValidIndex(0));
-
1115 CHECK(!val.isMember("key"));
-
1116
-
1117 val = true;
-
1118 CHECK(val.type() == Json::booleanValue);
-
1119 CHECK(val.size() == 0);
-
1120 CHECK(!val.isValidIndex(0));
-
1121 CHECK(!val.isMember("key"));
-
1122
-
1123 val = "string";
-
1124 CHECK(val.type() == Json::stringValue);
-
1125 CHECK(val.size() == 0);
-
1126 CHECK(!val.isValidIndex(0));
-
1127 CHECK(!val.isMember("key"));
-
1128
- -
1130 CHECK(val.type() == Json::objectValue);
-
1131 CHECK(val.size() == 0);
-
1132 static Json::StaticString const staticThree("three");
-
1133 val[staticThree] = 3;
-
1134 val["two"] = 2;
-
1135 CHECK(val.size() == 2);
-
1136 CHECK(val.isValidIndex(1));
-
1137 CHECK(!val.isValidIndex(2));
-
1138 CHECK(val[staticThree] == 3);
-
1139 CHECK(val.isMember("two"));
-
1140 CHECK(val.isMember(staticThree));
-
1141 CHECK(!val.isMember("key"));
-
1142 {
-
1143 Json::Value const constVal = val;
-
1144 CHECK(constVal["two"] == 2);
-
1145 CHECK(constVal["four"].type() == Json::nullValue);
-
1146 CHECK(constVal[staticThree] == 3);
-
1147 CHECK(constVal.isMember("two"));
-
1148 CHECK(constVal.isMember(staticThree));
-
1149 CHECK(!constVal.isMember("key"));
-
1150 CHECK(val.get(std::string("two"), "backup") == 2);
-
1151 CHECK(val.get("missing", "default2") == "default2");
-
1152 }
-
1153
- -
1155 CHECK(val.type() == Json::arrayValue);
-
1156 CHECK(val.size() == 0);
-
1157 val[0u] = "zero";
-
1158 val[1u] = "one";
-
1159 CHECK(val.size() == 2);
-
1160 CHECK(val.isValidIndex(1));
-
1161 CHECK(!val.isValidIndex(2));
-
1162 CHECK(val[20u].type() == Json::nullValue);
-
1163 CHECK(!val.isMember("key"));
-
1164 {
-
1165 Json::Value const constVal = val;
-
1166 CHECK(constVal[0u] == "zero");
-
1167 CHECK(constVal[2u].type() == Json::nullValue);
-
1168 CHECK(!constVal.isMember("key"));
-
1169 CHECK(val.get(1u, "default0") == "one");
-
1170 CHECK(val.get(3u, "default1") == "default1");
-
1171 }
-
1172}
+
1077
+
+
1078TEST(json_value, access_members)
+
1079{
+
1080 Json::Value val;
+
1081 EXPECT_EQ(val.type(), Json::nullValue);
+
1082 EXPECT_EQ(val.size(), 0);
+
1083 EXPECT_FALSE(val.isValidIndex(0));
+
1084 EXPECT_FALSE(val.isMember("key"));
+
1085 {
+
1086 Json::Value const constVal = val;
+
1087 EXPECT_EQ(constVal[7u].type(), Json::nullValue);
+
1088 EXPECT_FALSE(constVal.isMember("key"));
+
1089 EXPECT_EQ(constVal["key"].type(), Json::nullValue);
+
1090 EXPECT_TRUE(constVal.getMemberNames().empty());
+
1091 EXPECT_EQ(constVal.get(1u, "default0"), "default0");
+
1092 EXPECT_EQ(constVal.get(std::string("not"), "oh"), "oh");
+
1093 EXPECT_EQ(constVal.get("missing", "default2"), "default2");
+
1094 }
+
1095
+
1096 val = -7;
+
1097 EXPECT_EQ(val.type(), Json::intValue);
+
1098 EXPECT_EQ(val.size(), 0);
+
1099 EXPECT_FALSE(val.isValidIndex(0));
+
1100 EXPECT_FALSE(val.isMember("key"));
+
1101
+
1102 val = 42u;
+
1103 EXPECT_EQ(val.type(), Json::uintValue);
+
1104 EXPECT_EQ(val.size(), 0);
+
1105 EXPECT_FALSE(val.isValidIndex(0));
+
1106 EXPECT_FALSE(val.isMember("key"));
+
1107
+
1108 val = 3.14159;
+
1109 EXPECT_EQ(val.type(), Json::realValue);
+
1110 EXPECT_EQ(val.size(), 0);
+
1111 EXPECT_FALSE(val.isValidIndex(0));
+
1112 EXPECT_FALSE(val.isMember("key"));
+
1113
+
1114 val = true;
+
1115 EXPECT_EQ(val.type(), Json::booleanValue);
+
1116 EXPECT_EQ(val.size(), 0);
+
1117 EXPECT_FALSE(val.isValidIndex(0));
+
1118 EXPECT_FALSE(val.isMember("key"));
+
1119
+
1120 val = "string";
+
1121 EXPECT_EQ(val.type(), Json::stringValue);
+
1122 EXPECT_EQ(val.size(), 0);
+
1123 EXPECT_FALSE(val.isValidIndex(0));
+
1124 EXPECT_FALSE(val.isMember("key"));
+
1125
+ +
1127 EXPECT_EQ(val.type(), Json::objectValue);
+
1128 EXPECT_EQ(val.size(), 0);
+
1129 static Json::StaticString const staticThree("three");
+
1130 val[staticThree] = 3;
+
1131 val["two"] = 2;
+
1132 EXPECT_EQ(val.size(), 2);
+
1133 EXPECT_TRUE(val.isValidIndex(1));
+
1134 EXPECT_FALSE(val.isValidIndex(2));
+
1135 EXPECT_EQ(val[staticThree], 3);
+
1136 EXPECT_TRUE(val.isMember("two"));
+
1137 EXPECT_TRUE(val.isMember(staticThree));
+
1138 EXPECT_FALSE(val.isMember("key"));
+
1139 {
+
1140 Json::Value const constVal = val;
+
1141 EXPECT_EQ(constVal["two"], 2);
+
1142 EXPECT_EQ(constVal["four"].type(), Json::nullValue);
+
1143 EXPECT_EQ(constVal[staticThree], 3);
+
1144 EXPECT_TRUE(constVal.isMember("two"));
+
1145 EXPECT_TRUE(constVal.isMember(staticThree));
+
1146 EXPECT_FALSE(constVal.isMember("key"));
+
1147 EXPECT_EQ(val.get(std::string("two"), "backup"), 2);
+
1148 EXPECT_EQ(val.get("missing", "default2"), "default2");
+
1149 }
+
1150
+ +
1152 EXPECT_EQ(val.type(), Json::arrayValue);
+
1153 EXPECT_EQ(val.size(), 0);
+
1154 val[0u] = "zero";
+
1155 val[1u] = "one";
+
1156 EXPECT_EQ(val.size(), 2);
+
1157 EXPECT_TRUE(val.isValidIndex(1));
+
1158 EXPECT_FALSE(val.isValidIndex(2));
+
1159 EXPECT_EQ(val[20u].type(), Json::nullValue);
+
1160 EXPECT_FALSE(val.isMember("key"));
+
1161 {
+
1162 Json::Value const constVal = val;
+
1163 EXPECT_EQ(constVal[0u], "zero");
+
1164 EXPECT_EQ(constVal[2u].type(), Json::nullValue);
+
1165 EXPECT_FALSE(constVal.isMember("key"));
+
1166 EXPECT_EQ(val.get(1u, "default0"), "one");
+
1167 EXPECT_EQ(val.get(3u, "default1"), "default1");
+
1168 }
+
1169}
-
1173
-
-
1174TEST_CASE("remove members")
-
1175{
-
1176 Json::Value val;
-
1177 CHECK(val.removeMember(std::string("member")).type() == Json::nullValue);
-
1178
- -
1180 static Json::StaticString const staticThree("three");
-
1181 val[staticThree] = 3;
-
1182 val["two"] = 2;
-
1183 CHECK(val.size() == 2);
+
1170
+
+
1171TEST(json_value, remove_members)
+
1172{
+
1173 Json::Value val;
+
1174 EXPECT_EQ(val.removeMember(std::string("member")).type(), Json::nullValue);
+
1175
+ +
1177 static Json::StaticString const staticThree("three");
+
1178 val[staticThree] = 3;
+
1179 val["two"] = 2;
+
1180 EXPECT_EQ(val.size(), 2);
+
1181
+
1182 EXPECT_EQ(val.removeMember(std::string("six")).type(), Json::nullValue);
+
1183 EXPECT_EQ(val.size(), 2);
1184
- -
1186 CHECK(val.size() == 2);
+
1185 EXPECT_EQ(val.removeMember(staticThree), 3);
+
1186 EXPECT_EQ(val.size(), 1);
1187
-
1188 CHECK(val.removeMember(staticThree) == 3);
-
1189 CHECK(val.size() == 1);
+
1188 EXPECT_EQ(val.removeMember(staticThree).type(), Json::nullValue);
+
1189 EXPECT_EQ(val.size(), 1);
1190
-
1191 CHECK(val.removeMember(staticThree).type() == Json::nullValue);
-
1192 CHECK(val.size() == 1);
+
1191 EXPECT_EQ(val.removeMember(std::string("two")), 2);
+
1192 EXPECT_EQ(val.size(), 0);
1193
-
1194 CHECK(val.removeMember(std::string("two")) == 2);
-
1195 CHECK(val.size() == 0);
-
1196
- -
1198 CHECK(val.size() == 0);
-
1199}
+
1194 EXPECT_EQ(val.removeMember(std::string("two")).type(), Json::nullValue);
+
1195 EXPECT_EQ(val.size(), 0);
+
1196}
-
1200
-
-
1201TEST_CASE("iterator")
-
1202{
-
1203 {
-
1204 // Iterating an array.
- -
1206 arr[0u] = "zero";
-
1207 arr[1u] = "one";
-
1208 arr[2u] = "two";
-
1209 arr[3u] = "three";
+
1197
+
+
1198TEST(json_value, iterator)
+
1199{
+
1200 {
+
1201 // Iterating an array.
+ +
1203 arr[0u] = "zero";
+
1204 arr[1u] = "one";
+
1205 arr[2u] = "two";
+
1206 arr[3u] = "three";
+
1207
+
1208 Json::ValueIterator const b{arr.begin()};
+
1209 Json::ValueIterator const e{arr.end()};
1210
-
1211 Json::ValueIterator const b{arr.begin()};
-
1212 Json::ValueIterator const e{arr.end()};
-
1213
-
1214 Json::ValueIterator i1 = b;
-
1215 Json::ValueIterator i2 = e;
-
1216 --i2;
-
1217
-
1218 // key(), index(), and memberName() on an object iterator.
-
1219 CHECK(b != e);
-
1220 CHECK(!(b == e));
-
1221 CHECK(i1.key() == 0);
-
1222 CHECK(i2.key() == 3);
-
1223 CHECK(i1.index() == 0);
-
1224 CHECK(i2.index() == 3);
-
1225 CHECK(std::strcmp(i1.memberName(), "") == 0);
-
1226 CHECK(std::strcmp(i2.memberName(), "") == 0);
-
1227
-
1228 // Pre and post increment and decrement.
-
1229 *i1++ = "0";
-
1230 CHECK(*i1 == "one");
-
1231 *i1 = "1";
-
1232 ++i1;
-
1233
-
1234 *i2-- = "3";
-
1235 CHECK(*i2 == "two");
-
1236 CHECK(i1 == i2);
-
1237 *i2 = "2";
-
1238 CHECK(*i1 == "2");
-
1239 }
-
1240 {
-
1241 // Iterating a const object.
-
1242 Json::Value const obj{[]() {
- -
1244 obj["0"] = 0;
-
1245 obj["1"] = 1;
-
1246 obj["2"] = 2;
-
1247 obj["3"] = 3;
-
1248 return obj;
-
1249 }()};
-
1250
-
1251 Json::ValueConstIterator i1{obj.begin()};
-
1252 Json::ValueConstIterator i2{obj.end()};
-
1253 --i2;
-
1254
-
1255 // key(), index(), and memberName() on an object iterator.
-
1256 CHECK(i1 != i2);
-
1257 CHECK(!(i1 == i2));
-
1258 CHECK(i1.key() == "0");
-
1259 CHECK(i2.key() == "3");
-
1260 CHECK(i1.index() == -1);
-
1261 CHECK(i2.index() == -1);
-
1262 CHECK(std::strcmp(i1.memberName(), "0") == 0);
-
1263 CHECK(std::strcmp(i2.memberName(), "3") == 0);
-
1264
-
1265 // Pre and post increment and decrement.
-
1266 CHECK(*i1++ == 0);
-
1267 CHECK(*i1 == 1);
-
1268 ++i1;
-
1269
-
1270 CHECK(*i2-- == 3);
-
1271 CHECK(*i2 == 2);
-
1272 CHECK(i1 == i2);
-
1273 CHECK(*i1 == 2);
-
1274 }
-
1275 {
-
1276 // Iterating a non-const null object.
-
1277 Json::Value nul{};
-
1278 CHECK(nul.begin() == nul.end());
-
1279 }
-
1280 {
-
1281 // Iterating a const Int.
-
1282 Json::Value const i{-3};
-
1283 CHECK(i.begin() == i.end());
-
1284 }
-
1285}
+
1211 Json::ValueIterator i1 = b;
+
1212 Json::ValueIterator i2 = e;
+
1213 --i2;
+
1214
+
1215 // key(), index(), and memberName() on an array iterator.
+
1216 EXPECT_TRUE(b != e);
+
1217 EXPECT_FALSE(b == e);
+
1218 EXPECT_EQ(i1.key(), 0);
+
1219 EXPECT_EQ(i2.key(), 3);
+
1220 EXPECT_EQ(i1.index(), 0);
+
1221 EXPECT_EQ(i2.index(), 3);
+
1222 EXPECT_STREQ(i1.memberName(), "");
+
1223 EXPECT_STREQ(i2.memberName(), "");
+
1224
+
1225 // Pre and post increment and decrement.
+
1226 *i1++ = "0";
+
1227 EXPECT_EQ(*i1, "one");
+
1228 *i1 = "1";
+
1229 ++i1;
+
1230
+
1231 *i2-- = "3";
+
1232 EXPECT_EQ(*i2, "two");
+
1233 EXPECT_EQ(i1, i2);
+
1234 *i2 = "2";
+
1235 EXPECT_EQ(*i1, "2");
+
1236 }
+
1237 {
+
1238 // Iterating a const object.
+
1239 Json::Value const obj{[]() {
+ +
1241 obj["0"] = 0;
+
1242 obj["1"] = 1;
+
1243 obj["2"] = 2;
+
1244 obj["3"] = 3;
+
1245 return obj;
+
1246 }()};
+
1247
+
1248 Json::ValueConstIterator i1{obj.begin()};
+
1249 Json::ValueConstIterator i2{obj.end()};
+
1250 --i2;
+
1251
+
1252 // key(), index(), and memberName() on an object iterator.
+
1253 EXPECT_TRUE(i1 != i2);
+
1254 EXPECT_FALSE(i1 == i2);
+
1255 EXPECT_EQ(i1.key(), "0");
+
1256 EXPECT_EQ(i2.key(), "3");
+
1257 EXPECT_EQ(i1.index(), -1);
+
1258 EXPECT_EQ(i2.index(), -1);
+
1259 EXPECT_STREQ(i1.memberName(), "0");
+
1260 EXPECT_STREQ(i2.memberName(), "3");
+
1261
+
1262 // Pre and post increment and decrement.
+
1263 EXPECT_EQ(*i1++, 0);
+
1264 EXPECT_EQ(*i1, 1);
+
1265 ++i1;
+
1266
+
1267 EXPECT_EQ(*i2--, 3);
+
1268 EXPECT_EQ(*i2, 2);
+
1269 EXPECT_EQ(i1, i2);
+
1270 EXPECT_EQ(*i1, 2);
+
1271 }
+
1272 {
+
1273 // Iterating a non-const null object.
+
1274 Json::Value nul{};
+
1275 EXPECT_EQ(nul.begin(), nul.end());
+
1276 }
+
1277 {
+
1278 // Iterating a const Int.
+
1279 Json::Value const i{-3};
+
1280 EXPECT_EQ(i.begin(), i.end());
+
1281 }
+
1282}
-
1286
-
-
1287TEST_CASE("nest limits")
-
1288{
-
1289 Json::Reader r;
-
1290 {
-
1291 auto nest = [](std::uint32_t depth) -> std::string {
-
1292 std::string s = "{";
-
1293 for (std::uint32_t i{1}; i <= depth; ++i)
-
1294 s += "\"obj\":{";
-
1295 for (std::uint32_t i{1}; i <= depth; ++i)
-
1296 s += "}";
-
1297 s += "}";
-
1298 return s;
-
1299 };
-
1300
-
1301 {
-
1302 // Within object nest limit
-
1303 auto json{nest(std::min(10u, Json::Reader::nest_limit))};
-
1304 Json::Value j;
-
1305 CHECK(r.parse(json, j));
-
1306 }
-
1307
-
1308 {
-
1309 // Exceed object nest limit
-
1310 auto json{nest(Json::Reader::nest_limit + 1)};
-
1311 Json::Value j;
-
1312 CHECK(!r.parse(json, j));
-
1313 }
-
1314 }
-
1315
-
1316 auto nest = [](std::uint32_t depth) -> std::string {
-
1317 std::string s = "{";
-
1318 for (std::uint32_t i{1}; i <= depth; ++i)
-
1319 s += "\"array\":[{";
-
1320 for (std::uint32_t i{1}; i <= depth; ++i)
-
1321 s += "]}";
-
1322 s += "}";
-
1323 return s;
-
1324 };
-
1325 {
-
1326 // Exceed array nest limit
-
1327 auto json{nest(Json::Reader::nest_limit + 1)};
-
1328 Json::Value j;
-
1329 CHECK(!r.parse(json, j));
-
1330 }
-
1331}
+
1283
+
+
1284TEST(json_value, nest_limits)
+
1285{
+
1286 Json::Reader r;
+
1287 {
+
1288 auto nest = [](std::uint32_t depth) -> std::string {
+
1289 std::string s = "{";
+
1290 for (std::uint32_t i{1}; i <= depth; ++i)
+
1291 s += "\"obj\":{";
+
1292 for (std::uint32_t i{1}; i <= depth; ++i)
+
1293 s += "}";
+
1294 s += "}";
+
1295 return s;
+
1296 };
+
1297
+
1298 {
+
1299 // Within object nest limit
+
1300 auto json{nest(std::min(10u, Json::Reader::nest_limit))};
+
1301 Json::Value j;
+
1302 EXPECT_TRUE(r.parse(json, j));
+
1303 }
+
1304
+
1305 {
+
1306 // Exceed object nest limit
+
1307 auto json{nest(Json::Reader::nest_limit + 1)};
+
1308 Json::Value j;
+
1309 EXPECT_FALSE(r.parse(json, j));
+
1310 }
+
1311 }
+
1312
+
1313 auto nest = [](std::uint32_t depth) -> std::string {
+
1314 std::string s = "{";
+
1315 for (std::uint32_t i{1}; i <= depth; ++i)
+
1316 s += "\"array\":[{";
+
1317 for (std::uint32_t i{1}; i <= depth; ++i)
+
1318 s += "]}";
+
1319 s += "}";
+
1320 return s;
+
1321 };
+
1322 {
+
1323 // Exceed array nest limit
+
1324 auto json{nest(Json::Reader::nest_limit + 1)};
+
1325 Json::Value j;
+
1326 EXPECT_FALSE(r.parse(json, j));
+
1327 }
+
1328}
-
1332
-
-
1333TEST_CASE("memory leak")
-
1334{
-
1335 // When run with the address sanitizer, this test confirms there is no
-
1336 // memory leak with the scenarios below.
-
1337 {
-
1338 Json::Value a;
-
1339 a[0u] = 1;
-
1340 CHECK(a.type() == Json::arrayValue);
-
1341 CHECK(a[0u].type() == Json::intValue);
-
1342 a = std::move(a[0u]);
-
1343 CHECK(a.type() == Json::intValue);
-
1344 }
-
1345 {
-
1346 Json::Value b;
-
1347 Json::Value temp;
-
1348 temp["a"] = "Probably avoids the small string optimization";
-
1349 temp["b"] = "Also probably avoids the small string optimization";
-
1350 CHECK(temp.type() == Json::objectValue);
-
1351 b.append(temp);
-
1352 CHECK(temp.type() == Json::objectValue);
-
1353 CHECK(b.size() == 1);
+
1329
+
+
1330TEST(json_value, memory_leak)
+
1331{
+
1332 // When run with the address sanitizer, this test confirms there is no
+
1333 // memory leak with the scenarios below.
+
1334 {
+
1335 Json::Value a;
+
1336 a[0u] = 1;
+
1337 EXPECT_EQ(a.type(), Json::arrayValue);
+
1338 EXPECT_EQ(a[0u].type(), Json::intValue);
+
1339 a = std::move(a[0u]);
+
1340 EXPECT_EQ(a.type(), Json::intValue);
+
1341 }
+
1342 {
+
1343 Json::Value b;
+
1344 Json::Value temp;
+
1345 temp["a"] = "Probably avoids the small string optimization";
+
1346 temp["b"] = "Also probably avoids the small string optimization";
+
1347 EXPECT_EQ(temp.type(), Json::objectValue);
+
1348 b.append(temp);
+
1349 EXPECT_EQ(temp.type(), Json::objectValue);
+
1350 EXPECT_EQ(b.size(), 1);
+
1351
+
1352 b.append(std::move(temp));
+
1353 EXPECT_EQ(b.size(), 2);
1354
-
1355 b.append(std::move(temp));
-
1356 CHECK(b.size() == 2);
-
1357
-
1358 // Note that the type() == nullValue check is implementation
-
1359 // specific and not guaranteed to be valid in the future.
-
1360 CHECK(temp.type() == Json::nullValue);
-
1361 }
-
1362}
+
1355 // Note that the type() == nullValue check is implementation
+
1356 // specific and not guaranteed to be valid in the future.
+
1357 EXPECT_EQ(temp.type(), Json::nullValue);
+
1358 }
+
1359}
-
1363
- -
1365
-
1366} // namespace xrpl
+
1360
+
1361} // namespace xrpl
@@ -1541,15 +1536,11 @@ $(document).ready(function() { init_codefold(0); });
int Int
unsigned int UInt
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
-
TEST_SUITE_BEGIN("json_value")
- -
TEST_SUITE_END()
-
TEST_CASE("limits")
Definition Value.cpp:19
+
TEST(json_value, limits)
Definition Value.cpp:17
T regex_match(T... args)
T str(T... args)
-
T strcmp(T... args)
Thrown when a conversion is not possible with LexicalCast.
diff --git a/Vault__test_8cpp_source.html b/Vault__test_8cpp_source.html index 0718611ab5..fd15f66eb7 100644 --- a/Vault__test_8cpp_source.html +++ b/Vault__test_8cpp_source.html @@ -2175,7 +2175,7 @@ $(document).ready(function() { init_codefold(0); });
2076 PrettyAsset const& asset,
2077 Vault& vault,
2078 MPTTester& mptt) {
-
2079 testcase("MPT failed reserve to re-create MPToken");
+
2079 testcase("MPT fail reserve to re-create MPToken");
2080
2081 auto [tx, keylet] =
2082 vault.create({.owner = owner, .asset = asset});
diff --git a/annotated.html b/annotated.html index 443fc97ff7..a224c0ba4a 100644 --- a/annotated.html +++ b/annotated.html @@ -1755,7 +1755,7 @@ $(function() {  Ctest_sampler  CTag1  CTag2 - CWriterFixture + CWriterFixture
diff --git a/basics_2main_8cpp_source.html b/basics_2main_8cpp_source.html index ee5f3a7eea..77214152dc 100644 --- a/basics_2main_8cpp_source.html +++ b/basics_2main_8cpp_source.html @@ -81,8 +81,14 @@ $(document).ready(function() { init_codefold(0); });
basics/main.cpp
-
1#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
-
2#include <doctest/doctest.h>
+
1#include <gtest/gtest.h>
+
2
+
3int
+
4main(int argc, char** argv)
+
5{
+
6 ::testing::InitGoogleTest(&argc, argv);
+
7 return RUN_ALL_TESTS();
+
8}
-

This is the complete list of members for WriterFixture, including all inherited members.

+

This is the complete list of members for WriterFixture, including all inherited members.

- - - - - - + + + + + +
checkOutputAndReset(std::string const &expected)WriterFixture
expectOutput(std::string const &expected) constWriterFixture
outputWriterFixture
reset()WriterFixture
writerWriterFixture
WriterFixture()WriterFixture
checkOutputAndReset(std::string const &expected)WriterFixtureprotected
expectOutput(std::string const &expected) constWriterFixtureprotected
outputWriterFixtureprotected
reset()WriterFixtureprotected
SetUp() overrideWriterFixtureprotected
writerWriterFixtureprotected
+
WriterFixture Class Reference
+Inheritance diagram for WriterFixture:
+
+
Inheritance graph
+ + + + + +
[legend]
+
Collaboration diagram for WriterFixture:
-
Collaboration graph
+
Collaboration graph
- + + + - + - + @@ -106,53 +118,63 @@ Collaboration diagram for WriterFixture:
[legend]
- - - - + + + + - + - +

-Public Member Functions

 WriterFixture ()
 
void reset ()

+Protected Member Functions

void SetUp () override
 
void reset ()
 
void expectOutput (std::string const &expected) const
void expectOutput (std::string const &expected) const
 
void checkOutputAndReset (std::string const &expected)
void checkOutputAndReset (std::string const &expected)
 
- - + + - +

-Public Attributes

std::string output

+Protected Attributes

std::string output
 
std::unique_ptr< Writerwriter
std::unique_ptr< Writerwriter
 

Detailed Description

-

Definition at line 14 of file tests/libxrpl/json/Writer.cpp.

-

Constructor & Destructor Documentation

- -

◆ WriterFixture()

+

Definition at line 12 of file tests/libxrpl/json/Writer.cpp.

+

Member Function Documentation

+ +

◆ SetUp()

+ + + + + +
- +
WriterFixture::WriterFixture void WriterFixture::SetUp ( )
+
+overrideprotected

Definition at line 19 of file tests/libxrpl/json/Writer.cpp.

-

Member Function Documentation

◆ reset()

+ + + + + +
@@ -161,6 +183,11 @@ Public Attributes
void WriterFixture::reset
+
+protected

Definition at line 25 of file tests/libxrpl/json/Writer.cpp.

@@ -172,6 +199,9 @@ Public Attributes
+ + + + + +
@@ -181,6 +211,11 @@ Public Attributes
void WriterFixture::expectOutput
const
+
+protected

Definition at line 32 of file tests/libxrpl/json/Writer.cpp.

@@ -192,6 +227,9 @@ Public Attributes
+ + + + + +
@@ -201,6 +239,11 @@ Public Attributes
void WriterFixture::checkOutputAndReset
+
+protected

Definition at line 38 of file tests/libxrpl/json/Writer.cpp.

@@ -213,14 +256,22 @@ Public Attributes
+ + + + + +
std::string WriterFixture::output
+
+protected
-

Definition at line 16 of file tests/libxrpl/json/Writer.cpp.

+

Definition at line 15 of file tests/libxrpl/json/Writer.cpp.

@@ -229,14 +280,22 @@ Public Attributes
+ + + + + +
std::unique_ptr<Writer> WriterFixture::writer
+
+protected
-

Definition at line 17 of file tests/libxrpl/json/Writer.cpp.

+

Definition at line 16 of file tests/libxrpl/json/Writer.cpp.

diff --git a/structWriterFixture__coll__graph.map b/classWriterFixture__coll__graph.map similarity index 61% rename from structWriterFixture__coll__graph.map rename to classWriterFixture__coll__graph.map index 3b16f42651..c5f0a03d16 100644 --- a/structWriterFixture__coll__graph.map +++ b/classWriterFixture__coll__graph.map @@ -1,24 +1,26 @@ - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/classWriterFixture__coll__graph.md5 b/classWriterFixture__coll__graph.md5 new file mode 100644 index 0000000000..0c0c1ab734 --- /dev/null +++ b/classWriterFixture__coll__graph.md5 @@ -0,0 +1 @@ +0719dcba1b85cc0ea000126a5dc78e3d \ No newline at end of file diff --git a/classWriterFixture__coll__graph.png b/classWriterFixture__coll__graph.png new file mode 100644 index 0000000000000000000000000000000000000000..101d8685281986ed70975dfb01dc7aeb0f55e9e5 GIT binary patch literal 52681 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 K%Tc^?@BaWFUxw)b literal 0 HcmV?d00001 diff --git a/classWriterFixture__inherit__graph.map b/classWriterFixture__inherit__graph.map new file mode 100644 index 0000000000..ea177e4fe8 --- /dev/null +++ b/classWriterFixture__inherit__graph.map @@ -0,0 +1,5 @@ + + + + + diff --git a/classWriterFixture__inherit__graph.md5 b/classWriterFixture__inherit__graph.md5 new file mode 100644 index 0000000000..e697fdfd2f --- /dev/null +++ b/classWriterFixture__inherit__graph.md5 @@ -0,0 +1 @@ +b65c3072e81eb77523b37054f40c0216 \ No newline at end of file diff --git a/classWriterFixture__inherit__graph.png b/classWriterFixture__inherit__graph.png new file mode 100644 index 0000000000000000000000000000000000000000..df32035f50f5c9fafb1fdae6d8fcf0a0f34f467e GIT binary patch literal 3396 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::ValAdaptor (xrpl::test::csf)
ValidAMM (xrpl)
Validation (xrpl::test::csf)
ValidationParms (xrpl)
Validations (xrpl)
Validations_test (xrpl::test::csf)
TrustedPublisherServer::Validator (xrpl::test)
Validator (xrpl::test)
ValidatorList_test::Validator (xrpl::test)
ValidatorBlobInfo (xrpl)
ValidatorInfo_test (xrpl::test)
ValidatorKeys (xrpl)
ValidatorKeys_test (xrpl::test)
ValidatorList (xrpl)
ValidatorList_test (xrpl::test)
ValidatorRPC_test (xrpl::test)
ValidatorSite (xrpl)
ValidatorSite_test (xrpl::test)
ValidatorsTxtGuard (xrpl::detail)
ValidatorToken (xrpl)
ValidClawback (xrpl)
ValidLoan (xrpl)
ValidLoanBroker (xrpl)
ValidMPTIssuance (xrpl)
ValidNewAccountRoot (xrpl)
ValidNFTokenPage (xrpl)
ValidPermissionedDEX (xrpl)
ValidPermissionedDomain (xrpl)
ValidPseudoAccounts (xrpl)
ValidVault (xrpl)
LocalValues::Value (xrpl::detail)
Value (Json)
DeferredCredits::Value (xrpl::detail)
ValueAllocator (Json)
ValueConstIterator (Json)
TaggedCache::ValueEntry (xrpl)
aged_unordered_container::ValueHash (beast::detail)
Value::ValueHolder (Json)
ValueIterator (Json)
ValueIteratorBase (Json)
STObject::ValueProxy (xrpl)
ValueUnit (xrpl::unit)
valueUnitField (xrpl::test::jtx)
varint_test (xrpl::NodeStore::tests)
varint_traits (xrpl::NodeStore)
varint_traits< T, true > (xrpl::NodeStore)
ValidVault::Vault (xrpl)
Vault (xrpl::test::jtx)
Vault_test (xrpl)
VaultClawback (xrpl)
VaultCreate (xrpl)
VaultDelete (xrpl)
VaultDeposit (xrpl)
LoanBroker_test::VaultInfo (xrpl::test)
VaultSet (xrpl)
VaultWithdraw (xrpl)
Loan_test::VerifyLoanStatus (xrpl::test)
Version_test (xrpl)
VersionHandler (xrpl::RPC)
View_test (xrpl::test)
MultiApiJson::visitor_t (xrpl::detail)
base_uint::VoidHelper (xrpl)
VotableValue (xrpl::detail)
VoteArg (xrpl::test::jtx)
W
-
WalletPropose_test (xrpl::RPC)
WeakIntrusive (xrpl)
WithdrawArg (xrpl::test::jtx)
Vault::WithdrawArgs (xrpl::test::jtx)
Work (xrpl::detail)
io_list::work (xrpl)
ResolverAsioImpl::Work (xrpl)
WorkBase (xrpl::detail)
Workers::Worker (xrpl)
Workers (xrpl)
Workers_test (xrpl)
WorkFile (xrpl::detail)
WorkPlain (xrpl::detail)
WorkSSL (xrpl::detail)
WrappedSink (beast)
Writer (Json)
json_body::writer (xrpl)
Writer (xrpl)
WriterBase (Json)
WriterFixture
WrongPrevLedger (xrpl::test::csf)
WSClient (xrpl::test)
WSClient_test (xrpl::test)
WSClientImpl (xrpl::test)
WSInfoSub (xrpl)
WSMsg (xrpl)
WSSession (xrpl)
+
WalletPropose_test (xrpl::RPC)
WeakIntrusive (xrpl)
WithdrawArg (xrpl::test::jtx)
Vault::WithdrawArgs (xrpl::test::jtx)
Work (xrpl::detail)
io_list::work (xrpl)
ResolverAsioImpl::Work (xrpl)
WorkBase (xrpl::detail)
Workers::Worker (xrpl)
Workers (xrpl)
Workers_test (xrpl)
WorkFile (xrpl::detail)
WorkPlain (xrpl::detail)
WorkSSL (xrpl::detail)
WrappedSink (beast)
Writer (Json)
json_body::writer (xrpl)
Writer (xrpl)
WriterBase (Json)
WriterFixture
WrongPrevLedger (xrpl::test::csf)
WSClient (xrpl::test)
WSClient_test (xrpl::test)
WSClientImpl (xrpl::test)
WSInfoSub (xrpl)
WSMsg (xrpl)
WSSession (xrpl)
X
XChain_test (xrpl::test)
XChainAddAccountCreateAttestation (xrpl)
XChainAddClaimAttestation (xrpl)
XChainAttestationsBase (xrpl)
XChainBridgeObjects (xrpl::test::jtx)
XChainClaim (xrpl)
XChainClaimAttestation (xrpl)
XChainClaimAttestations (xrpl)
XChainCommit (xrpl)
XChainCreateAccountAttestation (xrpl)
XChainCreateAccountAttestations (xrpl)
XChainCreateAccountCommit (xrpl)
XChainCreateBridge (xrpl)
XChainCreateClaimID (xrpl)
XChainSim_test (xrpl::test)
XEnv (xrpl::test)
xferFee (xrpl::test::jtx::token)
xor_shift_engine (beast::detail)
XRP_t (xrpl::test::jtx)
XRPAmount (xrpl)
XRPAmount_test (xrpl)
XRPBalanceChecks (xrpl)
XRPEndpointOfferCrossingStep (xrpl)
XRPEndpointPaymentStep (xrpl)
XRPEndpointStep (xrpl)
XRPEndpointStepInfo (xrpl::test)
XRPNotCreated (xrpl)
xxhasher (beast)
XXHasher_test (beast)
diff --git a/classxrpl_1_1test_1_1Batch__test.html b/classxrpl_1_1test_1_1Batch__test.html index 07b0985485..e6446ebb41 100644 --- a/classxrpl_1_1test_1_1Batch__test.html +++ b/classxrpl_1_1test_1_1Batch__test.html @@ -719,7 +719,7 @@ template<typename... Args>
-

Definition at line 616 of file Batch_test.cpp.

+

Definition at line 618 of file Batch_test.cpp.

@@ -747,7 +747,7 @@ template<typename... Args>
-

Definition at line 860 of file Batch_test.cpp.

+

Definition at line 862 of file Batch_test.cpp.

@@ -775,7 +775,7 @@ template<typename... Args>
-

Definition at line 951 of file Batch_test.cpp.

+

Definition at line 953 of file Batch_test.cpp.

@@ -803,7 +803,7 @@ template<typename... Args>
-

Definition at line 1187 of file Batch_test.cpp.

+

Definition at line 1189 of file Batch_test.cpp.

@@ -831,7 +831,7 @@ template<typename... Args>
-

Definition at line 1361 of file Batch_test.cpp.

+

Definition at line 1363 of file Batch_test.cpp.

@@ -859,7 +859,7 @@ template<typename... Args>
-

Definition at line 1474 of file Batch_test.cpp.

+

Definition at line 1476 of file Batch_test.cpp.

@@ -887,7 +887,7 @@ template<typename... Args>
-

Definition at line 1610 of file Batch_test.cpp.

+

Definition at line 1612 of file Batch_test.cpp.

@@ -915,7 +915,7 @@ template<typename... Args>
-

Definition at line 1842 of file Batch_test.cpp.

+

Definition at line 1844 of file Batch_test.cpp.

@@ -943,7 +943,7 @@ template<typename... Args>
-

Definition at line 2064 of file Batch_test.cpp.

+

Definition at line 2066 of file Batch_test.cpp.

@@ -981,7 +981,7 @@ template<typename... Args>
-

Definition at line 2257 of file Batch_test.cpp.

+

Definition at line 2259 of file Batch_test.cpp.

@@ -1009,7 +1009,7 @@ template<typename... Args>
-

Definition at line 2443 of file Batch_test.cpp.

+

Definition at line 2445 of file Batch_test.cpp.

@@ -1037,7 +1037,7 @@ template<typename... Args>
-

Definition at line 2452 of file Batch_test.cpp.

+

Definition at line 2454 of file Batch_test.cpp.

@@ -1065,7 +1065,7 @@ template<typename... Args>
-

Definition at line 2499 of file Batch_test.cpp.

+

Definition at line 2501 of file Batch_test.cpp.

@@ -1093,7 +1093,7 @@ template<typename... Args>
-

Definition at line 2550 of file Batch_test.cpp.

+

Definition at line 2552 of file Batch_test.cpp.

@@ -1121,7 +1121,7 @@ template<typename... Args>
-

Definition at line 2684 of file Batch_test.cpp.

+

Definition at line 2686 of file Batch_test.cpp.

@@ -1149,7 +1149,7 @@ template<typename... Args>
-

Definition at line 2884 of file Batch_test.cpp.

+

Definition at line 2886 of file Batch_test.cpp.

@@ -1177,7 +1177,7 @@ template<typename... Args>
-

Definition at line 2997 of file Batch_test.cpp.

+

Definition at line 2999 of file Batch_test.cpp.

@@ -1205,7 +1205,7 @@ template<typename... Args>
-

Definition at line 3055 of file Batch_test.cpp.

+

Definition at line 3057 of file Batch_test.cpp.

@@ -1233,7 +1233,7 @@ template<typename... Args>
-

Definition at line 3116 of file Batch_test.cpp.

+

Definition at line 3118 of file Batch_test.cpp.

@@ -1261,7 +1261,7 @@ template<typename... Args>
-

Definition at line 3266 of file Batch_test.cpp.

+

Definition at line 3268 of file Batch_test.cpp.

@@ -1289,7 +1289,7 @@ template<typename... Args>
-

Definition at line 3453 of file Batch_test.cpp.

+

Definition at line 3455 of file Batch_test.cpp.

@@ -1317,7 +1317,7 @@ template<typename... Args>
-

Definition at line 3562 of file Batch_test.cpp.

+

Definition at line 3564 of file Batch_test.cpp.

@@ -1345,7 +1345,7 @@ template<typename... Args>
-

Definition at line 3713 of file Batch_test.cpp.

+

Definition at line 3715 of file Batch_test.cpp.

@@ -1373,7 +1373,7 @@ template<typename... Args>
-

Definition at line 3746 of file Batch_test.cpp.

+

Definition at line 3748 of file Batch_test.cpp.

@@ -1401,7 +1401,7 @@ template<typename... Args>
-

Definition at line 3827 of file Batch_test.cpp.

+

Definition at line 3829 of file Batch_test.cpp.

@@ -1429,7 +1429,7 @@ template<typename... Args>
-

Definition at line 3941 of file Batch_test.cpp.

+

Definition at line 3943 of file Batch_test.cpp.

@@ -1457,7 +1457,7 @@ template<typename... Args>
-

Definition at line 4000 of file Batch_test.cpp.

+

Definition at line 4002 of file Batch_test.cpp.

@@ -1485,7 +1485,7 @@ template<typename... Args>
-

Definition at line 4291 of file Batch_test.cpp.

+

Definition at line 4293 of file Batch_test.cpp.

@@ -1513,7 +1513,7 @@ template<typename... Args>
-

Definition at line 4373 of file Batch_test.cpp.

+

Definition at line 4375 of file Batch_test.cpp.

@@ -1541,7 +1541,7 @@ template<typename... Args>
-

Definition at line 4461 of file Batch_test.cpp.

+

Definition at line 4463 of file Batch_test.cpp.

@@ -1572,7 +1572,7 @@ template<typename... Args>

Implements beast::unit_test::suite.

-

Definition at line 4497 of file Batch_test.cpp.

+

Definition at line 4499 of file Batch_test.cpp.

diff --git a/crypto_2main_8cpp_source.html b/crypto_2main_8cpp_source.html index 56767d4371..1025336eaa 100644 --- a/crypto_2main_8cpp_source.html +++ b/crypto_2main_8cpp_source.html @@ -81,8 +81,14 @@ $(document).ready(function() { init_codefold(0); });
crypto/main.cpp
-
1#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
-
2#include <doctest/doctest.h>
+
1#include <gtest/gtest.h>
+
2
+
3int
+
4main(int argc, char** argv)
+
5{
+
6 ::testing::InitGoogleTest(&argc, argv);
+
7 return RUN_ALL_TESTS();
+
8}
-
1#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
-
2#include <doctest/doctest.h>
+
1#include <gtest/gtest.h>
+
2
+
3int
+
4main(int argc, char** argv)
+
5{
+
6 ::testing::InitGoogleTest(&argc, argv);
+
7 return RUN_ALL_TESTS();
+
8}
-

This directory contains unit tests for the project. The difference from existing src/test folder is that we switch to 3rd party testing framework (doctest). We intend to gradually move existing tests from our own framework to doctest and such tests will be moved to this new folder.

+

This directory contains unit tests for the project. The difference from existing src/test folder is that we switch to 3rd party testing framework (gtest). We intend to gradually move existing tests from our own framework to gtest and such tests will be moved to this new folder.

diff --git a/namespacemembers_func_t.html b/namespacemembers_func_t.html index 4339e94f10..0524dd263c 100644 --- a/namespacemembers_func_t.html +++ b/namespacemembers_func_t.html @@ -76,16 +76,14 @@ $(function() {
  • tenthBipsOfValue() : xrpl
  • tenthBipsPerUnity() : xrpl
  • TERtoInt() : xrpl
  • -
  • TEST_CASE() : xrpl
  • -
  • TEST_SUITE_BEGIN() : xrpl
  • -
  • TEST_SUITE_END() : xrpl
  • +
  • TEST() : xrpl
  • testable_amendments() : xrpl::test::jtx
  • textTime() : xrpl
  • Throw() : xrpl
  • throwFieldNotFound() : xrpl
  • to_asio_address() : beast::IP
  • to_asio_endpoint() : beast::IP
  • -
  • to_currency() : xrpl
  • +
  • to_currency() : xrpl
  • to_iso8601() : xrpl
  • to_issuer() : xrpl
  • to_json() : Json, xrpl
  • diff --git a/namespacemembers_s.html b/namespacemembers_s.html index 8375a58aa6..2befbc510e 100644 --- a/namespacemembers_s.html +++ b/namespacemembers_s.html @@ -259,8 +259,8 @@ $(function() {
  • statusRequestResponse() : xrpl
  • sterilize() : xrpl
  • STInt32 : xrpl
  • -
  • Stopwatch : xrpl
  • stopwatch() : xrpl
  • +
  • Stopwatch : xrpl
  • stpath() : xrpl::test::jtx
  • stpath_append() : xrpl::test::jtx
  • stpath_append_one() : xrpl::test::jtx
  • diff --git a/namespacemembers_t.html b/namespacemembers_t.html index 1f914bbe21..f3115f62bb 100644 --- a/namespacemembers_t.html +++ b/namespacemembers_t.html @@ -293,13 +293,11 @@ $(function() {
  • TERUnderlyingType : xrpl
  • TEScodes : xrpl
  • tesSUCCESS : xrpl
  • -
  • TEST_CASE() : xrpl
  • +
  • TEST() : xrpl
  • test_hardened_unordered_map : xrpl::detail
  • test_hardened_unordered_multimap : xrpl::detail
  • test_hardened_unordered_multiset : xrpl::detail
  • test_hardened_unordered_set : xrpl::detail
  • -
  • TEST_SUITE_BEGIN() : xrpl
  • -
  • TEST_SUITE_END() : xrpl
  • testable_amendments() : xrpl::test::jtx
  • testArray : xrpl::InnerObjectFormatsUnitTestDetail
  • testStartTime : xrpl::test::jtx::oracle
  • diff --git a/namespacexrpl.html b/namespacexrpl.html index 70d900770f..9135e5364f 100644 --- a/namespacexrpl.html +++ b/namespacexrpl.html @@ -4432,44 +4432,40 @@ requires requires(T const& t) { { t.getJson(   BEAST_DEFINE_TESTSUITE (Version, rpc, xrpl)   - TEST_SUITE_BEGIN ("json_value") -  - TEST_CASE ("limits") -  - TEST_CASE ("construct and compare Json::StaticString") -  - TEST_CASE ("different types") -  - TEST_CASE ("compare strings") -  - TEST_CASE ("bool") -  - TEST_CASE ("bad json") -  - TEST_CASE ("edge cases") -  - TEST_CASE ("copy") -  - TEST_CASE ("move") -  - TEST_CASE ("comparisons") -  - TEST_CASE ("compact") -  - TEST_CASE ("conversions") -  - TEST_CASE ("access members") -  - TEST_CASE ("remove members") -  - TEST_CASE ("iterator") -  - TEST_CASE ("nest limits") -  - TEST_CASE ("memory leak") -  - TEST_SUITE_END () -  + TEST (json_value, limits) +  + TEST (json_value, construct_and_compare_Json_StaticString) +  + TEST (json_value, different_types) +  + TEST (json_value, compare_strings) +  + TEST (json_value, bool) +  + TEST (json_value, bad_json) +  + TEST (json_value, edge_cases) +  + TEST (json_value, copy) +  + TEST (json_value, move) +  + TEST (json_value, comparisons) +  + TEST (json_value, compact) +  + TEST (json_value, conversions) +  + TEST (json_value, access_members) +  + TEST (json_value, remove_members) +  + TEST (json_value, iterator) +  + TEST (json_value, nest_limits) +  + TEST (json_value, memory_leak) +  uint256 proposalUniqueId (uint256 const &proposeHash, uint256 const &previousLedger, std::uint32_t proposeSeq, NetClock::time_point closeTime, Slice const &publicKey, Slice const &signature)  Calculate a unique identifier for a signed proposal.
      @@ -33982,379 +33978,514 @@ template<class Hasher , class... Args> - -

    ◆ TEST_SUITE_BEGIN()

    + +

    ◆ TEST() [1/17]

    - + - - + + + + + + + + + + + +
    xrpl::TEST_SUITE_BEGIN xrpl::TEST ("json_value" )json_value ,
    limits  
    )
    +

    Definition at line 17 of file Value.cpp.

    +
    - -

    ◆ TEST_CASE() [1/17]

    + +

    ◆ TEST() [2/17]

    - + - - + + + + + + + + + + + +
    xrpl::TEST_CASE xrpl::TEST ("limits" )json_value ,
    construct_and_compare_Json_StaticString  
    )
    -

    Definition at line 19 of file Value.cpp.

    +

    Definition at line 25 of file Value.cpp.

    - -

    ◆ TEST_CASE() [2/17]

    + +

    ◆ TEST() [3/17]

    - + - - + + + + + + + + + + + +
    xrpl::TEST_CASE xrpl::TEST ("construct and compare Json::StaticString" )json_value ,
    different_types  
    )
    -

    Definition at line 27 of file Value.cpp.

    +

    Definition at line 49 of file Value.cpp.

    - -

    ◆ TEST_CASE() [3/17]

    + +

    ◆ TEST() [4/17]

    - + - - + + + + + + + + + + + +
    xrpl::TEST_CASE xrpl::TEST ("different types" )json_value ,
    compare_strings  
    )
    -

    Definition at line 51 of file Value.cpp.

    +

    Definition at line 203 of file Value.cpp.

    - -

    ◆ TEST_CASE() [4/17]

    + +

    ◆ TEST() [5/17]

    - + - - + + + + + + + + + + + +
    xrpl::TEST_CASE xrpl::TEST ("compare strings" )json_value ,
    bool  
    )
    -

    Definition at line 205 of file Value.cpp.

    +

    Definition at line 557 of file Value.cpp.

    - -

    ◆ TEST_CASE() [5/17]

    + +

    ◆ TEST() [6/17]

    - + - - + + + + + + + + + + + +
    xrpl::TEST_CASE xrpl::TEST ("bool" )json_value ,
    bad_json  
    )
    -

    Definition at line 559 of file Value.cpp.

    +

    Definition at line 580 of file Value.cpp.

    - -

    ◆ TEST_CASE() [6/17]

    + +

    ◆ TEST() [7/17]

    - + - - + + + + + + + + + + + +
    xrpl::TEST_CASE xrpl::TEST ("bad json" )json_value ,
    edge_cases  
    )
    -

    Definition at line 582 of file Value.cpp.

    +

    Definition at line 590 of file Value.cpp.

    - -

    ◆ TEST_CASE() [7/17]

    + +

    ◆ TEST() [8/17]

    - + - - + + + + + + + + + + + +
    xrpl::TEST_CASE xrpl::TEST ("edge cases" )json_value ,
    copy  
    )
    -

    Definition at line 592 of file Value.cpp.

    +

    Definition at line 740 of file Value.cpp.

    - -

    ◆ TEST_CASE() [8/17]

    + +

    ◆ TEST() [9/17]

    - + - - + + + + + + + + + + + +
    xrpl::TEST_CASE xrpl::TEST ("copy" )json_value ,
    move  
    )
    -

    Definition at line 743 of file Value.cpp.

    +

    Definition at line 761 of file Value.cpp.

    - -

    ◆ TEST_CASE() [9/17]

    + +

    ◆ TEST() [10/17]

    - + - - + + + + + + + + + + + +
    xrpl::TEST_CASE xrpl::TEST ("move" )json_value ,
    comparisons  
    )
    -

    Definition at line 764 of file Value.cpp.

    +

    Definition at line 780 of file Value.cpp.

    - -

    ◆ TEST_CASE() [10/17]

    + +

    ◆ TEST() [11/17]

    - + - - + + + + + + + + + + + +
    xrpl::TEST_CASE xrpl::TEST ("comparisons" )json_value ,
    compact  
    )
    -

    Definition at line 783 of file Value.cpp.

    +

    Definition at line 835 of file Value.cpp.

    - -

    ◆ TEST_CASE() [11/17]

    + +

    ◆ TEST() [12/17]

    - + - - + + + + + + + + + + + +
    xrpl::TEST_CASE xrpl::TEST ("compact" )json_value ,
    conversions  
    )
    -

    Definition at line 838 of file Value.cpp.

    +

    Definition at line 860 of file Value.cpp.

    - -

    ◆ TEST_CASE() [12/17]

    + +

    ◆ TEST() [13/17]

    - + - - + + + + + + + + + + + +
    xrpl::TEST_CASE xrpl::TEST ("conversions" )json_value ,
    access_members  
    )
    -

    Definition at line 863 of file Value.cpp.

    +

    Definition at line 1078 of file Value.cpp.

    - -

    ◆ TEST_CASE() [13/17]

    + +

    ◆ TEST() [14/17]

    - + - - + + + + + + + + + + + +
    xrpl::TEST_CASE xrpl::TEST ("access members" )json_value ,
    remove_members  
    )
    -

    Definition at line 1081 of file Value.cpp.

    +

    Definition at line 1171 of file Value.cpp.

    - -

    ◆ TEST_CASE() [14/17]

    + +

    ◆ TEST() [15/17]

    - + - - + + + + + + + + + + + +
    xrpl::TEST_CASE xrpl::TEST ("remove members" )json_value ,
    iterator  
    )
    -

    Definition at line 1174 of file Value.cpp.

    +

    Definition at line 1198 of file Value.cpp.

    - -

    ◆ TEST_CASE() [15/17]

    + +

    ◆ TEST() [16/17]

    - + - - + + + + + + + + + + + +
    xrpl::TEST_CASE xrpl::TEST ("iterator" )json_value ,
    nest_limits  
    )
    -

    Definition at line 1201 of file Value.cpp.

    +

    Definition at line 1284 of file Value.cpp.

    - -

    ◆ TEST_CASE() [16/17]

    + +

    ◆ TEST() [17/17]

    - + - - - + + -
    xrpl::TEST_CASE xrpl::TEST ("nest limits" )json_value ,
    -
    - -

    Definition at line 1287 of file Value.cpp.

    - -
    -
    - -

    ◆ TEST_CASE() [17/17]

    - -
    -
    - - - - - + + + -
    xrpl::TEST_CASE ("memory leak" ) memory_leak  
    -
    - -

    Definition at line 1333 of file Value.cpp.

    - -
    -
    - -

    ◆ TEST_SUITE_END()

    - -
    -
    - - - - + +
    xrpl::TEST_SUITE_END () )
    +

    Definition at line 1330 of file Value.cpp.

    +
    diff --git a/net_2main_8cpp_source.html b/net_2main_8cpp_source.html index 0bf6813a2a..2bc4d6861a 100644 --- a/net_2main_8cpp_source.html +++ b/net_2main_8cpp_source.html @@ -81,8 +81,14 @@ $(document).ready(function() { init_codefold(0); });
    net/main.cpp
    -
    1#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
    -
    2#include <doctest/doctest.h>
    +
    1#include <gtest/gtest.h>
    +
    2
    +
    3int
    +
    4main(int argc, char** argv)
    +
    5{
    +
    6 ::testing::InitGoogleTest(&argc, argv);
    +
    7 return RUN_ALL_TESTS();
    +
    8}