Minimize use of jtx::with_only_features (RIPD-1515):

In order to automatically run unit tests with newly created
amendments, prefer to start with jtx::supported_features() and
then subtract unwanted features.

These changes identified a few bugs that were hiding in
amendments.  One of those bugs, in FlowCross, is not yet fixed.
By uncommenting the test in CrossingLimits_test.cpp you can see
failures relating to that bug.  Since FlowCross is not yet
enabled on the network we can fix the bug at our convenience.
This commit is contained in:
Scott Schurr
2017-08-16 18:30:55 -07:00
committed by seelabs
parent aa76632bb3
commit 3523cee63d
30 changed files with 826 additions and 658 deletions

View File

@@ -115,6 +115,9 @@ featureToBitsetIndex(uint256 const& f);
uint256 uint256
bitsetIndexToFeature(size_t i); bitsetIndexToFeature(size_t i);
bool
hasFeature (uint256 const& feat, FeatureBitset features);
template <class F> template <class F>
void void
foreachFeature(FeatureBitset bs, F&& f) foreachFeature(FeatureBitset bs, F&& f)

View File

@@ -129,6 +129,12 @@ uint256 bitsetIndexToFeature(size_t i)
return featureCollections.bitsetIndexToFeature(i); return featureCollections.bitsetIndexToFeature(i);
} }
bool hasFeature(uint256 const& feat, FeatureBitset features)
{
return features[featureToBitsetIndex(feat)];
}
uint256 const featureMultiSign = *getRegisteredFeature("MultiSign"); uint256 const featureMultiSign = *getRegisteredFeature("MultiSign");
uint256 const featureTickets = *getRegisteredFeature("Tickets"); uint256 const featureTickets = *getRegisteredFeature("Tickets");
uint256 const featureTrustSetAuth = *getRegisteredFeature("TrustSetAuth"); uint256 const featureTrustSetAuth = *getRegisteredFeature("TrustSetAuth");

View File

@@ -37,18 +37,22 @@ private:
using namespace jtx; using namespace jtx;
auto const ownerCount = env.le(account)->getFieldU32(sfOwnerCount); auto const ownerCount = env.le(account)->getFieldU32(sfOwnerCount);
for (std::size_t i = 0; i < n; i++) for (std::size_t i = 0; i < n; i++)
{
env(offer(account, in, out)); env(offer(account, in, out));
env.close();
}
env.require (owners (account, ownerCount + n)); env.require (owners (account, ownerCount + n));
} }
public: public:
void void
testStepLimit(std::initializer_list<uint256> fs) testStepLimit(FeatureBitset features)
{ {
testcase ("Step Limit");
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(fs)); Env env(*this, features);
auto const xrpMax = XRP(100000000000);
auto const gw = Account("gateway"); auto const gw = Account("gateway");
auto const USD = gw["USD"]; auto const USD = gw["USD"];
@@ -62,27 +66,32 @@ public:
// Alice offers to buy 1000 XRP for 1000 USD. She takes Bob's first // Alice offers to buy 1000 XRP for 1000 USD. She takes Bob's first
// offer, and removes 999 more as unfunded and hits the step limit. // offer, and removes 999 more as unfunded and hits the step limit.
env(offer("alice", USD(1000), XRP(1000)), env(offer("alice", USD(1000), XRP(1000)));
require ( env.require (balance("alice", USD(1)));
balance("alice", USD(1)), owners("alice", 2), env.require (owners("alice", 2));
balance("bob", USD(0)), owners("bob", 1001), env.require (balance("bob", USD(0)));
balance("dan", USD(1)), owners("dan", 2))); env.require (owners("bob", 1001));
env.require (balance("dan", USD(1)));
env.require (owners("dan", 2));
// Carol offers to buy 1000 XRP for 1000 USD. She removes Bob's next // Carol offers to buy 1000 XRP for 1000 USD. She removes Bob's next
// 1000 offers as unfunded and hits the step limit. // 1000 offers as unfunded and hits the step limit.
env(offer("carol", USD(1000), XRP(1000)), env(offer("carol", USD(1000), XRP(1000)));
require ( env.require (balance("carol", USD(none)));
balance("carol", USD(none)), owners("carol", 1), env.require (owners("carol", 1));
balance("bob", USD(0)), owners("bob", 1), env.require (balance("bob", USD(0)));
balance("dan", USD(1)), owners("dan", 2))); env.require (owners("bob", 1));
env.require (balance("dan", USD(1)));
env.require (owners("dan", 2));
} }
void void
testCrossingLimit(std::initializer_list<uint256> fs) testCrossingLimit(FeatureBitset features)
{ {
testcase ("Crossing Limit");
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(fs)); Env env(*this, features);
auto const xrpMax = XRP(100000000000);
auto const gw = Account("gateway"); auto const gw = Account("gateway");
auto const USD = gw["USD"]; auto const USD = gw["USD"];
@@ -93,25 +102,26 @@ public:
// Alice offers to buy 1000 XRP for 1000 USD. She takes the first // Alice offers to buy 1000 XRP for 1000 USD. She takes the first
// 850 offers, hitting the crossing limit. // 850 offers, hitting the crossing limit.
env(offer("alice", USD(1000), XRP(1000)), env(offer("alice", USD(1000), XRP(1000)));
require ( env.require (balance("alice", USD(850)));
balance("alice", USD(850)), env.require (balance("bob", USD(150)));
balance("bob", USD(150)), owners ("bob", 151))); env.require (owners ("bob", 151));
// Carol offers to buy 1000 XRP for 1000 USD. She takes the remaining // Carol offers to buy 1000 XRP for 1000 USD. She takes the remaining
// 150 offers without hitting a limit. // 150 offers without hitting a limit.
env(offer("carol", USD(1000), XRP(1000)), env(offer("carol", USD(1000), XRP(1000)));
require ( env.require (balance("carol", USD(150)));
balance("carol", USD(150)), env.require (balance("bob", USD(0)));
balance("bob", USD(0)), owners ("bob", 1))); env.require (owners ("bob", 1));
} }
void void
testStepAndCrossingLimit(std::initializer_list<uint256> fs) testStepAndCrossingLimit(FeatureBitset features)
{ {
testcase ("Step And Crossing Limit");
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(fs)); Env env(*this, features);
auto const xrpMax = XRP(100000000000);
auto const gw = Account("gateway"); auto const gw = Account("gateway");
auto const USD = gw["USD"]; auto const USD = gw["USD"];
@@ -131,36 +141,139 @@ public:
// Bob offers to buy 1000 XRP for 1000 USD. He takes all 400 USD from // Bob offers to buy 1000 XRP for 1000 USD. He takes all 400 USD from
// Alice's offers, 1 USD from Carol's and then removes 599 of Carol's // Alice's offers, 1 USD from Carol's and then removes 599 of Carol's
// offers as unfunded, before hitting the step limit. // offers as unfunded, before hitting the step limit.
env(offer("bob", USD(1000), XRP(1000)), env(offer("bob", USD(1000), XRP(1000)));
require ( env.require (balance("bob", USD(401)));
balance("bob", USD(401)), env.require (balance("alice", USD(600)));
balance("alice", USD(600)), owners("alice", 1), env.require (owners("alice", 1));
balance("carol", USD(0)), owners("carol", 101), env.require (balance("carol", USD(0)));
balance("evita", USD(1000)), owners("evita", 1000))); env.require (owners("carol", 101));
env.require (balance("evita", USD(1000)));
env.require (owners("evita", 1000));
// Dan offers to buy 900 XRP for 900 USD. He removes all 100 of Carol's // Dan offers to buy 900 XRP for 900 USD. He removes all 100 of Carol's
// offers as unfunded, then takes 850 USD from Evita's, hitting the // offers as unfunded, then takes 850 USD from Evita's, hitting the
// crossing limit. // crossing limit.
env(offer("dan", USD(900), XRP(900)), env(offer("dan", USD(900), XRP(900)));
require ( env.require (balance("dan", USD(850)));
balance("dan", USD(850)), env.require (balance("alice", USD(600)));
balance("alice", USD(600)), owners("alice", 1), env.require (owners("alice", 1));
balance("carol", USD(0)), owners("carol", 1), env.require (balance("carol", USD(0)));
balance("evita", USD(150)), owners("evita", 150))); env.require (owners("carol", 1));
env.require (balance("evita", USD(150)));
env.require (owners("evita", 150));
}
void testAutoBridgedLimits (FeatureBitset features)
{
testcase ("Auto Bridged Limits");
using namespace jtx;
Env env(*this, features);
auto const gw = Account("gateway");
auto const USD = gw["USD"];
auto const EUR = gw["EUR"];
env.fund(XRP(100000000), gw, "alice", "bob", "carol", "dan", "evita");
env.trust(USD(2000), "alice");
env(pay(gw, "alice", USD(2000)));
env.trust(USD(1000), "carol");
env(pay(gw, "carol", USD(3)));
env.trust(USD(1000), "evita");
env(pay(gw, "evita", USD(1000)));
n_offers (env, 302, "alice", EUR(2), XRP(1));
n_offers (env, 300, "alice", XRP(1), USD(4));
n_offers (env, 497, "carol", XRP(1), USD(3));
n_offers (env, 1001, "evita", EUR(1), USD(1));
// Bob offers to buy 2000 USD for 2000 EUR, even though he only has
// 1000 EUR.
// 1. He spends 600 EUR taking Alice's auto-bridged offers and
// gets 1200 USD for that.
// 2. He spends another 2 EUR taking one of Alice's EUR->XRP and
// one of Carol's XRP-USD offers. He gets 3 USD for that.
// 3. The remainder of Carol's offers are now unfunded. We've
// consumed 602 offers so far. We now chew through 398 more
// of Carol's unfunded offers until we hit the 1000 offer limit.
// This sets have_bridge to false -- we will handle no more
// bridged offers.
// 4. However, have_direct is still true. So we go around one more
// time and take one of Evita's offers.
// 5. After taking one of Evita's offers we notice (again) that our
// offer count was exceeded. So we completely stop after taking
// one of Evita's offers.
env.trust(EUR(10000), "bob");
env.close();
env(pay(gw, "bob", EUR(1000)));
env.close();
env(offer("bob", USD(2000), EUR(2000)));
env.require (balance("bob", USD(1204)));
env.require (balance("bob", EUR( 397)));
env.require (balance("alice", USD(800)));
env.require (balance("alice", EUR(602)));
env.require (offers("alice", 1));
env.require (owners("alice", 3));
env.require (balance("carol", USD(0)));
env.require (balance("carol", EUR(none)));
env.require (offers("carol", 100));
env.require (owners("carol", 101));
env.require (balance("evita", USD(999)));
env.require (balance("evita", EUR(1)));
env.require (offers("evita", 1000));
env.require (owners("evita", 1002));
// Dan offers to buy 900 EUR for 900 USD.
// 1. He removes all 100 of Carol's remaining unfunded offers.
// 2. Then takes 850 USD from Evita's offers.
// 3. Consuming 850 of Evita's funded offers hits the crossing
// limit. So Dan's offer crossing stops even though he would
// be willing to take another 50 of Evita's offers.
env.trust(EUR(10000), "dan");
env.close();
env(pay(gw, "dan", EUR(1000)));
env.close();
env(offer("dan", USD(900), EUR(900)));
env.require (balance("dan", USD(850)));
env.require (balance("dan", EUR(150)));
env.require (balance("alice", USD(800)));
env.require (balance("alice", EUR(602)));
env.require (offers("alice", 1));
env.require (owners("alice", 3));
env.require (balance("carol", USD(0)));
env.require (balance("carol", EUR(none)));
env.require (offers("carol", 0));
env.require (owners("carol", 1));
env.require (balance("evita", USD(149)));
env.require (balance("evita", EUR(851)));
env.require (offers("evita", 150));
env.require (owners("evita", 152));
} }
void void
run() run()
{ {
auto testAll = [this](std::initializer_list<uint256> fs) { auto testAll = [this](FeatureBitset features) {
testStepLimit(fs); testStepLimit(features);
testCrossingLimit(fs); testCrossingLimit(features);
testStepAndCrossingLimit(fs); testStepAndCrossingLimit(features);
testAutoBridgedLimits(features);
}; };
testAll({}); using namespace jtx;
testAll({featureFlow}); testAll(
testAll({featureFlow, fix1373}); supported_features_except (featureFlow, fix1373, featureFlowCross));
testAll({featureFlow, fix1373, featureFlowCross}); testAll(
supported_features_except ( fix1373, featureFlowCross));
testAll(
supported_features_except ( featureFlowCross));
// testAll(supported_amendments());// Does not pass with FlowCross enabled.
} }
}; };

View File

@@ -29,7 +29,7 @@ class DeliverMin_test : public beast::unit_test::suite
{ {
public: public:
void void
test_convert_all_of_an_asset(std::initializer_list<uint256> fs) test_convert_all_of_an_asset(FeatureBitset features)
{ {
testcase("Convert all of an asset using DeliverMin"); testcase("Convert all of an asset using DeliverMin");
@@ -38,7 +38,7 @@ public:
auto const USD = gw["USD"]; auto const USD = gw["USD"];
{ {
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), "alice", "bob", "carol", gw); env.fund(XRP(10000), "alice", "bob", "carol", gw);
env.trust(USD(100), "alice", "bob", "carol"); env.trust(USD(100), "alice", "bob", "carol");
env(pay("alice", "bob", USD(10)), delivermin(USD(10)), ter(temBAD_AMOUNT)); env(pay("alice", "bob", USD(10)), delivermin(USD(10)), ter(temBAD_AMOUNT));
@@ -61,7 +61,7 @@ public:
} }
{ {
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), "alice", "bob", gw); env.fund(XRP(10000), "alice", "bob", gw);
env.trust(USD(1000), "alice", "bob"); env.trust(USD(1000), "alice", "bob");
env(pay(gw, "bob", USD(100))); env(pay(gw, "bob", USD(100)));
@@ -73,7 +73,7 @@ public:
} }
{ {
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), "alice", "bob", "carol", gw); env.fund(XRP(10000), "alice", "bob", "carol", gw);
env.trust(USD(1000), "bob", "carol"); env.trust(USD(1000), "bob", "carol");
env(pay(gw, "bob", USD(200))); env(pay(gw, "bob", USD(200)));
@@ -91,7 +91,7 @@ public:
} }
{ {
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), "alice", "bob", "carol", "dan", gw); env.fund(XRP(10000), "alice", "bob", "carol", "dan", gw);
env.trust(USD(1000), "bob", "carol", "dan"); env.trust(USD(1000), "bob", "carol", "dan");
env(pay(gw, "bob", USD(100))); env(pay(gw, "bob", USD(100)));
@@ -111,11 +111,14 @@ public:
void void
run() run()
{ {
test_convert_all_of_an_asset({}); using namespace jtx;
test_convert_all_of_an_asset({featureFlow});
test_convert_all_of_an_asset({featureFlow, fix1373});
test_convert_all_of_an_asset( test_convert_all_of_an_asset(
{featureFlow, fix1373, featureFlowCross}); supported_features_except (featureFlow, fix1373, featureFlowCross));
test_convert_all_of_an_asset(
supported_features_except ( fix1373, featureFlowCross));
test_convert_all_of_an_asset(
supported_features_except ( featureFlowCross));
test_convert_all_of_an_asset(supported_amendments());
} }
}; };

