mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 11:05:54 +00:00
revise tests
This commit is contained in:
committed by
Bronek Kozicki
parent
ea30f44247
commit
12646cb89e
@@ -20,10 +20,12 @@
|
|||||||
#ifndef RIPPLE_JSON_JSON_VALUE_H_INCLUDED
|
#ifndef RIPPLE_JSON_JSON_VALUE_H_INCLUDED
|
||||||
#define RIPPLE_JSON_JSON_VALUE_H_INCLUDED
|
#define RIPPLE_JSON_JSON_VALUE_H_INCLUDED
|
||||||
|
|
||||||
|
#include <xrpl/basics/Number.h>
|
||||||
#include <xrpl/json/json_forwards.h>
|
#include <xrpl/json/json_forwards.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
/** \brief JSON (JavaScript Object Notation).
|
/** \brief JSON (JavaScript Object Notation).
|
||||||
@@ -237,6 +239,11 @@ public:
|
|||||||
Value&
|
Value&
|
||||||
operator=(Value&& other);
|
operator=(Value&& other);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
requires(!std::convertible_to<T, Value>)
|
||||||
|
Value&
|
||||||
|
operator=(T const& rhs);
|
||||||
|
|
||||||
Value(Value&& other) noexcept;
|
Value(Value&& other) noexcept;
|
||||||
|
|
||||||
/// Swap values.
|
/// Swap values.
|
||||||
@@ -682,6 +689,51 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// https://ericniebler.com/2014/10/21/customization-point-design-in-c11-and-beyond/
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
inline Value
|
||||||
|
to_json(ripple::Number const& number)
|
||||||
|
{
|
||||||
|
return to_string(number);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct to_json_fn
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
constexpr Value
|
||||||
|
operator()(T&& t) const
|
||||||
|
{
|
||||||
|
return to_json(std::forward<T>(t));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct static_const
|
||||||
|
{
|
||||||
|
static constexpr T value{};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr T static_const<T>::value;
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr auto const& to_json = detail::static_const<detail::to_json_fn>::value;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
requires(!std::convertible_to<T, Value>)
|
||||||
|
Value&
|
||||||
|
Value::operator=(T const& rhs)
|
||||||
|
{
|
||||||
|
*this = to_json(rhs);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
#endif // CPPTL_JSON_H_INCLUDED
|
#endif // CPPTL_JSON_H_INCLUDED
|
||||||
|
|||||||
@@ -29,11 +29,166 @@
|
|||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
|
using namespace test::jtx;
|
||||||
|
|
||||||
class Vault_test : public beast::unit_test::suite
|
class Vault_test : public beast::unit_test::suite
|
||||||
{
|
{
|
||||||
|
void
|
||||||
|
testSequence(
|
||||||
|
Env& env,
|
||||||
|
Account const& issuer,
|
||||||
|
Account const& owner,
|
||||||
|
Account const& depositor,
|
||||||
|
Vault& vault,
|
||||||
|
PrettyAsset const& asset)
|
||||||
|
{
|
||||||
|
auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
|
||||||
|
env(tx);
|
||||||
|
env.close();
|
||||||
|
BEAST_EXPECT(env.le(keylet));
|
||||||
|
|
||||||
|
{
|
||||||
|
testcase("fail to deposit more than assets held");
|
||||||
|
auto tx = vault.deposit(
|
||||||
|
{.depositor = depositor,
|
||||||
|
.id = keylet.key,
|
||||||
|
.amount = asset(10000)});
|
||||||
|
env(tx, ter(tecINSUFFICIENT_FUNDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
testcase("deposit non-zero amount");
|
||||||
|
auto tx = vault.deposit(
|
||||||
|
{.depositor = depositor,
|
||||||
|
.id = keylet.key,
|
||||||
|
.amount = asset(100)});
|
||||||
|
env(tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
testcase("fail to delete non-empty vault");
|
||||||
|
auto tx = vault.del({.owner = owner, .id = keylet.key});
|
||||||
|
env(tx, ter(tecHAS_OBLIGATIONS));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
testcase("fail to update because wrong owner");
|
||||||
|
auto tx = vault.set({.owner = issuer, .id = keylet.key});
|
||||||
|
env(tx, ter(tecNO_PERMISSION));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
testcase("fail to update immutable flags");
|
||||||
|
auto tx = vault.set({.owner = owner, .id = keylet.key});
|
||||||
|
tx[sfFlags] = tfVaultPrivate;
|
||||||
|
env(tx, ter(temINVALID_FLAG));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
testcase("fail to set maximum lower than current amount");
|
||||||
|
auto tx = vault.set({.owner = owner, .id = keylet.key});
|
||||||
|
tx[sfAssetMaximum] = asset(50).number();
|
||||||
|
env(tx, ter(tecLIMIT_EXCEEDED));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
testcase("set maximum higher than current amount");
|
||||||
|
auto tx = vault.set({.owner = owner, .id = keylet.key});
|
||||||
|
tx[sfAssetMaximum] = asset(200).number();
|
||||||
|
env(tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
testcase("fail to deposit more than maximum");
|
||||||
|
auto tx = vault.deposit(
|
||||||
|
{.depositor = depositor,
|
||||||
|
.id = keylet.key,
|
||||||
|
.amount = asset(200)});
|
||||||
|
env(tx, ter(tecLIMIT_EXCEEDED));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
testcase("fail to withdraw more than assets held");
|
||||||
|
auto tx = vault.withdraw(
|
||||||
|
{.depositor = depositor,
|
||||||
|
.id = keylet.key,
|
||||||
|
.amount = asset(1000)});
|
||||||
|
env(tx, ter(tecINSUFFICIENT_FUNDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
testcase("deposit up to maximum");
|
||||||
|
auto tx = vault.deposit(
|
||||||
|
{.depositor = depositor,
|
||||||
|
.id = keylet.key,
|
||||||
|
.amount = asset(100)});
|
||||||
|
env(tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: redeem.
|
||||||
|
|
||||||
|
{
|
||||||
|
testcase("withdraw non-zero assets");
|
||||||
|
auto tx = vault.withdraw(
|
||||||
|
{.depositor = depositor,
|
||||||
|
.id = keylet.key,
|
||||||
|
.amount = asset(200)});
|
||||||
|
env(tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
testcase("fail to delete because wrong owner");
|
||||||
|
auto tx = vault.del({.owner = issuer, .id = keylet.key});
|
||||||
|
env(tx, ter(tecNO_PERMISSION));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
testcase("delete empty vault");
|
||||||
|
auto tx = vault.del({.owner = owner, .id = keylet.key});
|
||||||
|
env(tx);
|
||||||
|
BEAST_EXPECT(!env.le(keylet));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE(Sequences)
|
||||||
|
{
|
||||||
|
using namespace test::jtx;
|
||||||
|
Env env{*this};
|
||||||
|
Account issuer{"issuer"};
|
||||||
|
Account owner{"owner"};
|
||||||
|
Account depositor{"depositor"};
|
||||||
|
auto vault = env.vault();
|
||||||
|
|
||||||
|
env.fund(XRP(1000), issuer, owner, depositor);
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
SUBCASE("XRP")
|
||||||
|
{
|
||||||
|
PrettyAsset asset{xrpIssue(), 1'000'000};
|
||||||
|
testSequence(env, issuer, owner, depositor, vault, asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("IOU")
|
||||||
|
{
|
||||||
|
PrettyAsset asset = issuer["IOU"];
|
||||||
|
env.trust(asset(1000), depositor);
|
||||||
|
env(pay(issuer, depositor, asset(1000)));
|
||||||
|
testSequence(env, issuer, owner, depositor, vault, asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("MPT")
|
||||||
|
{
|
||||||
|
MPTTester mptt{env, issuer, {.fund = false}};
|
||||||
|
mptt.create({.flags = tfMPTCanTransfer | tfMPTCanLock});
|
||||||
|
PrettyAsset asset = mptt.issuanceID();
|
||||||
|
mptt.authorize({.account = depositor});
|
||||||
|
env(pay(issuer, depositor, asset(1000)));
|
||||||
|
testSequence(env, issuer, owner, depositor, vault, asset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Test for non-asset specific behaviors.
|
// Test for non-asset specific behaviors.
|
||||||
TEST_CASE(WithXRP)
|
TEST_CASE(CreateFailXRP)
|
||||||
{
|
{
|
||||||
using namespace test::jtx;
|
using namespace test::jtx;
|
||||||
Env env{*this};
|
Env env{*this};
|
||||||
@@ -79,120 +234,9 @@ class Vault_test : public beast::unit_test::suite
|
|||||||
tx[sfMPTokenMetadata] = blob1025;
|
tx[sfMPTokenMetadata] = blob1025;
|
||||||
env(tx, ter(temSTRING_TOO_LARGE));
|
env(tx, ter(temSTRING_TOO_LARGE));
|
||||||
}
|
}
|
||||||
|
|
||||||
AND_THEN("create");
|
|
||||||
env(tx);
|
|
||||||
env.close();
|
|
||||||
BEAST_EXPECT(env.le(keylet));
|
|
||||||
|
|
||||||
{
|
|
||||||
STEP("fail to deposit more than assets held");
|
|
||||||
auto tx = vault.deposit(
|
|
||||||
{.depositor = depositor,
|
|
||||||
.id = keylet.key,
|
|
||||||
.amount = XRP(1000)});
|
|
||||||
env(tx, ter(tecINSUFFICIENT_FUNDS));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
TEST_CASE(CreateFailIOU)
|
||||||
STEP("deposit non-zero amount");
|
|
||||||
auto tx = vault.deposit(
|
|
||||||
{.depositor = depositor,
|
|
||||||
.id = keylet.key,
|
|
||||||
.amount = XRP(100)});
|
|
||||||
env(tx);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
STEP("fail to delete non-empty vault");
|
|
||||||
auto tx = vault.del({.owner = owner, .id = keylet.key});
|
|
||||||
env(tx, ter(tecHAS_OBLIGATIONS));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
STEP("fail to update because wrong owner");
|
|
||||||
auto tx = vault.set({.owner = issuer, .id = keylet.key});
|
|
||||||
env(tx, ter(tecNO_PERMISSION));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
STEP("fail to update immutable flags");
|
|
||||||
tx[sfFlags] = tfVaultPrivate;
|
|
||||||
env(tx, ter(temINVALID_FLAG));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
STEP("fail to set maximum lower than current amount");
|
|
||||||
auto tx = vault.set({.owner = owner, .id = keylet.key});
|
|
||||||
tx[sfAssetMaximum] = XRP(50);
|
|
||||||
env(tx, ter(tecLIMIT_EXCEEDED));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
STEP("set maximum higher than current amount");
|
|
||||||
auto tx = vault.set({.owner = owner, .id = keylet.key});
|
|
||||||
tx[sfAssetMaximum] = XRP(200);
|
|
||||||
env(tx);
|
|
||||||
env.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
STEP("fail to deposit more than maximum");
|
|
||||||
auto tx = vault.deposit(
|
|
||||||
{.depositor = depositor,
|
|
||||||
.id = keylet.key,
|
|
||||||
.amount = XRP(200)});
|
|
||||||
env(tx, ter(tecLIMIT_EXCEEDED));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
STEP("fail to withdraw more than assets held");
|
|
||||||
auto tx = vault.withdraw(
|
|
||||||
{.depositor = depositor,
|
|
||||||
.id = keylet.key,
|
|
||||||
.amount = XRP(1000)});
|
|
||||||
env(tx, ter(tecINSUFFICIENT_FUNDS));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
STEP("deposit up to maximum");
|
|
||||||
auto tx = vault.deposit(
|
|
||||||
{.depositor = depositor,
|
|
||||||
.id = keylet.key,
|
|
||||||
.amount = XRP(100)});
|
|
||||||
env(tx);
|
|
||||||
env.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: redeem.
|
|
||||||
|
|
||||||
{
|
|
||||||
STEP("withdraw non-zero assets");
|
|
||||||
auto tx = vault.withdraw(
|
|
||||||
{.depositor = depositor,
|
|
||||||
.id = keylet.key,
|
|
||||||
.amount = XRP(200)});
|
|
||||||
env(tx);
|
|
||||||
env.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
STEP("fail to delete because wrong owner");
|
|
||||||
auto tx = vault.del({.owner = issuer, .id = keylet.key});
|
|
||||||
env(tx, ter(tecNO_PERMISSION));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
STEP("delete empty vault");
|
|
||||||
auto tx = vault.del({.owner = owner, .id = keylet.key});
|
|
||||||
env(tx);
|
|
||||||
env.close();
|
|
||||||
BEAST_EXPECT(!env.le(keylet));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE(WithIOU)
|
|
||||||
{
|
{
|
||||||
using namespace test::jtx;
|
using namespace test::jtx;
|
||||||
Env env{*this};
|
Env env{*this};
|
||||||
@@ -215,7 +259,7 @@ class Vault_test : public beast::unit_test::suite
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE(WithMPT)
|
TEST_CASE(CreateFailMPT)
|
||||||
{
|
{
|
||||||
using namespace test::jtx;
|
using namespace test::jtx;
|
||||||
Env env{*this};
|
Env env{*this};
|
||||||
@@ -238,145 +282,25 @@ class Vault_test : public beast::unit_test::suite
|
|||||||
}
|
}
|
||||||
|
|
||||||
AND_THEN("create");
|
AND_THEN("create");
|
||||||
|
|
||||||
mptt.create({.flags = tfMPTCanTransfer | tfMPTCanLock});
|
mptt.create({.flags = tfMPTCanTransfer | tfMPTCanLock});
|
||||||
Asset asset = mptt.issuanceID();
|
Asset asset = mptt.issuanceID();
|
||||||
auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
|
|
||||||
|
|
||||||
SUBCASE("create")
|
|
||||||
{
|
|
||||||
env(tx);
|
|
||||||
env.close();
|
|
||||||
|
|
||||||
SUBCASE("update")
|
|
||||||
{
|
|
||||||
auto tx = vault.set({.owner = owner, .id = keylet.key});
|
|
||||||
|
|
||||||
SUBCASE("happy path")
|
|
||||||
{
|
|
||||||
tx[sfData] = "ABCD";
|
|
||||||
tx[sfAssetMaximum] = 123;
|
|
||||||
env(tx);
|
|
||||||
env.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SUBCASE("global lock")
|
SUBCASE("global lock")
|
||||||
{
|
{
|
||||||
|
auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
|
||||||
mptt.set({.account = issuer, .flags = tfMPTLock});
|
mptt.set({.account = issuer, .flags = tfMPTLock});
|
||||||
env(tx, ter(tecLOCKED));
|
env(tx, ter(tecLOCKED));
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBCASE("MPT cannot transfer")
|
|
||||||
{
|
|
||||||
MPTTester mptt{env, issuer, {.fund = false}};
|
|
||||||
}
|
|
||||||
|
|
||||||
SUBCASE("transfer XRP")
|
|
||||||
{
|
|
||||||
// Construct asset.
|
|
||||||
Asset asset{xrpIssue()};
|
|
||||||
// Depositor already holds asset.
|
|
||||||
// Create vault.
|
|
||||||
auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
|
|
||||||
env(tx);
|
|
||||||
env.close();
|
|
||||||
|
|
||||||
{
|
|
||||||
auto tx = vault.deposit(
|
|
||||||
{.depositor = depositor,
|
|
||||||
.id = keylet.key,
|
|
||||||
.amount = asset(123)});
|
|
||||||
env(tx);
|
|
||||||
env.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SUBCASE("transfer IOU")
|
|
||||||
{
|
|
||||||
// Construct asset.
|
|
||||||
Asset asset = issuer["IOU"];
|
|
||||||
// Fund depositor with asset.
|
|
||||||
env.trust(asset(1000), depositor);
|
|
||||||
env(pay(issuer, depositor, asset(1000)));
|
|
||||||
// Create vault.
|
|
||||||
auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
|
|
||||||
env(tx);
|
|
||||||
env.close();
|
|
||||||
|
|
||||||
{
|
|
||||||
// Deposit non-zero amount.
|
|
||||||
auto tx = vault.deposit(
|
|
||||||
{.depositor = depositor,
|
|
||||||
.id = keylet.key,
|
|
||||||
.amount = asset(123)});
|
|
||||||
env(tx);
|
|
||||||
env.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SUBCASE("transfer MPT")
|
|
||||||
{
|
|
||||||
// Construct asset.
|
|
||||||
MPTTester mptt{env, issuer, {.fund = false}};
|
|
||||||
mptt.create({.flags = tfMPTCanTransfer | tfMPTCanLock});
|
|
||||||
Asset asset = mptt.issuanceID();
|
|
||||||
// Fund depositor with asset.
|
|
||||||
mptt.authorize({.account = depositor});
|
|
||||||
env(pay(issuer, depositor, asset(1000)));
|
|
||||||
// Create vault.
|
|
||||||
auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
|
|
||||||
env(tx);
|
|
||||||
env.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: VaultSet (update) succeed
|
|
||||||
// TODO: VaultSet (update) fail: wrong owner
|
|
||||||
// TODO: VaultSet (update) fail: Data too large
|
|
||||||
// TODO: VaultSet (update) fail: tfPrivate flag
|
|
||||||
// TODO: VaultSet (update) fail: tfShareNonTransferable flag
|
|
||||||
// TODO: Payment to VaultSet.PA fail
|
|
||||||
// TODO: VaultSet (update) fail: missing vault
|
|
||||||
|
|
||||||
BEAST_EXPECT(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE(Sequence)
|
|
||||||
{
|
|
||||||
using namespace test::jtx;
|
|
||||||
Env env{*this};
|
|
||||||
|
|
||||||
Account issuer{"issuer"};
|
|
||||||
Account owner{"owner"};
|
|
||||||
Account depositor{"depositor"};
|
|
||||||
env.fund(XRP(1000), issuer, owner, depositor);
|
|
||||||
env.close();
|
|
||||||
auto vault = env.vault();
|
|
||||||
|
|
||||||
SUBCASE("IOU")
|
|
||||||
{
|
|
||||||
// Construct asset.
|
|
||||||
Asset asset = issuer["IOU"];
|
|
||||||
// Fund depositor with asset.
|
|
||||||
env.trust(asset(1000), depositor);
|
|
||||||
env(pay(issuer, depositor, asset(1000)));
|
|
||||||
// Create vault.
|
|
||||||
auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
|
|
||||||
env(tx);
|
|
||||||
env.close();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void
|
void
|
||||||
run() override
|
run() override
|
||||||
{
|
{
|
||||||
pass();
|
EXECUTE(Sequences);
|
||||||
// EXECUTE(CreateUpdateDelete);
|
EXECUTE(CreateFailXRP);
|
||||||
// EXECUTE(WithXRP);
|
EXECUTE(CreateFailIOU);
|
||||||
|
EXECUTE(CreateFailMPT);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <xrpl/protocol/FeeUnits.h>
|
#include <xrpl/protocol/FeeUnits.h>
|
||||||
#include <xrpl/protocol/Issue.h>
|
#include <xrpl/protocol/Issue.h>
|
||||||
#include <xrpl/protocol/STAmount.h>
|
#include <xrpl/protocol/STAmount.h>
|
||||||
|
#include <concepts>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -125,6 +126,12 @@ public:
|
|||||||
return amount_;
|
return amount_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Number
|
||||||
|
number() const
|
||||||
|
{
|
||||||
|
return amount_;
|
||||||
|
}
|
||||||
|
|
||||||
operator STAmount const&() const
|
operator STAmount const&() const
|
||||||
{
|
{
|
||||||
return amount_;
|
return amount_;
|
||||||
@@ -153,6 +160,43 @@ operator!=(PrettyAmount const& lhs, PrettyAmount const& rhs)
|
|||||||
std::ostream&
|
std::ostream&
|
||||||
operator<<(std::ostream& os, PrettyAmount const& amount);
|
operator<<(std::ostream& os, PrettyAmount const& amount);
|
||||||
|
|
||||||
|
struct PrettyAsset
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Asset asset_;
|
||||||
|
unsigned int scale_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
template <typename A>
|
||||||
|
requires std::convertible_to<A, Asset>
|
||||||
|
PrettyAsset(A const& asset, unsigned int scale = 1)
|
||||||
|
: PrettyAsset{Asset{asset}, scale}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PrettyAsset(Asset const& asset, unsigned int scale = 1)
|
||||||
|
: asset_(asset), scale_(scale)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
operator Asset const&() const
|
||||||
|
{
|
||||||
|
return asset_;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator Json::Value() const
|
||||||
|
{
|
||||||
|
return to_json(asset_);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::integral T>
|
||||||
|
PrettyAmount
|
||||||
|
operator()(T v) const
|
||||||
|
{
|
||||||
|
STAmount amount{asset_, v * scale_};
|
||||||
|
return {amount, "uhh"};
|
||||||
|
}
|
||||||
|
};
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Specifies an order book
|
// Specifies an order book
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <test/jtx/subcases.h>
|
#include <test/jtx/subcases.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace subcases {
|
namespace subcases {
|
||||||
@@ -54,6 +55,9 @@ Subcase::~Subcase()
|
|||||||
if (_.level == _.entered && _.skipped == 0)
|
if (_.level == _.entered && _.skipped == 0)
|
||||||
{
|
{
|
||||||
// We are destroying the leaf subcase that executed on this pass.
|
// We are destroying the leaf subcase that executed on this pass.
|
||||||
|
// Didn't have time to debug this. Cannot explain what is going wrong
|
||||||
|
// with jtx. Just switch to a better test framework already.
|
||||||
|
_.suite.pass();
|
||||||
// We call `suite::testcase()` here, after the subcase is finished,
|
// We call `suite::testcase()` here, after the subcase is finished,
|
||||||
// because only now do we know which subcase was the leaf,
|
// because only now do we know which subcase was the leaf,
|
||||||
// and we only want to print one name line for each subcase.
|
// and we only want to print one name line for each subcase.
|
||||||
|
|||||||
@@ -132,7 +132,8 @@ execute(beast::unit_test::suite* suite, char const* name, Supercase supercase);
|
|||||||
// without having to indent them in a nested block.
|
// without having to indent them in a nested block.
|
||||||
#define AND_THEN(name) \
|
#define AND_THEN(name) \
|
||||||
subcases::Subcase sc##__COUNTER__{_09876, name}; \
|
subcases::Subcase sc##__COUNTER__{_09876, name}; \
|
||||||
if (!*subcases::Subcase::lastCreated) return
|
if (!*subcases::Subcase::lastCreated) \
|
||||||
#define STEP(name_) _09876.suite.testcase(_09876.name() + " > " + name_)
|
return
|
||||||
|
#define SECTION(name_) _09876.suite.testcase(_09876.name() + " > " + name_)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -921,6 +921,8 @@ createPseudoAccount(ApplyView& view, uint256 const& pseudoOwnerKey)
|
|||||||
account->setFieldU32(
|
account->setFieldU32(
|
||||||
sfFlags, lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth);
|
sfFlags, lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth);
|
||||||
// Link the pseudo-account with its owner object.
|
// Link the pseudo-account with its owner object.
|
||||||
|
// TODO: This debate is unresolved. There is allegedly a need to know
|
||||||
|
// whether a pseudo-account belongs to an AMM specifically.
|
||||||
// account->setFieldH256(sfPseudoOwner, pseudoOwnerKey);
|
// account->setFieldH256(sfPseudoOwner, pseudoOwnerKey);
|
||||||
view.insert(account);
|
view.insert(account);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user