View File

@@ -37,11 +37,11 @@ class Discrepancy_test : public beast::unit_test::suite
// A payment with path and sendmax is made and the transaction is queried // A payment with path and sendmax is made and the transaction is queried
// to verify that the net of balance changes match the fee charged. // to verify that the net of balance changes match the fee charged.
void void
testXRPDiscrepancy (std::initializer_list<uint256> fs) testXRPDiscrepancy (FeatureBitset features)
{ {
testcase ("Discrepancy test : XRP Discrepancy"); testcase ("Discrepancy test : XRP Discrepancy");
using namespace test::jtx; using namespace test::jtx;
Env env {*this, with_only_features(fs)}; Env env {*this, features};
Account A1 {"A1"}; Account A1 {"A1"};
Account A2 {"A2"}; Account A2 {"A2"};
@@ -144,10 +144,14 @@ class Discrepancy_test : public beast::unit_test::suite
public: public:
void run () void run ()
{ {
testXRPDiscrepancy ({}); using namespace test::jtx;
testXRPDiscrepancy ({featureFlow}); testXRPDiscrepancy (
testXRPDiscrepancy ({featureFlow, fix1373}); supported_features_except (featureFlow, fix1373, featureFlowCross));
testXRPDiscrepancy ({featureFlow, fix1373, featureFlowCross}); testXRPDiscrepancy (
supported_features_except ( fix1373, featureFlowCross));
testXRPDiscrepancy (
supported_features_except ( featureFlowCross));
testXRPDiscrepancy (supported_amendments());
} }
}; };

View File

@@ -207,7 +207,7 @@ struct Escrow_test : public beast::unit_test::suite
using namespace std::chrono; using namespace std::chrono;
{ // Escrow not enabled { // Escrow not enabled
Env env(*this, no_features); Env env(*this, supported_features_except (featureEscrow));
env.fund(XRP(5000), "alice", "bob"); env.fund(XRP(5000), "alice", "bob");
env(lockup("alice", "bob", XRP(1000), env.now() + 1s), ter(temDISABLED)); env(lockup("alice", "bob", XRP(1000), env.now() + 1s), ter(temDISABLED));
env(finish("bob", "alice", 1), ter(temDISABLED)); env(finish("bob", "alice", 1), ter(temDISABLED));
@@ -215,7 +215,7 @@ struct Escrow_test : public beast::unit_test::suite
} }
{ // Escrow enabled { // Escrow enabled
Env env(*this, with_only_features(featureEscrow)); Env env(*this);
env.fund(XRP(5000), "alice", "bob"); env.fund(XRP(5000), "alice", "bob");
env(lockup("alice", "bob", XRP(1000), env.now() + 1s)); env(lockup("alice", "bob", XRP(1000), env.now() + 1s));
env.close(); env.close();
@@ -237,7 +237,7 @@ struct Escrow_test : public beast::unit_test::suite
using namespace jtx; using namespace jtx;
using namespace std::chrono; using namespace std::chrono;
Env env(*this, with_only_features(featureEscrow)); Env env(*this);
auto const alice = Account("alice"); auto const alice = Account("alice");
env.fund(XRP(5000), alice, "bob"); env.fund(XRP(5000), alice, "bob");
@@ -261,7 +261,7 @@ struct Escrow_test : public beast::unit_test::suite
using namespace jtx; using namespace jtx;
using namespace std::chrono; using namespace std::chrono;
Env env(*this, with_only_features(featureEscrow)); Env env(*this);
env.fund(XRP(5000), "alice", "bob"); env.fund(XRP(5000), "alice", "bob");
env.close(); env.close();
@@ -364,7 +364,7 @@ struct Escrow_test : public beast::unit_test::suite
using namespace std::chrono; using namespace std::chrono;
{ // Unconditional { // Unconditional
Env env(*this, with_only_features(featureEscrow)); Env env(*this);
env.fund(XRP(5000), "alice", "bob"); env.fund(XRP(5000), "alice", "bob");
auto const seq = env.seq("alice"); auto const seq = env.seq("alice");
env(lockup("alice", "alice", XRP(1000), env.now() + 1s)); env(lockup("alice", "alice", XRP(1000), env.now() + 1s));
@@ -379,7 +379,7 @@ struct Escrow_test : public beast::unit_test::suite
} }
{ // Conditional { // Conditional
Env env(*this, with_only_features(featureEscrow)); Env env(*this);
env.fund(XRP(5000), "alice", "bob"); env.fund(XRP(5000), "alice", "bob");
auto const seq = env.seq("alice"); auto const seq = env.seq("alice");
env(lockup("alice", "alice", XRP(1000), makeSlice(cb2), env.now() + 1s)); env(lockup("alice", "alice", XRP(1000), makeSlice(cb2), env.now() + 1s));
@@ -411,8 +411,7 @@ struct Escrow_test : public beast::unit_test::suite
using S = seconds; using S = seconds;
{ // Test cryptoconditions { // Test cryptoconditions
Env env(*this, Env env(*this);
with_only_features(featureEscrow));
auto T = [&env](NetClock::duration const& d) auto T = [&env](NetClock::duration const& d)
{ return env.now() + d; }; { return env.now() + d; };
env.fund(XRP(5000), "alice", "bob", "carol"); env.fund(XRP(5000), "alice", "bob", "carol");
@@ -459,8 +458,7 @@ struct Escrow_test : public beast::unit_test::suite
} }
{ // Test cancel when condition is present { // Test cancel when condition is present
Env env(*this, Env env(*this);
with_only_features(featureEscrow));
auto T = [&env](NetClock::duration const& d) auto T = [&env](NetClock::duration const& d)
{ return env.now() + d; }; { return env.now() + d; };
env.fund(XRP(5000), "alice", "bob", "carol"); env.fund(XRP(5000), "alice", "bob", "carol");
@@ -477,7 +475,7 @@ struct Escrow_test : public beast::unit_test::suite
} }
{ {
Env env(*this, with_only_features(featureEscrow)); Env env(*this);
auto T = [&env](NetClock::duration const& d) auto T = [&env](NetClock::duration const& d)
{ return env.now() + d; }; { return env.now() + d; };
env.fund(XRP(5000), "alice", "bob", "carol"); env.fund(XRP(5000), "alice", "bob", "carol");
@@ -497,7 +495,7 @@ struct Escrow_test : public beast::unit_test::suite
} }
{ // Test long & short conditions during creation { // Test long & short conditions during creation
Env env(*this, with_only_features(featureEscrow)); Env env(*this);
auto T = [&env](NetClock::duration const& d) auto T = [&env](NetClock::duration const& d)
{ return env.now() + d; }; { return env.now() + d; };
env.fund(XRP(5000), "alice", "bob", "carol"); env.fund(XRP(5000), "alice", "bob", "carol");
@@ -537,8 +535,7 @@ struct Escrow_test : public beast::unit_test::suite
} }
{ // Test long and short conditions & fulfillments during finish { // Test long and short conditions & fulfillments during finish
Env env(*this, Env env(*this);
with_only_features(featureEscrow));
auto T = [&env](NetClock::duration const& d) auto T = [&env](NetClock::duration const& d)
{ return env.now() + d; }; { return env.now() + d; };
env.fund(XRP(5000), "alice", "bob", "carol"); env.fund(XRP(5000), "alice", "bob", "carol");
@@ -623,7 +620,7 @@ struct Escrow_test : public beast::unit_test::suite
{ // Test empty condition during creation and { // Test empty condition during creation and
// empty condition & fulfillment during finish // empty condition & fulfillment during finish
Env env(*this, with_only_features(featureEscrow)); Env env(*this);
auto T = [&env](NetClock::duration const& d) auto T = [&env](NetClock::duration const& d)
{ return env.now() + d; }; { return env.now() + d; };
env.fund(XRP(5000), "alice", "bob", "carol"); env.fund(XRP(5000), "alice", "bob", "carol");
@@ -663,7 +660,7 @@ struct Escrow_test : public beast::unit_test::suite
{ // Test a condition other than PreimageSha256, which { // Test a condition other than PreimageSha256, which
// would require a separate amendment // would require a separate amendment
Env env(*this, with_only_features(featureEscrow)); Env env(*this);
auto T = [&env](NetClock::duration const& d) auto T = [&env](NetClock::duration const& d)
{ return env.now() + d; }; { return env.now() + d; };
env.fund(XRP(5000), "alice", "bob", "carol"); env.fund(XRP(5000), "alice", "bob", "carol");
@@ -696,7 +693,7 @@ struct Escrow_test : public beast::unit_test::suite
{ {
testcase ("Metadata & Ownership (without fix1523)"); testcase ("Metadata & Ownership (without fix1523)");
Env env(*this, with_only_features(featureEscrow)); Env env(*this, supported_features_except (fix1523));
env.fund(XRP(5000), alice, bruce, carol); env.fund(XRP(5000), alice, bruce, carol);
auto const seq = env.seq(alice); auto const seq = env.seq(alice);
@@ -718,7 +715,7 @@ struct Escrow_test : public beast::unit_test::suite
{ {
testcase ("Metadata (with fix1523, to self)"); testcase ("Metadata (with fix1523, to self)");
Env env(*this, with_only_features(featureEscrow, fix1523)); Env env(*this);
env.fund(XRP(5000), alice, bruce, carol); env.fund(XRP(5000), alice, bruce, carol);
auto const aseq = env.seq(alice); auto const aseq = env.seq(alice);
auto const bseq = env.seq(bruce); auto const bseq = env.seq(bruce);
@@ -777,7 +774,7 @@ struct Escrow_test : public beast::unit_test::suite
{ {
testcase ("Metadata (with fix1523, to other)"); testcase ("Metadata (with fix1523, to other)");
Env env(*this, with_only_features(featureEscrow, fix1523)); Env env(*this);
env.fund(XRP(5000), alice, bruce, carol); env.fund(XRP(5000), alice, bruce, carol);
auto const aseq = env.seq(alice); auto const aseq = env.seq(alice);
auto const bseq = env.seq(bruce); auto const bseq = env.seq(bruce);
@@ -856,7 +853,7 @@ struct Escrow_test : public beast::unit_test::suite
using namespace jtx; using namespace jtx;
using namespace std::chrono; using namespace std::chrono;
Env env(*this, with_only_features(featureEscrow)); Env env(*this);
env.memoize("alice"); env.memoize("alice");
env.memoize("bob"); env.memoize("bob");

View File

@@ -56,15 +56,7 @@ xrpMinusFee (jtx::Env const& env, std::int64_t xrpAmount)
struct Flow_test : public beast::unit_test::suite struct Flow_test : public beast::unit_test::suite
{ {
static bool hasFeature(uint256 const& feat, std::initializer_list<uint256> args) void testDirectStep (FeatureBitset features)
{
for(auto const& f : args)
if (f == feat)
return true;
return false;
}
void testDirectStep (std::initializer_list<uint256> fs)
{ {
testcase ("Direct Step"); testcase ("Direct Step");
@@ -82,7 +74,7 @@ struct Flow_test : public beast::unit_test::suite
auto const USD = gw["USD"]; auto const USD = gw["USD"];
{ {
// Pay USD, trivial path // Pay USD, trivial path
Env env (*this, with_only_features(fs)); Env env (*this, features);
env.fund (XRP (10000), alice, bob, gw); env.fund (XRP (10000), alice, bob, gw);
env.trust (USD (1000), alice, bob); env.trust (USD (1000), alice, bob);
@@ -92,7 +84,7 @@ struct Flow_test : public beast::unit_test::suite
} }
{ {
// XRP transfer // XRP transfer
Env env (*this, with_only_features(fs)); Env env (*this, features);
env.fund (XRP (10000), alice, bob); env.fund (XRP (10000), alice, bob);
env (pay (alice, bob, XRP (100))); env (pay (alice, bob, XRP (100)));
@@ -101,7 +93,7 @@ struct Flow_test : public beast::unit_test::suite
} }
{ {
// Partial payments // Partial payments
Env env (*this, with_only_features(fs)); Env env (*this, features);
env.fund (XRP (10000), alice, bob, gw); env.fund (XRP (10000), alice, bob, gw);
env.trust (USD (1000), alice, bob); env.trust (USD (1000), alice, bob);
@@ -115,7 +107,7 @@ struct Flow_test : public beast::unit_test::suite
} }
{ {
// Pay by rippling through accounts, use path finder // Pay by rippling through accounts, use path finder
Env env (*this, with_only_features(fs)); Env env (*this, features);
env.fund (XRP (10000), alice, bob, carol, dan); env.fund (XRP (10000), alice, bob, carol, dan);
env.trust (USDA (10), bob); env.trust (USDA (10), bob);
@@ -130,7 +122,7 @@ struct Flow_test : public beast::unit_test::suite
{ {
// Pay by rippling through accounts, specify path // Pay by rippling through accounts, specify path
// and charge a transfer fee // and charge a transfer fee
Env env (*this, with_only_features(fs)); Env env (*this, features);
env.fund (XRP (10000), alice, bob, carol, dan); env.fund (XRP (10000), alice, bob, carol, dan);
env.trust (USDA (10), bob); env.trust (USDA (10), bob);
@@ -148,7 +140,7 @@ struct Flow_test : public beast::unit_test::suite
{ {
// Pay by rippling through accounts, specify path and transfer fee // Pay by rippling through accounts, specify path and transfer fee
// Test that the transfer fee is not charged when alice issues // Test that the transfer fee is not charged when alice issues
Env env (*this, with_only_features(fs)); Env env (*this, features);
env.fund (XRP (10000), alice, bob, carol, dan); env.fund (XRP (10000), alice, bob, carol, dan);
env.trust (USDA (10), bob); env.trust (USDA (10), bob);
@@ -164,7 +156,7 @@ struct Flow_test : public beast::unit_test::suite
{ {
// test best quality path is taken // test best quality path is taken
// Paths: A->B->D->E ; A->C->D->E // Paths: A->B->D->E ; A->C->D->E
Env env (*this, with_only_features(fs)); Env env (*this, features);
env.fund (XRP (10000), alice, bob, carol, dan, erin); env.fund (XRP (10000), alice, bob, carol, dan, erin);
env.trust (USDA (10), bob, carol); env.trust (USDA (10), bob, carol);
@@ -185,7 +177,7 @@ struct Flow_test : public beast::unit_test::suite
} }
{ {
// Limit quality // Limit quality
Env env (*this, with_only_features(fs)); Env env (*this, features);
env.fund (XRP (10000), alice, bob, carol); env.fund (XRP (10000), alice, bob, carol);
env.trust (USDA (10), bob); env.trust (USDA (10), bob);
@@ -201,7 +193,7 @@ struct Flow_test : public beast::unit_test::suite
} }
} }
void testLineQuality (std::initializer_list<uint256> fs) void testLineQuality (FeatureBitset features)
{ {
testcase ("Line Quality"); testcase ("Line Quality");
@@ -219,10 +211,10 @@ struct Flow_test : public beast::unit_test::suite
for (auto bobDanQIn : {80, 100, 120}) for (auto bobDanQIn : {80, 100, 120})
for (auto bobAliceQOut : {80, 100, 120}) for (auto bobAliceQOut : {80, 100, 120})
{ {
if (!hasFeature(featureFlow, fs) && bobDanQIn < 100 && if (!hasFeature(featureFlow, features) && bobDanQIn < 100 &&
bobAliceQOut < 100) bobAliceQOut < 100)
continue; // Bug in flow v1 continue; // Bug in flow v1
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), alice, bob, carol, dan); env.fund(XRP(10000), alice, bob, carol, dan);
env(trust(bob, USDD(100)), qualityInPercent(bobDanQIn)); env(trust(bob, USDD(100)), qualityInPercent(bobDanQIn));
env(trust(bob, USDA(100)), qualityOutPercent(bobAliceQOut)); env(trust(bob, USDA(100)), qualityOutPercent(bobAliceQOut));
@@ -245,7 +237,7 @@ struct Flow_test : public beast::unit_test::suite
// bob -> alice -> carol; vary carolAliceQIn // bob -> alice -> carol; vary carolAliceQIn
for (auto carolAliceQIn : {80, 100, 120}) for (auto carolAliceQIn : {80, 100, 120})
{ {
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), alice, bob, carol); env.fund(XRP(10000), alice, bob, carol);
env(trust(bob, USDA(10))); env(trust(bob, USDA(10)));
env(trust(carol, USDA(10)), qualityInPercent(carolAliceQIn)); env(trust(carol, USDA(10)), qualityInPercent(carolAliceQIn));
@@ -261,7 +253,7 @@ struct Flow_test : public beast::unit_test::suite
// bob -> alice -> carol; bobAliceQOut varies. // bob -> alice -> carol; bobAliceQOut varies.
for (auto bobAliceQOut : {80, 100, 120}) for (auto bobAliceQOut : {80, 100, 120})
{ {
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), alice, bob, carol); env.fund(XRP(10000), alice, bob, carol);
env(trust(bob, USDA(10)), qualityOutPercent(bobAliceQOut)); env(trust(bob, USDA(10)), qualityOutPercent(bobAliceQOut));
env(trust(carol, USDA(10))); env(trust(carol, USDA(10)));
@@ -274,7 +266,7 @@ struct Flow_test : public beast::unit_test::suite
} }
} }
void testBookStep (std::initializer_list<uint256> fs) void testBookStep (FeatureBitset features)
{ {
testcase ("Book Step"); testcase ("Book Step");
@@ -290,7 +282,7 @@ struct Flow_test : public beast::unit_test::suite
{ {
// simple IOU/IOU offer // simple IOU/IOU offer
Env env (*this, with_only_features(fs)); Env env (*this, features);
env.fund (XRP (10000), alice, bob, carol, gw); env.fund (XRP (10000), alice, bob, carol, gw);
env.trust (USD (1000), alice, bob, carol); env.trust (USD (1000), alice, bob, carol);
@@ -311,7 +303,7 @@ struct Flow_test : public beast::unit_test::suite
} }
{ {
// simple IOU/XRP XRP/IOU offer // simple IOU/XRP XRP/IOU offer
Env env (*this, with_only_features(fs)); Env env (*this, features);
env.fund (XRP (10000), alice, bob, carol, gw); env.fund (XRP (10000), alice, bob, carol, gw);
env.trust (USD (1000), alice, bob, carol); env.trust (USD (1000), alice, bob, carol);
@@ -335,7 +327,7 @@ struct Flow_test : public beast::unit_test::suite
} }
{ {
// simple XRP -> USD through offer and sendmax // simple XRP -> USD through offer and sendmax
Env env (*this, with_only_features(fs)); Env env (*this, features);
env.fund (XRP (10000), alice, bob, carol, gw); env.fund (XRP (10000), alice, bob, carol, gw);
env.trust (USD (1000), alice, bob, carol); env.trust (USD (1000), alice, bob, carol);
@@ -356,7 +348,7 @@ struct Flow_test : public beast::unit_test::suite
} }
{ {
// simple USD -> XRP through offer and sendmax // simple USD -> XRP through offer and sendmax
Env env (*this, with_only_features(fs)); Env env (*this, features);
env.fund (XRP (10000), alice, bob, carol, gw); env.fund (XRP (10000), alice, bob, carol, gw);
env.trust (USD (1000), alice, bob, carol); env.trust (USD (1000), alice, bob, carol);
@@ -377,7 +369,7 @@ struct Flow_test : public beast::unit_test::suite
} }
{ {
// test unfunded offers are removed when payment succeeds // test unfunded offers are removed when payment succeeds
Env env (*this, with_only_features(fs)); Env env (*this, features);
env.fund (XRP (10000), alice, bob, carol, gw); env.fund (XRP (10000), alice, bob, carol, gw);
env.trust (USD (1000), alice, bob, carol); env.trust (USD (1000), alice, bob, carol);
@@ -423,7 +415,7 @@ struct Flow_test : public beast::unit_test::suite
// offer. When the payment fails `flow` should return the unfunded // offer. When the payment fails `flow` should return the unfunded
// offer. This test is intentionally similar to the one that removes // offer. This test is intentionally similar to the one that removes
// unfunded offers when the payment succeeds. // unfunded offers when the payment succeeds.
Env env (*this, with_only_features(fs)); Env env (*this, features);
env.fund (XRP (10000), alice, bob, carol, gw); env.fund (XRP (10000), alice, bob, carol, gw);
env.trust (USD (1000), alice, bob, carol); env.trust (USD (1000), alice, bob, carol);
@@ -498,7 +490,7 @@ struct Flow_test : public beast::unit_test::suite
// Without limits, the 0.4 USD would produce 1000 EUR in the forward // Without limits, the 0.4 USD would produce 1000 EUR in the forward
// pass. This test checks that the payment produces 1 EUR, as expected. // pass. This test checks that the payment produces 1 EUR, as expected.
Env env (*this, with_only_features (fs)); Env env (*this, features);
auto const closeTime = STAmountSO::soTime2 + auto const closeTime = STAmountSO::soTime2 +
100 * env.closed ()->info ().closeTimeResolution; 100 * env.closed ()->info ().closeTimeResolution;
@@ -523,7 +515,7 @@ struct Flow_test : public beast::unit_test::suite
} }
} }
void testTransferRate (std::initializer_list<uint256> fs) void testTransferRate (FeatureBitset features)
{ {
testcase ("Transfer Rate"); testcase ("Transfer Rate");
@@ -541,7 +533,7 @@ struct Flow_test : public beast::unit_test::suite
{ {
// Simple payment through a gateway with a // Simple payment through a gateway with a
// transfer rate // transfer rate
Env env (*this, with_only_features(fs)); Env env (*this, features);
env.fund (XRP (10000), alice, bob, carol, gw); env.fund (XRP (10000), alice, bob, carol, gw);
env(rate(gw, 1.25)); env(rate(gw, 1.25));
@@ -553,7 +545,7 @@ struct Flow_test : public beast::unit_test::suite
} }
{ {
// transfer rate is not charged when issuer is src or dst // transfer rate is not charged when issuer is src or dst
Env env (*this, with_only_features(fs)); Env env (*this, features);
env.fund (XRP (10000), alice, bob, carol, gw); env.fund (XRP (10000), alice, bob, carol, gw);
env(rate(gw, 1.25)); env(rate(gw, 1.25));
@@ -565,7 +557,7 @@ struct Flow_test : public beast::unit_test::suite
} }
{ {
// transfer fee on an offer // transfer fee on an offer
Env env (*this, with_only_features(fs)); Env env (*this, features);
env.fund (XRP (10000), alice, bob, carol, gw); env.fund (XRP (10000), alice, bob, carol, gw);
env(rate(gw, 1.25)); env(rate(gw, 1.25));
@@ -583,7 +575,7 @@ struct Flow_test : public beast::unit_test::suite
{ {
// Transfer fee two consecutive offers // Transfer fee two consecutive offers
Env env (*this, with_only_features(fs)); Env env (*this, features);
env.fund (XRP (10000), alice, bob, carol, gw); env.fund (XRP (10000), alice, bob, carol, gw);
env(rate(gw, 1.25)); env(rate(gw, 1.25));
@@ -606,7 +598,7 @@ struct Flow_test : public beast::unit_test::suite
{ {
// First pass through a strand redeems, second pass issues, no offers // First pass through a strand redeems, second pass issues, no offers
// limiting step is not an endpoint // limiting step is not an endpoint
Env env (*this, with_only_features(fs)); Env env (*this, features);
auto const USDA = alice["USD"]; auto const USDA = alice["USD"];
auto const USDB = bob["USD"]; auto const USDB = bob["USD"];
@@ -626,7 +618,7 @@ struct Flow_test : public beast::unit_test::suite
{ {
// First pass through a strand redeems, second pass issues, through an offer // First pass through a strand redeems, second pass issues, through an offer
// limiting step is not an endpoint // limiting step is not an endpoint
Env env (*this, with_only_features(fs)); Env env (*this, features);
auto const USDA = alice["USD"]; auto const USDA = alice["USD"];
auto const USDB = bob["USD"]; auto const USDB = bob["USD"];
Account const dan ("dan"); Account const dan ("dan");
@@ -653,7 +645,7 @@ struct Flow_test : public beast::unit_test::suite
{ {
// Offer where the owner is also the issuer, owner pays fee // Offer where the owner is also the issuer, owner pays fee
Env env (*this, with_only_features(fs)); Env env (*this, features);
env.fund (XRP (10000), alice, bob, gw); env.fund (XRP (10000), alice, bob, gw);
env(rate(gw, 1.25)); env(rate(gw, 1.25));
@@ -665,10 +657,10 @@ struct Flow_test : public beast::unit_test::suite
balance (alice, xrpMinusFee(env, 10000-100)), balance (alice, xrpMinusFee(env, 10000-100)),
balance (bob, USD (100))); balance (bob, USD (100)));
} }
if (!hasFeature(featureOwnerPaysFee, fs)) if (!hasFeature(featureOwnerPaysFee, features))
{ {
// Offer where the owner is also the issuer, sender pays fee // Offer where the owner is also the issuer, sender pays fee
Env env (*this, with_only_features(fs)); Env env (*this, features);
env.fund (XRP (10000), alice, bob, gw); env.fund (XRP (10000), alice, bob, gw);
env(rate(gw, 1.25)); env(rate(gw, 1.25));
@@ -683,7 +675,7 @@ struct Flow_test : public beast::unit_test::suite
} }
void void
testFalseDry(std::initializer_list<uint256> fs) testFalseDry(FeatureBitset features)
{ {
testcase ("falseDryChanges"); testcase ("falseDryChanges");
@@ -696,7 +688,7 @@ struct Flow_test : public beast::unit_test::suite
Account const bob ("bob"); Account const bob ("bob");
Account const carol ("carol"); Account const carol ("carol");
Env env (*this, with_only_features (fs)); Env env (*this, features);
auto const closeTime = fix1141Time() + auto const closeTime = fix1141Time() +
100 * env.closed ()->info ().closeTimeResolution; 100 * env.closed ()->info ().closeTimeResolution;
@@ -793,7 +785,7 @@ struct Flow_test : public beast::unit_test::suite
} }
void void
testSelfPayment1(std::initializer_list<uint256> fs) testSelfPayment1(FeatureBitset features)
{ {
testcase ("Self-payment 1"); testcase ("Self-payment 1");
@@ -810,7 +802,7 @@ struct Flow_test : public beast::unit_test::suite
auto const USD = gw1["USD"]; auto const USD = gw1["USD"];
auto const EUR = gw2["EUR"]; auto const EUR = gw2["EUR"];
Env env (*this, with_only_features (fs)); Env env (*this, features);
auto const closeTime = auto const closeTime =
fix1141Time () + 100 * env.closed ()->info ().closeTimeResolution; fix1141Time () + 100 * env.closed ()->info ().closeTimeResolution;
@@ -869,7 +861,7 @@ struct Flow_test : public beast::unit_test::suite
} }
void void
testSelfPayment2(std::initializer_list<uint256> fs) testSelfPayment2(FeatureBitset features)
{ {
testcase ("Self-payment 2"); testcase ("Self-payment 2");
@@ -884,7 +876,7 @@ struct Flow_test : public beast::unit_test::suite
auto const USD = gw1["USD"]; auto const USD = gw1["USD"];
auto const EUR = gw2["EUR"]; auto const EUR = gw2["EUR"];
Env env (*this, with_only_features (fs)); Env env (*this, features);
auto const closeTime = auto const closeTime =
fix1141Time () + 100 * env.closed ()->info ().closeTimeResolution; fix1141Time () + 100 * env.closed ()->info ().closeTimeResolution;
@@ -941,7 +933,7 @@ struct Flow_test : public beast::unit_test::suite
BEAST_EXPECT(offer[sfTakerPays] == USD (495)); BEAST_EXPECT(offer[sfTakerPays] == USD (495));
} }
} }
void testSelfFundedXRPEndpoint (bool consumeOffer, std::initializer_list<uint256> fs) void testSelfFundedXRPEndpoint (bool consumeOffer, FeatureBitset features)
{ {
// Test that the deferred credit table is not bypassed for // Test that the deferred credit table is not bypassed for
// XRPEndpointSteps. If the account in the first step is sending XRP and // XRPEndpointSteps. If the account in the first step is sending XRP and
@@ -952,7 +944,7 @@ struct Flow_test : public beast::unit_test::suite
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(fs)); Env env(*this, features);
// Need new behavior from `accountHolds` // Need new behavior from `accountHolds`
auto const closeTime = fix1141Time() + auto const closeTime = fix1141Time() +
@@ -975,7 +967,7 @@ struct Flow_test : public beast::unit_test::suite
txflags(tfPartialPayment | tfNoRippleDirect)); txflags(tfPartialPayment | tfNoRippleDirect));
} }
void testUnfundedOffer (bool withFix, std::initializer_list<uint256> fs) void testUnfundedOffer (bool withFix, FeatureBitset features)
{ {
testcase(std::string("Unfunded Offer ") + testcase(std::string("Unfunded Offer ") +
(withFix ? "with fix" : "without fix")); (withFix ? "with fix" : "without fix"));
@@ -983,7 +975,7 @@ struct Flow_test : public beast::unit_test::suite
using namespace jtx; using namespace jtx;
{ {
// Test reverse // Test reverse
Env env(*this, with_only_features(fs)); Env env(*this, features);
auto closeTime = fix1298Time(); auto closeTime = fix1298Time();
if (withFix) if (withFix)
closeTime += env.closed()->info().closeTimeResolution; closeTime += env.closed()->info().closeTimeResolution;
@@ -1015,7 +1007,7 @@ struct Flow_test : public beast::unit_test::suite
} }
{ {
// Test forward // Test forward
Env env(*this, with_only_features(fs)); Env env(*this, features);
auto closeTime = fix1298Time(); auto closeTime = fix1298Time();
if (withFix) if (withFix)
closeTime += env.closed()->info().closeTimeResolution; closeTime += env.closed()->info().closeTimeResolution;
@@ -1050,12 +1042,12 @@ struct Flow_test : public beast::unit_test::suite
} }
void void
testReexecuteDirectStep(std::initializer_list<uint256> fs) testReexecuteDirectStep(FeatureBitset features)
{ {
testcase("ReexecuteDirectStep"); testcase("ReexecuteDirectStep");
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(fs)); Env env(*this, features);
auto const alice = Account("alice"); auto const alice = Account("alice");
auto const bob = Account("bob"); auto const bob = Account("bob");
@@ -1111,7 +1103,7 @@ struct Flow_test : public beast::unit_test::suite
testcase("ripd1443"); testcase("ripd1443");
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(featureFlow)); Env env(*this);
auto const timeDelta = env.closed ()->info ().closeTimeResolution; auto const timeDelta = env.closed ()->info ().closeTimeResolution;
auto const d = withFix ? 100*timeDelta : -100*timeDelta; auto const d = withFix ? 100*timeDelta : -100*timeDelta;
auto closeTime = fix1443Time() + d; auto closeTime = fix1443Time() + d;
@@ -1164,7 +1156,7 @@ struct Flow_test : public beast::unit_test::suite
testcase("ripd1449"); testcase("ripd1449");
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(featureFlow)); Env env(*this);
auto const timeDelta = env.closed ()->info ().closeTimeResolution; auto const timeDelta = env.closed ()->info ().closeTimeResolution;
auto const d = withFix ? 100*timeDelta : -100*timeDelta; auto const d = withFix ? 100*timeDelta : -100*timeDelta;
auto closeTime = fix1449Time() + d; auto closeTime = fix1449Time() + d;
@@ -1201,7 +1193,7 @@ struct Flow_test : public beast::unit_test::suite
} }
void void
testSelfPayLowQualityOffer (std::initializer_list<uint256> fs) testSelfPayLowQualityOffer (FeatureBitset features)
{ {
// The new payment code used to assert if an offer was made for more // The new payment code used to assert if an offer was made for more
// XRP than the offering account held. This unit test reproduces // XRP than the offering account held. This unit test reproduces
@@ -1210,7 +1202,7 @@ struct Flow_test : public beast::unit_test::suite
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features (fs)); Env env(*this, features);
auto const ann = Account("ann"); auto const ann = Account("ann");
auto const gw = Account("gateway"); auto const gw = Account("gateway");
@@ -1237,14 +1229,14 @@ struct Flow_test : public beast::unit_test::suite
} }
void void
testEmptyStrand(std::initializer_list<uint256> fs) testEmptyStrand(FeatureBitset features)
{ {
testcase("Empty Strand"); testcase("Empty Strand");
using namespace jtx; using namespace jtx;
auto const alice = Account("alice"); auto const alice = Account("alice");
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), alice); env.fund(XRP(10000), alice);
@@ -1254,32 +1246,30 @@ struct Flow_test : public beast::unit_test::suite
ter(temBAD_PATH)); ter(temBAD_PATH));
} }
template<class... T> void testWithFeats(FeatureBitset features)
void testWithFeats(bool haveFlow, T&&... fs)
{ {
testLineQuality({ fs... }); using namespace jtx;
testFalseDry({ fs... }); FeatureBitset const ownerPaysFee
if (!haveFlow) {with_only_features (featureOwnerPaysFee)};
return;
testDirectStep({ fs... });
testBookStep({ fs... });
testDirectStep({ featureOwnerPaysFee, fs... });
testBookStep({ featureOwnerPaysFee, fs... });
testTransferRate({ featureOwnerPaysFee, fs... });
testSelfPayment1({ fs... });
testSelfPayment2({ fs... });
testSelfFundedXRPEndpoint(false, { fs... });
testSelfFundedXRPEndpoint(true, { fs... });
testUnfundedOffer(true, { fs... });
testUnfundedOffer(false, { fs... });
testReexecuteDirectStep({ fix1368, fs... });
testSelfPayLowQualityOffer({ fs... });
}
template<class... T> testLineQuality(features);
void testWithFeats(T&&... fs) testFalseDry(features);
{ // Only do the rest of the tests if featureFlow is enabled.
testWithFeats(!!sizeof...(fs), fs...); if (! hasFeature (featureFlow, features))
return;
testDirectStep(features);
testBookStep(features);
testDirectStep(features | ownerPaysFee);
testBookStep(features | ownerPaysFee);
testTransferRate(features | ownerPaysFee);
testSelfPayment1(features);
testSelfPayment2(features);
testSelfFundedXRPEndpoint(false, features);
testSelfFundedXRPEndpoint(true, features);
testUnfundedOffer(true, features);
testUnfundedOffer(false, features);
testReexecuteDirectStep(features | with_only_features (fix1368));
testSelfPayLowQualityOffer(features);
} }
void run() override void run() override
@@ -1290,13 +1280,16 @@ struct Flow_test : public beast::unit_test::suite
testRIPD1449(true); testRIPD1449(true);
testRIPD1449(false); testRIPD1449(false);
testWithFeats(false, featureFeeEscalation, fix1513); using namespace jtx;
testWithFeats(featureFlow, featureFeeEscalation, fix1513); testWithFeats(
testWithFeats(featureFlow, fix1373, featureFeeEscalation, fix1513); supported_features_except (featureFlow, fix1373, featureFlowCross));
testWithFeats(featureFlow, fix1373, featureFlowCross, testWithFeats(
featureFeeEscalation, fix1513); supported_features_except ( fix1373, featureFlowCross));
testEmptyStrand({featureFlow, fix1373, featureFlowCross, testWithFeats(
featureFeeEscalation, fix1513 }); supported_features_except ( featureFlowCross));
testWithFeats(supported_amendments());
testEmptyStrand(supported_amendments());
} }
}; };
@@ -1304,31 +1297,30 @@ struct Flow_manual_test : public Flow_test
{ {
void run() override void run() override
{ {
testWithFeats(); using namespace jtx;
testWithFeats(false, auto const all = supported_amendments();
featureFeeEscalation); auto const feeEscalation = with_only_features (featureFeeEscalation);
testWithFeats(false, auto const flow = with_only_features (featureFlow);
featureFeeEscalation, fix1513); auto const f1373 = with_only_features (fix1373);
testWithFeats(featureFlow); auto const flowCross = with_only_features (featureFlowCross);
testWithFeats(featureFlow, auto const f1513 = with_only_features (fix1513);
featureFeeEscalation);
testWithFeats(featureFlow, testWithFeats(all & ~(feeEscalation | flow | f1373 | flowCross | f1513));
featureFeeEscalation, fix1513); testWithFeats(all & ~( flow | f1373 | flowCross | f1513));
testWithFeats(featureFlow, fix1373); testWithFeats(all & ~( flow | f1373 | flowCross ));
testWithFeats(featureFlow, fix1373, testWithFeats(all & ~(feeEscalation | f1373 | flowCross | f1513));
featureFeeEscalation); testWithFeats(all & ~( f1373 | flowCross | f1513));
testWithFeats(featureFlow, fix1373, testWithFeats(all & ~( f1373 | flowCross ));
featureFeeEscalation, fix1513); testWithFeats(all & ~(feeEscalation | flowCross | f1513));
testWithFeats(featureFlow, fix1373, featureFlowCross); testWithFeats(all & ~( flowCross | f1513));
testWithFeats(featureFlow, fix1373, featureFlowCross, testWithFeats(all & ~( flowCross ));
featureFeeEscalation); testWithFeats(all & ~(feeEscalation | f1513));
testWithFeats(featureFlow, fix1373, featureFlowCross, testWithFeats(all & ~( f1513));
featureFeeEscalation, fix1513); testWithFeats(all );
testEmptyStrand({ featureFlow, fix1373, featureFlowCross });
testEmptyStrand({ featureFlow, fix1373, featureFlowCross, testEmptyStrand(all & ~(feeEscalation | f1513));
featureFeeEscalation }); testEmptyStrand(all & ~( f1513));
testEmptyStrand({ featureFlow, fix1373, featureFlowCross, testEmptyStrand(all );
featureFeeEscalation, fix1513 });
} }
}; };

View File

@@ -53,12 +53,12 @@ class Freeze_test : public beast::unit_test::suite
return val.isArray() && val.size() == size; return val.isArray() && val.size() == size;
} }
void testRippleState(std::initializer_list<uint256> fs) void testRippleState(FeatureBitset features)
{ {
testcase("RippleState Freeze"); testcase("RippleState Freeze");
using namespace test::jtx; using namespace test::jtx;
Env env(*this, with_only_features(fs)); Env env(*this, features);
Account G1 {"G1"}; Account G1 {"G1"};
Account alice {"alice"}; Account alice {"alice"};
@@ -207,12 +207,12 @@ class Freeze_test : public beast::unit_test::suite
} }
void void
testGlobalFreeze(std::initializer_list<uint256> fs) testGlobalFreeze(FeatureBitset features)
{ {
testcase("Global Freeze"); testcase("Global Freeze");
using namespace test::jtx; using namespace test::jtx;
Env env(*this, with_only_features(fs)); Env env(*this, features);
Account G1 {"G1"}; Account G1 {"G1"};
Account A1 {"A1"}; Account A1 {"A1"};
@@ -365,12 +365,12 @@ class Freeze_test : public beast::unit_test::suite
} }
void void
testNoFreeze(std::initializer_list<uint256> fs) testNoFreeze(FeatureBitset features)
{ {
testcase("No Freeze"); testcase("No Freeze");
using namespace test::jtx; using namespace test::jtx;
Env env(*this, with_only_features(fs)); Env env(*this, features);
Account G1 {"G1"}; Account G1 {"G1"};
Account A1 {"A1"}; Account A1 {"A1"};
@@ -419,12 +419,12 @@ class Freeze_test : public beast::unit_test::suite
} }
void void
testOffersWhenFrozen(std::initializer_list<uint256> fs) testOffersWhenFrozen(FeatureBitset features)
{ {
testcase("Offers for Frozen Trust Lines"); testcase("Offers for Frozen Trust Lines");
using namespace test::jtx; using namespace test::jtx;
Env env(*this, with_only_features(fs)); Env env(*this, features);
Account G1 {"G1"}; Account G1 {"G1"};
Account A2 {"A2"}; Account A2 {"A2"};
@@ -523,21 +523,23 @@ public:
void run() void run()
{ {
auto testAll = [this](std::initializer_list<uint256> fs) auto testAll = [this](FeatureBitset features)
{ {
testRippleState(fs); testRippleState(features);
testGlobalFreeze(fs); testGlobalFreeze(features);
testNoFreeze(fs); testNoFreeze(features);
testOffersWhenFrozen(fs); testOffersWhenFrozen(features);
}; };
testAll({}); using namespace test::jtx;
testAll({featureFlow}); testAll(
testAll({featureFlow, fix1373}); supported_features_except (featureFlow, fix1373, featureFlowCross));
testAll({featureFlow, fix1373, featureFlowCross}); testAll(
supported_features_except ( fix1373, featureFlowCross));
testAll(
supported_features_except ( featureFlowCross));
testAll(supported_amendments());
} }
}; };
BEAST_DEFINE_TESTSUITE(Freeze, app, ripple); BEAST_DEFINE_TESTSUITE(Freeze, app, ripple);
} // ripple } // ripple

View File

@@ -39,7 +39,7 @@ public:
void test_noReserve() void test_noReserve()
{ {
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(featureMultiSign)); Env env(*this);
Account const alice {"alice", KeyType::secp256k1}; Account const alice {"alice", KeyType::secp256k1};
// Pay alice enough to meet the initial reserve, but not enough to // Pay alice enough to meet the initial reserve, but not enough to
@@ -87,7 +87,7 @@ public:
void test_signerListSet() void test_signerListSet()
{ {
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(featureMultiSign)); Env env(*this);
Account const alice {"alice", KeyType::ed25519}; Account const alice {"alice", KeyType::ed25519};
env.fund(XRP(1000), alice); env.fund(XRP(1000), alice);
@@ -132,7 +132,7 @@ public:
void test_phantomSigners() void test_phantomSigners()
{ {
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(featureMultiSign)); Env env(*this);
Account const alice {"alice", KeyType::ed25519}; Account const alice {"alice", KeyType::ed25519};
env.fund(XRP(1000), alice); env.fund(XRP(1000), alice);
env.close(); env.close();
@@ -233,7 +233,7 @@ public:
void test_fee () void test_fee ()
{ {
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(featureMultiSign)); Env env(*this);
Account const alice {"alice", KeyType::ed25519}; Account const alice {"alice", KeyType::ed25519};
env.fund(XRP(1000), alice); env.fund(XRP(1000), alice);
env.close(); env.close();
@@ -283,7 +283,7 @@ public:
void test_misorderedSigners() void test_misorderedSigners()
{ {
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(featureMultiSign)); Env env(*this);
Account const alice {"alice", KeyType::ed25519}; Account const alice {"alice", KeyType::ed25519};
env.fund(XRP(1000), alice); env.fund(XRP(1000), alice);
env.close(); env.close();
@@ -305,7 +305,7 @@ public:
void test_masterSigners() void test_masterSigners()
{ {
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(featureMultiSign)); Env env(*this);
Account const alice {"alice", KeyType::ed25519}; Account const alice {"alice", KeyType::ed25519};
Account const becky {"becky", KeyType::secp256k1}; Account const becky {"becky", KeyType::secp256k1};
Account const cheri {"cheri", KeyType::ed25519}; Account const cheri {"cheri", KeyType::ed25519};
@@ -357,7 +357,7 @@ public:
void test_regularSigners() void test_regularSigners()
{ {
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(featureMultiSign)); Env env(*this);
Account const alice {"alice", KeyType::secp256k1}; Account const alice {"alice", KeyType::secp256k1};
Account const becky {"becky", KeyType::ed25519}; Account const becky {"becky", KeyType::ed25519};
Account const cheri {"cheri", KeyType::secp256k1}; Account const cheri {"cheri", KeyType::secp256k1};
@@ -415,7 +415,7 @@ public:
void test_regularSignersUsingSubmitMulti() void test_regularSignersUsingSubmitMulti()
{ {
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(featureMultiSign)); Env env(*this);
Account const alice {"alice", KeyType::secp256k1}; Account const alice {"alice", KeyType::secp256k1};
Account const becky {"becky", KeyType::ed25519}; Account const becky {"becky", KeyType::ed25519};
Account const cheri {"cheri", KeyType::secp256k1}; Account const cheri {"cheri", KeyType::secp256k1};
@@ -618,7 +618,7 @@ public:
void test_heterogeneousSigners() void test_heterogeneousSigners()
{ {
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(featureMultiSign)); Env env(*this);
Account const alice {"alice", KeyType::secp256k1}; Account const alice {"alice", KeyType::secp256k1};
Account const becky {"becky", KeyType::ed25519}; Account const becky {"becky", KeyType::ed25519};
Account const cheri {"cheri", KeyType::secp256k1}; Account const cheri {"cheri", KeyType::secp256k1};
@@ -733,7 +733,7 @@ public:
void test_keyDisable() void test_keyDisable()
{ {
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(featureMultiSign)); Env env(*this);
Account const alice {"alice", KeyType::ed25519}; Account const alice {"alice", KeyType::ed25519};
env.fund(XRP(1000), alice); env.fund(XRP(1000), alice);
@@ -808,7 +808,7 @@ public:
void test_regKey() void test_regKey()
{ {
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(featureMultiSign)); Env env(*this);
Account const alice {"alice", KeyType::secp256k1}; Account const alice {"alice", KeyType::secp256k1};
env.fund(XRP(1000), alice); env.fund(XRP(1000), alice);
@@ -840,7 +840,7 @@ public:
void test_txTypes() void test_txTypes()
{ {
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(featureMultiSign)); Env env(*this);
Account const alice {"alice", KeyType::secp256k1}; Account const alice {"alice", KeyType::secp256k1};
Account const becky {"becky", KeyType::ed25519}; Account const becky {"becky", KeyType::ed25519};
Account const zelda {"zelda", KeyType::secp256k1}; Account const zelda {"zelda", KeyType::secp256k1};
@@ -924,7 +924,7 @@ public:
// Verify that the text returned for signature failures is correct. // Verify that the text returned for signature failures is correct.
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(featureMultiSign)); Env env(*this);
// lambda that submits an STTx and returns the resulting JSON. // lambda that submits an STTx and returns the resulting JSON.
auto submitSTTx = [&env] (STTx const& stx) auto submitSTTx = [&env] (STTx const& stx)
@@ -1058,7 +1058,7 @@ public:
void test_noMultiSigners() void test_noMultiSigners()
{ {
using namespace jtx; using namespace jtx;
Env env {*this, with_only_features(featureMultiSign)}; Env env {*this};
Account const alice {"alice", KeyType::ed25519}; Account const alice {"alice", KeyType::ed25519};
Account const becky {"becky", KeyType::secp256k1}; Account const becky {"becky", KeyType::secp256k1};
env.fund(XRP(1000), alice, becky); env.fund(XRP(1000), alice, becky);

File diff suppressed because it is too large Load Diff

View File

@@ -35,7 +35,10 @@ public:
{ {
using namespace jtx; using namespace jtx;
for (std::size_t i = 1; i <= n; ++i) for (std::size_t i = 1; i <= n; ++i)
{
env(offer("alice", XRP(i), iou(1))); env(offer("alice", XRP(i), iou(1)));
env.close();
}
} }
void void
@@ -47,8 +50,8 @@ public:
env.disable_sigs(); env.disable_sigs();
auto const gw = Account("gateway"); auto const gw = Account("gateway");
auto const USD = gw["USD"]; auto const USD = gw["USD"];
env.fund(XRP(billion), gw, "alice", "bob", "carol"); env.fund(XRP(billion), gw, "alice");
env.trust(USD(billion), "alice", "bob", "carol"); env.trust(USD(billion), "alice");
env(pay(gw, "alice", USD(billion))); env(pay(gw, "alice", USD(billion)));
createOffers(env, USD, n); createOffers(env, USD, n);
} }
@@ -88,7 +91,10 @@ public:
{ {
using namespace jtx; using namespace jtx;
for (std::size_t i = 1; i <= n; ++i) for (std::size_t i = 1; i <= n; ++i)
{
env(offer("alice", XRP(1), iou(1))); env(offer("alice", XRP(1), iou(1)));
env.close();
}
} }
void void
@@ -101,8 +107,8 @@ public:
env.disable_sigs(); env.disable_sigs();
auto const gw = Account("gateway"); auto const gw = Account("gateway");
auto const USD = gw["USD"]; auto const USD = gw["USD"];
env.fund(XRP(billion), gw, "alice", "bob", "carol"); env.fund(XRP(billion), gw, "alice");
env.trust(USD(billion), "alice", "bob", "carol"); env.trust(USD(billion), "alice");
env(pay(gw, "alice", USD(billion))); env(pay(gw, "alice", USD(billion)));
createOffers(env, USD, n); createOffers(env, USD, n);
env(pay("alice", gw, USD(billion))); env(pay("alice", gw, USD(billion)));
@@ -151,7 +157,10 @@ public:
{ {
using namespace jtx; using namespace jtx;
for (std::size_t i = 1; i <= n; ++i) for (std::size_t i = 1; i <= n; ++i)
{
env(offer("alice", XRP(i), iou(1))); env(offer("alice", XRP(i), iou(1)));
env.close();
}
} }
bool bool
@@ -163,8 +172,8 @@ public:
env.disable_sigs(); env.disable_sigs();
auto const gw = Account("gateway"); auto const gw = Account("gateway");
auto const USD = gw["USD"]; auto const USD = gw["USD"];
env.fund(XRP(billion), gw, "alice", "bob", "carol"); env.fund(XRP(billion), gw, "alice");
env.trust(USD(billion), "alice", "bob", "carol"); env.trust(USD(billion), "alice");
env(pay(gw, "alice", USD(billion))); env(pay(gw, "alice", USD(billion)));
createOffers(env, USD, n); createOffers(env, USD, n);
env(pay("alice", gw, USD(billion))); env(pay("alice", gw, USD(billion)));

View File

@@ -625,14 +625,14 @@ struct PayStrandAllPairs_test : public beast::unit_test::suite
{ {
// Test every combination of element type pairs on a path // Test every combination of element type pairs on a path
void void
testAllPairs(std::initializer_list<uint256> fs) testAllPairs(FeatureBitset features)
{ {
testcase("All pairs"); testcase("All pairs");
using namespace jtx; using namespace jtx;
using RippleCalc = ::ripple::path::RippleCalc; using RippleCalc = ::ripple::path::RippleCalc;
ExistingElementPool eep; ExistingElementPool eep;
Env env(*this, with_only_features(fs)); Env env(*this, features);
auto const closeTime = fix1298Time() + auto const closeTime = fix1298Time() +
100 * env.closed()->info().closeTimeResolution; 100 * env.closed()->info().closeTimeResolution;
@@ -847,8 +847,8 @@ struct PayStrandAllPairs_test : public beast::unit_test::suite
void void
run() override run() override
{ {
testAllPairs({featureFlow, fix1373}); testAllPairs(jtx::supported_features_except (featureFlowCross));
testAllPairs({featureFlow, fix1373, featureFlowCross}); testAllPairs(jtx::supported_amendments());
} }
}; };
@@ -856,15 +856,8 @@ BEAST_DEFINE_TESTSUITE_MANUAL(PayStrandAllPairs, app, ripple);
struct PayStrand_test : public beast::unit_test::suite struct PayStrand_test : public beast::unit_test::suite
{ {
static bool hasFeature(uint256 const& feat, std::initializer_list<uint256> args)
{
for(auto const& f : args)
if (f == feat)
return true;
return false;
}
void void
testToStrand(std::initializer_list<uint256> fs) testToStrand(FeatureBitset features)
{ {
testcase("To Strand"); testcase("To Strand");
@@ -910,7 +903,7 @@ struct PayStrand_test : public beast::unit_test::suite
}; };
{ {
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), alice, bob, gw); env.fund(XRP(10000), alice, bob, gw);
env.trust(USD(1000), alice, bob); env.trust(USD(1000), alice, bob);
env.trust(EUR(1000), alice, bob); env.trust(EUR(1000), alice, bob);
@@ -951,7 +944,7 @@ struct PayStrand_test : public beast::unit_test::suite
}; };
{ {
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), alice, bob, carol, gw); env.fund(XRP(10000), alice, bob, carol, gw);
test(env, USD, boost::none, STPath(), terNO_LINE); test(env, USD, boost::none, STPath(), terNO_LINE);
@@ -1134,7 +1127,7 @@ struct PayStrand_test : public beast::unit_test::suite
// cannot have more than one offer with the same output issue // cannot have more than one offer with the same output issue
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), alice, bob, carol, gw); env.fund(XRP(10000), alice, bob, carol, gw);
env.trust(USD(10000), alice, bob, carol); env.trust(USD(10000), alice, bob, carol);
@@ -1156,7 +1149,7 @@ struct PayStrand_test : public beast::unit_test::suite
} }
{ {
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), alice, bob, noripple(gw)); env.fund(XRP(10000), alice, bob, noripple(gw));
env.trust(USD(1000), alice, bob); env.trust(USD(1000), alice, bob);
env(pay(gw, alice, USD(100))); env(pay(gw, alice, USD(100)));
@@ -1165,7 +1158,7 @@ struct PayStrand_test : public beast::unit_test::suite
{ {
// check global freeze // check global freeze
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), alice, bob, gw); env.fund(XRP(10000), alice, bob, gw);
env.trust(USD(1000), alice, bob); env.trust(USD(1000), alice, bob);
env(pay(gw, alice, USD(100))); env(pay(gw, alice, USD(100)));
@@ -1190,7 +1183,7 @@ struct PayStrand_test : public beast::unit_test::suite
} }
{ {
// Freeze between gw and alice // Freeze between gw and alice
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), alice, bob, gw); env.fund(XRP(10000), alice, bob, gw);
env.trust(USD(1000), alice, bob); env.trust(USD(1000), alice, bob);
env(pay(gw, alice, USD(100))); env(pay(gw, alice, USD(100)));
@@ -1203,7 +1196,7 @@ struct PayStrand_test : public beast::unit_test::suite
// check no auth // check no auth
// An account may require authorization to receive IOUs from an // An account may require authorization to receive IOUs from an
// issuer // issuer
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), alice, bob, gw); env.fund(XRP(10000), alice, bob, gw);
env(fset(gw, asfRequireAuth)); env(fset(gw, asfRequireAuth));
env.trust(USD(1000), alice, bob); env.trust(USD(1000), alice, bob);
@@ -1231,7 +1224,7 @@ struct PayStrand_test : public beast::unit_test::suite
} }
{ {
// Check path with sendMax and node with correct sendMax already set // Check path with sendMax and node with correct sendMax already set
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), alice, bob, gw); env.fund(XRP(10000), alice, bob, gw);
env.trust(USD(1000), alice, bob); env.trust(USD(1000), alice, bob);
env.trust(EUR(1000), alice, bob); env.trust(EUR(1000), alice, bob);
@@ -1246,7 +1239,7 @@ struct PayStrand_test : public beast::unit_test::suite
{ {
// last step xrp from offer // last step xrp from offer
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), alice, bob, gw); env.fund(XRP(10000), alice, bob, gw);
env.trust(USD(1000), alice, bob); env.trust(USD(1000), alice, bob);
env(pay(gw, alice, USD(100))); env(pay(gw, alice, USD(100)));
@@ -1273,7 +1266,7 @@ struct PayStrand_test : public beast::unit_test::suite
} }
void void
testRIPD1373(std::initializer_list<uint256> fs) testRIPD1373(FeatureBitset features)
{ {
using namespace jtx; using namespace jtx;
testcase("RIPD1373"); testcase("RIPD1373");
@@ -1285,9 +1278,9 @@ struct PayStrand_test : public beast::unit_test::suite
auto const USD = gw["USD"]; auto const USD = gw["USD"];
auto const EUR = gw["EUR"]; auto const EUR = gw["EUR"];
if (hasFeature(fix1373, fs)) if (hasFeature(fix1373, features))
{ {
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), alice, bob, gw); env.fund(XRP(10000), alice, bob, gw);
env.trust(USD(1000), alice, bob); env.trust(USD(1000), alice, bob);
@@ -1319,7 +1312,7 @@ struct PayStrand_test : public beast::unit_test::suite
} }
{ {
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), alice, bob, carol, gw); env.fund(XRP(10000), alice, bob, carol, gw);
env.trust(USD(10000), alice, bob, carol); env.trust(USD(10000), alice, bob, carol);
@@ -1337,7 +1330,7 @@ struct PayStrand_test : public beast::unit_test::suite
} }
{ {
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), alice, bob, carol, gw); env.fund(XRP(10000), alice, bob, carol, gw);
env.trust(USD(10000), alice, bob, carol); env.trust(USD(10000), alice, bob, carol);
@@ -1357,7 +1350,7 @@ struct PayStrand_test : public beast::unit_test::suite
} }
void void
testLoop(std::initializer_list<uint256> fs) testLoop(FeatureBitset features)
{ {
testcase("test loop"); testcase("test loop");
using namespace jtx; using namespace jtx;
@@ -1371,7 +1364,7 @@ struct PayStrand_test : public beast::unit_test::suite
auto const CNY = gw["CNY"]; auto const CNY = gw["CNY"];
{ {
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), alice, bob, carol, gw); env.fund(XRP(10000), alice, bob, carol, gw);
env.trust(USD(10000), alice, bob, carol); env.trust(USD(10000), alice, bob, carol);
@@ -1383,8 +1376,8 @@ struct PayStrand_test : public beast::unit_test::suite
env(offer(bob, USD(100), XRP(100)), txflags(tfPassive)); env(offer(bob, USD(100), XRP(100)), txflags(tfPassive));
auto const expectedResult = [&] { auto const expectedResult = [&] {
if (hasFeature(featureFlow, fs) && if (hasFeature(featureFlow, features) &&
!hasFeature(fix1373, fs)) !hasFeature(fix1373, features))
return tesSUCCESS; return tesSUCCESS;
return temBAD_PATH_LOOP; return temBAD_PATH_LOOP;
}(); }();
@@ -1396,7 +1389,7 @@ struct PayStrand_test : public beast::unit_test::suite
ter(expectedResult)); ter(expectedResult));
} }
{ {
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), alice, bob, carol, gw); env.fund(XRP(10000), alice, bob, carol, gw);
env.trust(USD(10000), alice, bob, carol); env.trust(USD(10000), alice, bob, carol);
@@ -1421,7 +1414,7 @@ struct PayStrand_test : public beast::unit_test::suite
} }
void void
testNoAccount(std::initializer_list<uint256> fs) testNoAccount(FeatureBitset features)
{ {
testcase("test no account"); testcase("test no account");
using namespace jtx; using namespace jtx;
@@ -1431,7 +1424,7 @@ struct PayStrand_test : public beast::unit_test::suite
auto const gw = Account("gw"); auto const gw = Account("gw");
auto const USD = gw["USD"]; auto const USD = gw["USD"];
Env env(*this, with_only_features(fs)); Env env(*this, features);
env.fund(XRP(10000), alice, bob, gw); env.fund(XRP(10000), alice, bob, gw);
STAmount sendMax{USD.issue(), 100, 1}; STAmount sendMax{USD.issue(), 100, 1};
@@ -1479,17 +1472,26 @@ struct PayStrand_test : public beast::unit_test::suite
void void
run() override run() override
{ {
testToStrand({featureFlow}); using namespace jtx;
testToStrand({featureFlow, fix1373}); testToStrand(supported_features_except (fix1373, featureFlowCross));
testToStrand({featureFlow, fix1373, featureFlowCross}); testToStrand(supported_features_except ( featureFlowCross));
testRIPD1373({}); testToStrand(supported_amendments ());
testRIPD1373({featureFlow, fix1373});
testRIPD1373({featureFlow, fix1373, featureFlowCross}); testRIPD1373(
testLoop({}); supported_features_except (featureFlow, fix1373, featureFlowCross));
testLoop({featureFlow}); testRIPD1373(
testLoop({featureFlow, fix1373}); supported_features_except ( featureFlowCross));
testLoop({featureFlow, fix1373, featureFlowCross}); testRIPD1373(supported_amendments ());
testNoAccount({featureFlow, fix1373});
testLoop(
supported_features_except (featureFlow, fix1373, featureFlowCross));
testLoop(
supported_features_except ( fix1373, featureFlowCross));
testLoop(
supported_features_except ( featureFlowCross));
testLoop(supported_amendments ());
testNoAccount(supported_amendments ());
} }
}; };

View File

@@ -170,8 +170,7 @@ struct Regression_test : public beast::unit_test::suite
cfg->section("transaction_queue") cfg->section("transaction_queue")
.set("minimum_txn_in_ledger_standalone", "3"); .set("minimum_txn_in_ledger_standalone", "3");
return cfg; return cfg;
}), }));
with_features(featureFeeEscalation, fix1513));
Env_ss envs(env); Env_ss envs(env);
auto const alice = Account("alice"); auto const alice = Account("alice");

View File

@@ -46,19 +46,23 @@ struct SetAuth_test : public beast::unit_test::suite
return jv; return jv;
} }
void testAuth(std::initializer_list<uint256> fs) void testAuth(FeatureBitset features)
{ {
// featureTrustSetAuth should always be set by the caller.
BEAST_EXPECT (hasFeature (featureTrustSetAuth, features));
using namespace jtx; using namespace jtx;
auto const gw = Account("gw"); auto const gw = Account("gw");
auto const USD = gw["USD"]; auto const USD = gw["USD"];
{ {
Env env(*this, with_only_features(fs)); Env env(*this, features & ~with_only_features(featureTrustSetAuth));
env.fund(XRP(100000), "alice", gw); env.fund(XRP(100000), "alice", gw);
env(fset(gw, asfRequireAuth)); env(fset(gw, asfRequireAuth));
env(auth(gw, "alice", "USD"), ter(tecNO_LINE_REDUNDANT)); env(auth(gw, "alice", "USD"), ter(tecNO_LINE_REDUNDANT));
} }
{ {
Env env(*this, with_only_features(featureTrustSetAuth)); Env env(*this, features);
env.fund(XRP(100000), "alice", "bob", gw); env.fund(XRP(100000), "alice", "bob", gw);
env(fset(gw, asfRequireAuth)); env(fset(gw, asfRequireAuth));
env(auth(gw, "alice", "USD")); env(auth(gw, "alice", "USD"));
@@ -75,10 +79,14 @@ struct SetAuth_test : public beast::unit_test::suite
void run() override void run() override
{ {
testAuth({}); using namespace jtx;
testAuth({featureFlow}); testAuth(supported_features_except (
testAuth({featureFlow, fix1373}); featureFlow, fix1373, featureFlowCross));
testAuth({featureFlow, fix1373, featureFlowCross}); testAuth(supported_features_except (
fix1373, featureFlowCross));
testAuth(supported_features_except (
featureFlowCross));
testAuth(supported_amendments());
} }
}; };

View File

@@ -126,7 +126,7 @@ class Ticket_test : public beast::unit_test::suite
testcase ("Cancel Nonexistent"); testcase ("Cancel Nonexistent");
using namespace test::jtx; using namespace test::jtx;
Env env {*this, with_only_features (featureTickets)}; Env env {*this, supported_features_plus (featureTickets)};
env (ticket::cancel (env.master, idOne), ter (tecNO_ENTRY)); env (ticket::cancel (env.master, idOne), ter (tecNO_ENTRY));
} }
@@ -135,7 +135,7 @@ class Ticket_test : public beast::unit_test::suite
testcase ("Create/Cancel Ticket with Bad Fee, Fail Preflight"); testcase ("Create/Cancel Ticket with Bad Fee, Fail Preflight");
using namespace test::jtx; using namespace test::jtx;
Env env {*this, with_only_features (featureTickets)}; Env env {*this, supported_features_plus (featureTickets)};
env (ticket::create (env.master), fee (XRP (-1)), ter (temBAD_FEE)); env (ticket::create (env.master), fee (XRP (-1)), ter (temBAD_FEE));
env (ticket::cancel (env.master, idOne), fee (XRP (-1)), ter (temBAD_FEE)); env (ticket::cancel (env.master, idOne), fee (XRP (-1)), ter (temBAD_FEE));
@@ -146,7 +146,7 @@ class Ticket_test : public beast::unit_test::suite
testcase ("Create Tickets with Nonexistent Accounts"); testcase ("Create Tickets with Nonexistent Accounts");
using namespace test::jtx; using namespace test::jtx;
Env env {*this, with_only_features (featureTickets)}; Env env {*this, supported_features_plus (featureTickets)};
Account alice {"alice"}; Account alice {"alice"};
env.memoize (alice); env.memoize (alice);
@@ -162,7 +162,7 @@ class Ticket_test : public beast::unit_test::suite
testcase ("Create Tickets with Same Account and Target"); testcase ("Create Tickets with Same Account and Target");
using namespace test::jtx; using namespace test::jtx;
Env env {*this, with_only_features (featureTickets)}; Env env {*this, supported_features_plus (featureTickets)};
env (ticket::create (env.master, env.master)); env (ticket::create (env.master, env.master));
auto cr = checkTicketMeta (env); auto cr = checkTicketMeta (env);
@@ -183,7 +183,7 @@ class Ticket_test : public beast::unit_test::suite
testcase ("Create Ticket and Then Cancel by Creator"); testcase ("Create Ticket and Then Cancel by Creator");
using namespace test::jtx; using namespace test::jtx;
Env env {*this, with_only_features (featureTickets)}; Env env {*this, supported_features_plus (featureTickets)};
// create and verify // create and verify
env (ticket::create (env.master)); env (ticket::create (env.master));
@@ -215,7 +215,7 @@ class Ticket_test : public beast::unit_test::suite
testcase ("Create Ticket Insufficient Reserve"); testcase ("Create Ticket Insufficient Reserve");
using namespace test::jtx; using namespace test::jtx;
Env env {*this, with_only_features (featureTickets)}; Env env {*this, supported_features_plus (featureTickets)};
Account alice {"alice"}; Account alice {"alice"};
env.fund (env.current ()->fees ().accountReserve (0), alice); env.fund (env.current ()->fees ().accountReserve (0), alice);
@@ -229,7 +229,7 @@ class Ticket_test : public beast::unit_test::suite
testcase ("Create Ticket and Then Cancel by Target"); testcase ("Create Ticket and Then Cancel by Target");
using namespace test::jtx; using namespace test::jtx;
Env env {*this, with_only_features (featureTickets)}; Env env {*this, supported_features_plus (featureTickets)};
Account alice {"alice"}; Account alice {"alice"};
env.fund (XRP (10000), alice); env.fund (XRP (10000), alice);
@@ -275,7 +275,7 @@ class Ticket_test : public beast::unit_test::suite
testcase ("Create Ticket with Future Expiration"); testcase ("Create Ticket with Future Expiration");
using namespace test::jtx; using namespace test::jtx;
Env env {*this, with_only_features (featureTickets)}; Env env {*this, supported_features_plus (featureTickets)};
// create and verify // create and verify
uint32_t expire = uint32_t expire =
@@ -300,7 +300,7 @@ class Ticket_test : public beast::unit_test::suite
testcase ("Create Ticket with Zero Expiration"); testcase ("Create Ticket with Zero Expiration");
using namespace test::jtx; using namespace test::jtx;
Env env {*this, with_only_features (featureTickets)}; Env env {*this, supported_features_plus (featureTickets)};
// create and verify // create and verify
env (ticket::create (env.master, 0u), ter (temBAD_EXPIRATION)); env (ticket::create (env.master, 0u), ter (temBAD_EXPIRATION));
@@ -311,7 +311,7 @@ class Ticket_test : public beast::unit_test::suite
testcase ("Create Ticket with Past Expiration"); testcase ("Create Ticket with Past Expiration");
using namespace test::jtx; using namespace test::jtx;
Env env {*this, with_only_features (featureTickets)}; Env env {*this, supported_features_plus (featureTickets)};
env.timeKeeper ().adjustCloseTime (days {2}); env.timeKeeper ().adjustCloseTime (days {2});
env.close (); env.close ();
@@ -340,7 +340,7 @@ class Ticket_test : public beast::unit_test::suite
testcase ("Create Ticket and Allow to Expire"); testcase ("Create Ticket and Allow to Expire");
using namespace test::jtx; using namespace test::jtx;
Env env {*this, with_only_features (featureTickets)}; Env env {*this, supported_features_plus (featureTickets)};
// create and verify // create and verify
uint32_t expire = uint32_t expire =

View File

@@ -46,12 +46,12 @@ class TrustAndBalance_test : public beast::unit_test::suite
}; };
void void
testPayNonexistent (std::initializer_list<uint256> fs) testPayNonexistent (FeatureBitset features)
{ {
testcase ("Payment to Nonexistent Account"); testcase ("Payment to Nonexistent Account");
using namespace test::jtx; using namespace test::jtx;
Env env {*this, with_only_features(fs)}; Env env {*this, features};
env (pay (env.master, "alice", XRP(1)), ter(tecNO_DST_INSUF_XRP)); env (pay (env.master, "alice", XRP(1)), ter(tecNO_DST_INSUF_XRP));
env.close(); env.close();
} }
@@ -162,12 +162,12 @@ class TrustAndBalance_test : public beast::unit_test::suite
} }
void void
testDirectRipple (std::initializer_list<uint256> fs) testDirectRipple (FeatureBitset features)
{ {
testcase ("Direct Payment, Ripple"); testcase ("Direct Payment, Ripple");
using namespace test::jtx; using namespace test::jtx;
Env env {*this, with_only_features(fs)}; Env env {*this, features};
Account alice {"alice"}; Account alice {"alice"};
Account bob {"bob"}; Account bob {"bob"};
@@ -203,14 +203,14 @@ class TrustAndBalance_test : public beast::unit_test::suite
} }
void void
testWithTransferFee (bool subscribe, bool with_rate, std::initializer_list<uint256> fs) testWithTransferFee (bool subscribe, bool with_rate, FeatureBitset features)
{ {
testcase(std::string("Direct Payment: ") + testcase(std::string("Direct Payment: ") +
(with_rate ? "With " : "Without ") + " Xfer Fee, " + (with_rate ? "With " : "Without ") + " Xfer Fee, " +
(subscribe ? "With " : "Without ") + " Subscribe"); (subscribe ? "With " : "Without ") + " Subscribe");
using namespace test::jtx; using namespace test::jtx;
Env env {*this, with_only_features(fs)}; Env env {*this, features};
auto wsc = test::makeWSClient(env.app().config()); auto wsc = test::makeWSClient(env.app().config());
Account gw {"gateway"}; Account gw {"gateway"};
Account alice {"alice"}; Account alice {"alice"};
@@ -283,12 +283,12 @@ class TrustAndBalance_test : public beast::unit_test::suite
} }
void void
testWithPath (std::initializer_list<uint256> fs) testWithPath (FeatureBitset features)
{ {
testcase ("Payments With Paths and Fees"); testcase ("Payments With Paths and Fees");
using namespace test::jtx; using namespace test::jtx;
Env env {*this, with_only_features(fs)}; Env env {*this, features};
Account gw {"gateway"}; Account gw {"gateway"};
Account alice {"alice"}; Account alice {"alice"};
Account bob {"bob"}; Account bob {"bob"};
@@ -331,12 +331,12 @@ class TrustAndBalance_test : public beast::unit_test::suite
} }
void void
testIndirect (std::initializer_list<uint256> fs) testIndirect (FeatureBitset features)
{ {
testcase ("Indirect Payment"); testcase ("Indirect Payment");
using namespace test::jtx; using namespace test::jtx;
Env env {*this, with_only_features(fs)}; Env env {*this, features};
Account gw {"gateway"}; Account gw {"gateway"};
Account alice {"alice"}; Account alice {"alice"};
Account bob {"bob"}; Account bob {"bob"};
@@ -372,13 +372,13 @@ class TrustAndBalance_test : public beast::unit_test::suite
} }
void void
testIndirectMultiPath (bool with_rate, std::initializer_list<uint256> fs) testIndirectMultiPath (bool with_rate, FeatureBitset features)
{ {
testcase (std::string("Indirect Payment, Multi Path, ") + testcase (std::string("Indirect Payment, Multi Path, ") +
(with_rate ? "With " : "Without ") + " Xfer Fee, "); (with_rate ? "With " : "Without ") + " Xfer Fee, ");
using namespace test::jtx; using namespace test::jtx;
Env env {*this, with_only_features(fs)}; Env env {*this, features};
Account gw {"gateway"}; Account gw {"gateway"};
Account amazon {"amazon"}; Account amazon {"amazon"};
Account alice {"alice"}; Account alice {"alice"};
@@ -438,12 +438,12 @@ class TrustAndBalance_test : public beast::unit_test::suite
} }
void void
testInvoiceID (std::initializer_list<uint256> fs) testInvoiceID (FeatureBitset features)
{ {
testcase ("Set Invoice ID on Payment"); testcase ("Set Invoice ID on Payment");
using namespace test::jtx; using namespace test::jtx;
Env env {*this, with_only_features(fs)}; Env env {*this, features};
Account alice {"alice"}; Account alice {"alice"};
auto wsc = test::makeWSClient(env.app().config()); auto wsc = test::makeWSClient(env.app().config());
@@ -493,23 +493,28 @@ public:
testTrustNonexistent (); testTrustNonexistent ();
testCreditLimit (); testCreditLimit ();
auto testWithFeatures = [this](std::initializer_list<uint256> fs) { auto testWithFeatures = [this](FeatureBitset features) {
testPayNonexistent(fs); testPayNonexistent(features);
testDirectRipple(fs); testDirectRipple(features);
testWithTransferFee(false, false, fs); testWithTransferFee(false, false, features);
testWithTransferFee(false, true, fs); testWithTransferFee(false, true, features);
testWithTransferFee(true, false, fs); testWithTransferFee(true, false, features);
testWithTransferFee(true, true, fs); testWithTransferFee(true, true, features);
testWithPath(fs); testWithPath(features);
testIndirect(fs); testIndirect(features);
testIndirectMultiPath(true, fs); testIndirectMultiPath(true, features);
testIndirectMultiPath(false, fs); testIndirectMultiPath(false, features);
testInvoiceID(fs); testInvoiceID(features);
}; };
testWithFeatures({});
testWithFeatures({featureFlow}); using namespace test::jtx;
testWithFeatures({featureFlow, fix1373}); testWithFeatures(
testWithFeatures({featureFlow, fix1373, featureFlowCross}); supported_features_except (featureFlow, fix1373, featureFlowCross));
testWithFeatures(
supported_features_except ( fix1373, featureFlowCross));
testWithFeatures(
supported_features_except ( featureFlowCross));
testWithFeatures(supported_amendments());
} }
}; };

View File

@@ -162,8 +162,8 @@ public:
using namespace jtx; using namespace jtx;
using namespace std::chrono; using namespace std::chrono;
Env env(*this, makeConfig({ {"minimum_txn_in_ledger_standalone", "3"} }), Env env(*this,
with_features(featureFeeEscalation, fix1513)); makeConfig({ {"minimum_txn_in_ledger_standalone", "3"} }));
auto& txq = env.app().getTxQ(); auto& txq = env.app().getTxQ();
auto alice = Account("alice"); auto alice = Account("alice");
@@ -349,8 +349,8 @@ public:
using namespace jtx; using namespace jtx;
using namespace std::chrono; using namespace std::chrono;
Env env(*this, makeConfig({ { "minimum_txn_in_ledger_standalone", "2" } }), Env env(*this,
with_features(featureFeeEscalation, fix1513)); makeConfig({ { "minimum_txn_in_ledger_standalone", "2" } }));
auto alice = Account("alice"); auto alice = Account("alice");
auto bob = Account("bob"); auto bob = Account("bob");
@@ -405,8 +405,8 @@ public:
using namespace jtx; using namespace jtx;
using namespace std::chrono; using namespace std::chrono;
Env env(*this, makeConfig({ { "minimum_txn_in_ledger_standalone", "2" } }), Env env(*this,
with_features(featureFeeEscalation, fix1513)); makeConfig({ { "minimum_txn_in_ledger_standalone", "2" } }));
auto alice = Account("alice"); auto alice = Account("alice");
auto bob = Account("bob"); auto bob = Account("bob");
@@ -513,8 +513,8 @@ public:
using namespace jtx; using namespace jtx;
using namespace std::chrono; using namespace std::chrono;
Env env(*this, makeConfig({ { "minimum_txn_in_ledger_standalone", "2" } }), Env env(*this,
with_features(featureFeeEscalation, fix1513)); makeConfig({ { "minimum_txn_in_ledger_standalone", "2" } }));
auto alice = Account("alice"); auto alice = Account("alice");
auto bob = Account("bob"); auto bob = Account("bob");
@@ -620,7 +620,7 @@ public:
{ {
using namespace jtx; using namespace jtx;
Env env(*this, makeConfig(), with_features(featureFeeEscalation, fix1513)); Env env(*this, makeConfig());
auto alice = Account("alice"); auto alice = Account("alice");
auto bob = Account("bob"); auto bob = Account("bob");
@@ -644,8 +644,8 @@ public:
{ {
using namespace jtx; using namespace jtx;
Env env(*this, makeConfig({ { "minimum_txn_in_ledger_standalone", "2" } }), Env env(*this,
with_features(featureFeeEscalation, fix1513)); makeConfig({ { "minimum_txn_in_ledger_standalone", "2" } }));
auto alice = Account("alice"); auto alice = Account("alice");
auto bob = Account("bob"); auto bob = Account("bob");
@@ -701,8 +701,7 @@ public:
Env env(*this, Env env(*this,
makeConfig( makeConfig(
{{"minimum_txn_in_ledger_standalone", "3"}}, {{"minimum_txn_in_ledger_standalone", "3"}},
{{"account_reserve", "200"}, {"owner_reserve", "50"}}), {{"account_reserve", "200"}, {"owner_reserve", "50"}}));
with_features(featureFeeEscalation, fix1513));
auto alice = Account("alice"); auto alice = Account("alice");
auto bob = Account("bob"); auto bob = Account("bob");
@@ -929,8 +928,8 @@ public:
using namespace jtx; using namespace jtx;
using namespace std::chrono; using namespace std::chrono;
Env env(*this, makeConfig({ { "minimum_txn_in_ledger_standalone", "4" } }), Env env(*this,
with_features(featureFeeEscalation, fix1513)); makeConfig({ { "minimum_txn_in_ledger_standalone", "4" } }));
auto alice = Account("alice"); auto alice = Account("alice");
auto bob = Account("bob"); auto bob = Account("bob");
@@ -1088,8 +1087,8 @@ public:
{ {
using namespace jtx; using namespace jtx;
Env env(*this, makeConfig({ { "minimum_txn_in_ledger_standalone", "1" } }), Env env(*this,
with_features(featureFeeEscalation, fix1513)); makeConfig({ { "minimum_txn_in_ledger_standalone", "1" } }));
auto alice = Account("alice"); auto alice = Account("alice");
@@ -1131,8 +1130,7 @@ public:
Env env(*this, makeConfig( Env env(*this, makeConfig(
{ {"minimum_txn_in_ledger_standalone", "2"}, { {"minimum_txn_in_ledger_standalone", "2"},
{"target_txn_in_ledger", "4"}, {"target_txn_in_ledger", "4"},
{"maximum_txn_in_ledger", "5"} }), {"maximum_txn_in_ledger", "5"} }));
with_features(featureFeeEscalation, fix1513));
auto alice = Account("alice"); auto alice = Account("alice");
auto queued = ter(terQUEUED); auto queued = ter(terQUEUED);
@@ -1161,8 +1159,7 @@ public:
*this, *this,
makeConfig( makeConfig(
{{"minimum_txn_in_ledger_standalone", "3"}}, {{"minimum_txn_in_ledger_standalone", "3"}},
{{"account_reserve", "200"}, {"owner_reserve", "50"}}), {{"account_reserve", "200"}, {"owner_reserve", "50"}}));
with_features(featureFeeEscalation, fix1513));
auto alice = Account("alice"); auto alice = Account("alice");
auto bob = Account("bob"); auto bob = Account("bob");
@@ -1251,8 +1248,7 @@ public:
using namespace jtx; using namespace jtx;
Env env(*this, Env env(*this,
makeConfig({ { "minimum_txn_in_ledger_standalone", "3" } }), makeConfig({ { "minimum_txn_in_ledger_standalone", "3" } }));
with_features(featureFeeEscalation, featureMultiSign, fix1513));
auto alice = Account("alice"); auto alice = Account("alice");
auto bob = Account("bob"); auto bob = Account("bob");
@@ -1316,8 +1312,7 @@ public:
using namespace jtx; using namespace jtx;
Env env(*this, Env env(*this,
makeConfig({ { "minimum_txn_in_ledger_standalone", "3" } }), makeConfig({ { "minimum_txn_in_ledger_standalone", "3" } }));
with_features(featureFeeEscalation, featureTickets, fix1513));
auto alice = Account("alice"); auto alice = Account("alice");
auto charlie = Account("charlie"); auto charlie = Account("charlie");
@@ -1562,7 +1557,7 @@ public:
{ {
using namespace jtx; using namespace jtx;
using namespace std::chrono; using namespace std::chrono;
Env env(*this, with_only_features(featureTickets)); Env env(*this, supported_features_plus (featureTickets));
auto const alice = Account("alice"); auto const alice = Account("alice");
env.memoize(alice); env.memoize(alice);
env.memoize("bob"); env.memoize("bob");
@@ -1630,7 +1625,7 @@ public:
{ {
using namespace jtx; using namespace jtx;
{ {
Env env(*this, with_features(featureFeeEscalation, fix1513)); Env env(*this);
auto fee = env.rpc("fee"); auto fee = env.rpc("fee");
@@ -1718,8 +1713,7 @@ public:
using namespace jtx; using namespace jtx;
Env env(*this, makeConfig({ { "minimum_txn_in_ledger_standalone", "1" }, Env env(*this, makeConfig({ { "minimum_txn_in_ledger_standalone", "1" },
{"ledgers_in_queue", "10"}, {"maximum_txn_per_account", "20"} }), {"ledgers_in_queue", "10"}, {"maximum_txn_per_account", "20"} }));
with_features(featureFeeEscalation, fix1513));
// Alice will recreate the scenario. Bob will block. // Alice will recreate the scenario. Bob will block.
auto const alice = Account("alice"); auto const alice = Account("alice");
@@ -1793,8 +1787,8 @@ public:
{ {
testcase("Autofilled sequence should account for TxQ"); testcase("Autofilled sequence should account for TxQ");
using namespace jtx; using namespace jtx;
Env env(*this, makeConfig({ {"minimum_txn_in_ledger_standalone", "6"} }), Env env(*this,
with_features(featureFeeEscalation, fix1513)); makeConfig({ {"minimum_txn_in_ledger_standalone", "6"} }));
Env_ss envs(env); Env_ss envs(env);
auto const& txQ = env.app().getTxQ(); auto const& txQ = env.app().getTxQ();
@@ -1923,8 +1917,8 @@ public:
void testAccountInfo() void testAccountInfo()
{ {
using namespace jtx; using namespace jtx;
Env env(*this, makeConfig({ { "minimum_txn_in_ledger_standalone", "3" } }), Env env(*this,
with_features(featureFeeEscalation, fix1513)); makeConfig({ { "minimum_txn_in_ledger_standalone", "3" } }));
Env_ss envs(env); Env_ss envs(env);
Account const alice{ "alice" }; Account const alice{ "alice" };
@@ -2193,8 +2187,8 @@ public:
void testServerInfo() void testServerInfo()
{ {
using namespace jtx; using namespace jtx;
Env env(*this, makeConfig({ { "minimum_txn_in_ledger_standalone", "3" } }), Env env(*this,
with_features(featureFeeEscalation, fix1513)); makeConfig({ { "minimum_txn_in_ledger_standalone", "3" } }));
Env_ss envs(env); Env_ss envs(env);
Account const alice{ "alice" }; Account const alice{ "alice" };
@@ -2416,8 +2410,8 @@ public:
{ {
using namespace jtx; using namespace jtx;
Env env(*this, makeConfig({ { "minimum_txn_in_ledger_standalone", "3" } }), Env env(*this,
with_features(featureFeeEscalation, fix1513)); makeConfig({ { "minimum_txn_in_ledger_standalone", "3" } }));
Json::Value stream; Json::Value stream;
stream[jss::streams] = Json::arrayValue; stream[jss::streams] = Json::arrayValue;
@@ -2585,8 +2579,7 @@ public:
using namespace jtx; using namespace jtx;
Env env(*this, Env env(*this,
makeConfig({ { "minimum_txn_in_ledger_standalone", "3" } }), makeConfig({ { "minimum_txn_in_ledger_standalone", "3" } }));
with_features(featureFeeEscalation, fix1513));
auto alice = Account("alice"); auto alice = Account("alice");
auto bob = Account("bob"); auto bob = Account("bob");

View File

@@ -151,6 +151,37 @@ supported_features_except (uint256 const& key, Args const&... args)
std::array<uint256, 1 + sizeof...(args)>{{key, args...}}); std::array<uint256, 1 + sizeof...(args)>{{key, args...}});
} }
/**
* @brief create collection of features to pass to Env ctor
*
* The resulting collection will contain *all supported amendments* plus
* the features passed as arguments.
*
* @param keys features to include in the resulting collection
*/
template<class Col>
FeatureBitset
supported_features_plus (Col const& keys)
{
return supported_amendments() | makeFeatureBitset(keys);
}
/**
*
* @brief create collection of features to pass to Env ctor
* The resulting collection will contain *all supported amendments* plus
* the features passed as arguments.
*
* @param key+args features to include in the resulting collection
*/
template <class... Args>
FeatureBitset
supported_features_plus (uint256 const& key, Args const&... args)
{
return supported_features_plus(
std::array<uint256, 1 + sizeof...(args)>{{key, args...}});
}
class SuiteSink : public beast::Journal::Sink class SuiteSink : public beast::Journal::Sink
{ {
std::string partition_; std::string partition_;

View File

@@ -355,7 +355,7 @@ public:
{ {
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(featureMultiSign)); Env env(*this);
env.fund(XRP(10000), "alice"); env.fund(XRP(10000), "alice");
env(signers("alice", 1, env(signers("alice", 1,
{ { "alice", 1 }, { "bob", 2 } }), ter(temBAD_SIGNER)); { { "alice", 1 }, { "bob", 2 } }), ter(temBAD_SIGNER));
@@ -384,7 +384,7 @@ public:
ticket::create("alice", 60, "bob"); ticket::create("alice", 60, "bob");
{ {
Env env(*this, with_only_features(featureTickets)); Env env(*this, supported_features_plus (featureTickets));
env.fund(XRP(10000), "alice"); env.fund(XRP(10000), "alice");
env(noop("alice"), require(owners("alice", 0), tickets("alice", 0))); env(noop("alice"), require(owners("alice", 0), tickets("alice", 0)));
env(ticket::create("alice"), require(owners("alice", 1), tickets("alice", 1))); env(ticket::create("alice"), require(owners("alice", 1), tickets("alice", 1)));

View File

@@ -25,10 +25,10 @@ namespace test {
struct BookDirs_test : public beast::unit_test::suite struct BookDirs_test : public beast::unit_test::suite
{ {
void test_bookdir(std::initializer_list<uint256> fs) void test_bookdir(FeatureBitset features)
{ {
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(fs)); Env env(*this, features);
auto gw = Account("gw"); auto gw = Account("gw");
auto USD = gw["USD"]; auto USD = gw["USD"];
env.fund(XRP(1000000), "alice", "bob", "gw"); env.fund(XRP(1000000), "alice", "bob", "gw");
@@ -94,9 +94,12 @@ struct BookDirs_test : public beast::unit_test::suite
void run() override void run() override
{ {
test_bookdir({}); using namespace jtx;
test_bookdir({featureFlow, fix1373}); test_bookdir(
test_bookdir({featureFlow, fix1373, featureFlowCross}); supported_features_except (featureFlow, fix1373, featureFlowCross));
test_bookdir(
supported_features_except ( featureFlowCross));
test_bookdir(supported_amendments ());
} }
}; };

View File

@@ -116,7 +116,7 @@ struct Directory_test : public beast::unit_test::suite
{ {
testcase ("Directory Ordering (with 'SortedDirectories' amendment)"); testcase ("Directory Ordering (with 'SortedDirectories' amendment)");
Env env(*this, with_only_features(featureSortedDirectories)); Env env(*this);
env.fund(XRP(10000000), alice, gw); env.fund(XRP(10000000), alice, gw);
for (std::size_t i = 1; i <= 400; ++i) for (std::size_t i = 1; i <= 400; ++i)
@@ -184,8 +184,7 @@ struct Directory_test : public beast::unit_test::suite
beast::xor_shift_engine eng; beast::xor_shift_engine eng;
Env env(*this, Env env(*this);
with_only_features(featureSortedDirectories, featureMultiSign));
env.fund(XRP(1000000), alice, charlie, gw); env.fund(XRP(1000000), alice, charlie, gw);
env.close(); env.close();
@@ -289,7 +288,7 @@ struct Directory_test : public beast::unit_test::suite
testcase("RIPD-1353 Empty Offer Directories"); testcase("RIPD-1353 Empty Offer Directories");
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(featureSortedDirectories)); Env env(*this);
auto const gw = Account{"gateway"}; auto const gw = Account{"gateway"};
auto const alice = Account{"alice"}; auto const alice = Account{"alice"};
@@ -349,7 +348,7 @@ struct Directory_test : public beast::unit_test::suite
testcase("Empty Chain on Delete"); testcase("Empty Chain on Delete");
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(featureSortedDirectories)); Env env(*this);
auto const gw = Account{"gateway"}; auto const gw = Account{"gateway"};
auto const alice = Account{"alice"}; auto const alice = Account{"alice"};

View File

@@ -55,12 +55,12 @@ class PaymentSandbox_test : public beast::unit_test::suite
2) New code: Path is dry because sender does not have any 2) New code: Path is dry because sender does not have any
GW1 to spend until the end of the transaction. GW1 to spend until the end of the transaction.
*/ */
void testSelfFunding (std::initializer_list<uint256> fs) void testSelfFunding (FeatureBitset features)
{ {
testcase ("selfFunding"); testcase ("selfFunding");
using namespace jtx; using namespace jtx;
Env env (*this, with_only_features(fs)); Env env (*this, features);
Account const gw1 ("gw1"); Account const gw1 ("gw1");
Account const gw2 ("gw2"); Account const gw2 ("gw2");
Account const snd ("snd"); Account const snd ("snd");
@@ -96,12 +96,12 @@ class PaymentSandbox_test : public beast::unit_test::suite
env.require (balance ("rcv", USD_gw2 (2))); env.require (balance ("rcv", USD_gw2 (2)));
} }
void testSubtractCredits (std::initializer_list<uint256> fs) void testSubtractCredits (FeatureBitset features)
{ {
testcase ("subtractCredits"); testcase ("subtractCredits");
using namespace jtx; using namespace jtx;
Env env (*this, with_only_features(fs)); Env env (*this, features);
Account const gw1 ("gw1"); Account const gw1 ("gw1");
Account const gw2 ("gw2"); Account const gw2 ("gw2");
Account const alice ("alice"); Account const alice ("alice");
@@ -256,7 +256,7 @@ class PaymentSandbox_test : public beast::unit_test::suite
} }
} }
void testTinyBalance (std::initializer_list<uint256> fs) void testTinyBalance (FeatureBitset features)
{ {
testcase ("Tiny balance"); testcase ("Tiny balance");
@@ -266,7 +266,7 @@ class PaymentSandbox_test : public beast::unit_test::suite
using namespace jtx; using namespace jtx;
Env env (*this, with_only_features(fs)); Env env (*this, features);
Account const gw ("gw"); Account const gw ("gw");
Account const alice ("alice"); Account const alice ("alice");
@@ -293,7 +293,7 @@ class PaymentSandbox_test : public beast::unit_test::suite
} }
} }
void testReserve(std::initializer_list<uint256> fs) void testReserve(FeatureBitset features)
{ {
testcase ("Reserve"); testcase ("Reserve");
using namespace jtx; using namespace jtx;
@@ -312,7 +312,7 @@ class PaymentSandbox_test : public beast::unit_test::suite
return env.current ()->fees ().accountReserve (count); return env.current ()->fees ().accountReserve (count);
}; };
Env env (*this, with_only_features(fs)); Env env (*this, features);
Account const alice ("alice"); Account const alice ("alice");
env.fund (reserve(env, 1), alice); env.fund (reserve(env, 1), alice);
@@ -333,14 +333,14 @@ class PaymentSandbox_test : public beast::unit_test::suite
} }
} }
void testBalanceHook(std::initializer_list<uint256> fs) void testBalanceHook(FeatureBitset features)
{ {
// Make sure the Issue::Account returned by PAymentSandbox::balanceHook // Make sure the Issue::Account returned by PAymentSandbox::balanceHook
// is correct. // is correct.
testcase ("balanceHook"); testcase ("balanceHook");
using namespace jtx; using namespace jtx;
Env env (*this, with_only_features(fs)); Env env (*this, features);
Account const gw ("gw"); Account const gw ("gw");
auto const USD = gw["USD"]; auto const USD = gw["USD"];
@@ -370,16 +370,19 @@ class PaymentSandbox_test : public beast::unit_test::suite
public: public:
void run () void run ()
{ {
auto testAll = [this](std::initializer_list<uint256> fs) { auto testAll = [this](FeatureBitset features) {
testSelfFunding(fs); testSelfFunding(features);
testSubtractCredits(fs); testSubtractCredits(features);
testTinyBalance(fs); testTinyBalance(features);
testReserve(fs); testReserve(features);
testBalanceHook(fs); testBalanceHook(features);
}; };
testAll({}); using namespace jtx;
testAll({featureFlow, fix1373}); testAll(
testAll({featureFlow, fix1373, featureFlowCross}); supported_features_except (featureFlow, fix1373, featureFlowCross));
testAll(
supported_features_except ( featureFlowCross));
testAll(supported_amendments());
} }
}; };

View File

@@ -59,7 +59,7 @@ public:
void testSignerLists() void testSignerLists()
{ {
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(featureMultiSign)); Env env(*this);
Account const alice {"alice"}; Account const alice {"alice"};
env.fund(XRP(1000), alice); env.fund(XRP(1000), alice);
@@ -165,7 +165,7 @@ public:
void testSignerListsV2() void testSignerListsV2()
{ {
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(featureMultiSign)); Env env(*this);
Account const alice {"alice"}; Account const alice {"alice"};
env.fund(XRP(1000), alice); env.fund(XRP(1000), alice);

View File

@@ -371,7 +371,7 @@ public:
void testRequireAuthWithDir() void testRequireAuthWithDir()
{ {
using namespace test::jtx; using namespace test::jtx;
Env env(*this, with_only_features(featureMultiSign)); Env env(*this);
Account const alice ("alice"); Account const alice ("alice");
Account const bob ("bob"); Account const bob ("bob");

View File

@@ -117,10 +117,6 @@ class Feature_test : public beast::unit_test::suite
using namespace test::jtx; using namespace test::jtx;
Env env {*this, Env env {*this,
with_only_features(featureEscrow, featureCryptoConditions)}; with_only_features(featureEscrow, featureCryptoConditions)};
// The amendment table has to be modified
// since that is what feature RPC actually checks
env.app().getAmendmentTable().enable(featureEscrow);
env.app().getAmendmentTable().enable(featureCryptoConditions);
auto jrr = env.rpc("feature") [jss::result]; auto jrr = env.rpc("feature") [jss::result];
if(! BEAST_EXPECT(jrr.isMember(jss::features))) if(! BEAST_EXPECT(jrr.isMember(jss::features)))
@@ -221,9 +217,6 @@ class Feature_test : public beast::unit_test::suite
using namespace test::jtx; using namespace test::jtx;
Env env {*this, Env env {*this,
with_only_features(featureCryptoConditions)}; with_only_features(featureCryptoConditions)};
// The amendment table has to be modified
// since that is what feature RPC actually checks
env.app().getAmendmentTable().enable(featureCryptoConditions);
auto jrr = env.rpc("feature", "CryptoConditions") [jss::result]; auto jrr = env.rpc("feature", "CryptoConditions") [jss::result];
if(! BEAST_EXPECTS(jrr[jss::status] == jss::success, "status")) if(! BEAST_EXPECTS(jrr[jss::status] == jss::success, "status"))

View File

@@ -30,11 +30,11 @@ class GatewayBalances_test : public beast::unit_test::suite
public: public:
void void
testGWB(std::initializer_list<uint256> fs) testGWB(FeatureBitset features)
{ {
using namespace std::chrono_literals; using namespace std::chrono_literals;
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(fs)); Env env(*this, features);
// Gateway account and assets // Gateway account and assets
Account const alice {"alice"}; Account const alice {"alice"};
@@ -153,9 +153,12 @@ public:
void void
run() override run() override
{ {
testGWB({}); using namespace jtx;
testGWB({featureFlow, fix1373}); testGWB(
testGWB({featureFlow, fix1373, featureFlowCross}); supported_features_except (featureFlow, fix1373, featureFlowCross));
testGWB(
supported_features_except ( featureFlowCross));
testGWB(supported_amendments());
} }
}; };

View File

@@ -1941,8 +1941,7 @@ public:
cfg->section("transaction_queue") cfg->section("transaction_queue")
.set("minimum_txn_in_ledger_standalone", "3"); .set("minimum_txn_in_ledger_standalone", "3");
return cfg; return cfg;
}), })};
with_features(featureFeeEscalation, fix1513)};
LoadFeeTrack const& feeTrack = env.app().getFeeTrack(); LoadFeeTrack const& feeTrack = env.app().getFeeTrack();
{ {
@@ -2254,8 +2253,7 @@ public:
// "b" (not in the ledger) is rDg53Haik2475DJx8bjMDSDPj4VX7htaMd. // "b" (not in the ledger) is rDg53Haik2475DJx8bjMDSDPj4VX7htaMd.
// "c" (phantom signer) is rPcNzota6B8YBokhYtcTNqQVCngtbnWfux. // "c" (phantom signer) is rPcNzota6B8YBokhYtcTNqQVCngtbnWfux.
test::jtx::Env env(*this, test::jtx::Env env(*this);
test::jtx::with_only_features(featureMultiSign));
env.fund(test::jtx::XRP(100000), a, ed, g); env.fund(test::jtx::XRP(100000), a, ed, g);
env.close(); env.close();

View File

@@ -268,8 +268,8 @@ public:
using namespace test::jtx; using namespace test::jtx;
using namespace std::chrono; using namespace std::chrono;
Env env { *this, envconfig(validator, ""), Env env { *this, envconfig(validator, ""),
with_only_features(featureMultiSign, featureTickets, supported_features_plus(featureTickets) };
featureEscrow, featurePayChan) };
Account const gw { "gateway" }; Account const gw { "gateway" };
auto const USD = gw["USD"]; auto const USD = gw["USD"];
env.fund(XRP(100000), gw); env.fund(XRP(100000), gw);

View File

@@ -476,8 +476,7 @@ class LedgerRPC_test : public beast::unit_test::suite
cfg->section("transaction_queue") cfg->section("transaction_queue")
.set("minimum_txn_in_ledger_standalone", "3"); .set("minimum_txn_in_ledger_standalone", "3");
return cfg; return cfg;
}), })};
with_features(featureFeeEscalation, fix1513)};
Json::Value jv; Json::Value jv;
jv[jss::ledger_index] = "current"; jv[jss::ledger_index] = "current";

View File

@@ -67,12 +67,12 @@ public:
} }
} }
void testNegativeBalance(std::initializer_list<uint256> fs) void testNegativeBalance(FeatureBitset features)
{ {
testcase("Set noripple on a line with negative balance"); testcase("Set noripple on a line with negative balance");
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(fs)); Env env(*this, features);
auto const gw = Account("gateway"); auto const gw = Account("gateway");
auto const alice = Account("alice"); auto const alice = Account("alice");
@@ -113,12 +113,12 @@ public:
BEAST_EXPECT(!lines[0u].isMember(jss::no_ripple)); BEAST_EXPECT(!lines[0u].isMember(jss::no_ripple));
} }
void testPairwise(std::initializer_list<uint256> fs) void testPairwise(FeatureBitset features)
{ {
testcase("pairwise NoRipple"); testcase("pairwise NoRipple");
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(fs)); Env env(*this, features);
auto const alice = Account("alice"); auto const alice = Account("alice");
auto const bob = Account("bob"); auto const bob = Account("bob");
@@ -150,12 +150,12 @@ public:
env(pay(alice, carol, bob["USD"](50)), ter(tecPATH_DRY)); env(pay(alice, carol, bob["USD"](50)), ter(tecPATH_DRY));
} }
void testDefaultRipple(std::initializer_list<uint256> fs) void testDefaultRipple(FeatureBitset features)
{ {
testcase("Set default ripple on an account and check new trustlines"); testcase("Set default ripple on an account and check new trustlines");
using namespace jtx; using namespace jtx;
Env env(*this, with_only_features(fs)); Env env(*this, features);
auto const gw = Account("gateway"); auto const gw = Account("gateway");
auto const alice = Account("alice"); auto const alice = Account("alice");
@@ -212,15 +212,19 @@ public:
{ {
testSetAndClear(); testSetAndClear();
auto withFeatsTests = [this](std::initializer_list<uint256> fs) { auto withFeatsTests = [this](FeatureBitset features) {
testNegativeBalance(fs); testNegativeBalance(features);
testPairwise(fs); testPairwise(features);
testDefaultRipple(fs); testDefaultRipple(features);
}; };
withFeatsTests({}); using namespace jtx;
withFeatsTests({featureFlow}); withFeatsTests(
withFeatsTests({featureFlow, fix1373}); supported_features_except (featureFlow, fix1373, featureFlowCross));
withFeatsTests({featureFlow, fix1373, featureFlowCross}); withFeatsTests(
supported_features_except ( fix1373, featureFlowCross));
withFeatsTests(
supported_features_except ( featureFlowCross));
withFeatsTests(supported_amendments());
} }
}; };