mirror of
https://github.com/XRPLF/rippled.git
synced 2026-08-18 21:10:02 +00:00
fix: Port WASM host function tests to new WASM design
This commit is contained in:
File diff suppressed because it is too large
Load Diff
56
src/tests/libxrpl/tx/wasm/FloatFixture.h
Normal file
56
src/tests/libxrpl/tx/wasm/FloatFixture.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
// Known float bit patterns (12-byte `wasm_float` regions) — inputs / expected values for
|
||||
// the float host functions. `kNormalExp` is the exponent offset the encoding uses.
|
||||
namespace floats {
|
||||
inline constexpr int kNormalExp = 18;
|
||||
|
||||
// clang-format off
|
||||
inline Bytes const kIntMin = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}; // -2^63 (rounds to -(2^63-1))
|
||||
inline Bytes const kIntZero = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00}; // 0
|
||||
inline Bytes const kIntMax = {0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}; // 2^63-1
|
||||
inline Bytes const kUintMax = {0x19, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9A, 0x00, 0x00, 0x00, 0x01}; // 2^64-1
|
||||
inline Bytes const kMaxExp = {0x0D, 0xE0, 0xB6, 0xB3, 0xA7, 0x64, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00}; // 1e(kMaxExponent + kNormalExp)
|
||||
inline Bytes const kPreMaxExp = {0x0D, 0xE0, 0xB6, 0xB3, 0xA7, 0x64, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF}; // 1e(kMaxExponent + kNormalExp - 1)
|
||||
inline Bytes const kMinusMaxExp = {0xF2, 0x1F, 0x49, 0x4C, 0x58, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00}; // -1e(kMaxExponent + kNormalExp)
|
||||
inline Bytes const kMinExp = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00}; // 1e(kMinExponent - kNormalExp)
|
||||
inline Bytes const kMax = {0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x80, 0x00}; // kMaxRep e(kMaxExponent - kNormalExp)
|
||||
inline Bytes const kMaxIOU = {0x0D, 0xE0, 0xB6, 0xB3, 0xA7, 0x63, 0xFF, 0x9C, 0x00, 0x00, 0x00, 0x4E}; // 9999999999999999e(96)
|
||||
inline Bytes const kMinIOU = {0x0D, 0xE0, 0xB6, 0xB3, 0xA7, 0x64, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x9D}; // 1e(-81)
|
||||
inline Bytes const kOne = {0x0D, 0xE0, 0xB6, 0xB3, 0xA7, 0x64, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xEE}; // 1
|
||||
inline Bytes const kMinusOne = {0xF2, 0x1F, 0x49, 0x4C, 0x58, 0x9C, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xEE}; // -1
|
||||
inline Bytes const kOneMore = {0x0D, 0xE0, 0xB6, 0xB3, 0xA7, 0x64, 0x03, 0xE8, 0xFF, 0xFF, 0xFF, 0xEE}; // 1.000000000000001
|
||||
inline Bytes const kTwo = {0x1B, 0xC1, 0x6D, 0x67, 0x4E, 0xC8, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xEE}; // 2
|
||||
inline Bytes const kTen = {0x0D, 0xE0, 0xB6, 0xB3, 0xA7, 0x64, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xEF}; // 10
|
||||
inline Bytes const kPi = {0x2B, 0x99, 0x2D, 0xDF, 0xA2, 0x32, 0x48, 0xE8, 0xFF, 0xFF, 0xFF, 0xEE}; // 3.141592653589793
|
||||
inline Bytes const kInvalidZero = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00}; // non-canonical zero
|
||||
inline Bytes const kMinusThree = {0xD6, 0x5D, 0xDB, 0xE5, 0x09, 0xD4, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xEE}; // -3
|
||||
// clang-format on
|
||||
|
||||
inline std::string const kInvalidData = "invalid_data";
|
||||
} // namespace floats
|
||||
|
||||
struct FloatTest : WasmImplTest
|
||||
{
|
||||
static constexpr std::int64_t kMin64 = std::numeric_limits<std::int64_t>::min();
|
||||
static constexpr std::int64_t kMax64 = std::numeric_limits<std::int64_t>::max();
|
||||
|
||||
static Slice
|
||||
slice(Bytes const& b)
|
||||
{
|
||||
return Slice{b.data(), b.size()};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace xrpl::test
|
||||
69
src/tests/libxrpl/tx/wasm/NFTFixture.h
Normal file
69
src/tests/libxrpl/tx/wasm/NFTFixture.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/Keylet.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STArray.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/nft.h>
|
||||
#include <xrpl/protocol_autogen/transactions/NFTokenMint.h>
|
||||
#include <xrpl/tx/transactors/nft/NFTokenMint.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct NFTTest : WasmImplTest
|
||||
{
|
||||
static constexpr std::uint16_t kFlags = nft::kFlagTransferable | nft::kFlagBurnable;
|
||||
static constexpr std::uint16_t kFee = 314;
|
||||
static constexpr std::uint32_t kTaxon = 12345;
|
||||
static constexpr std::uint32_t kSequence = 7;
|
||||
|
||||
static uint256
|
||||
makeNftId(AccountID const& issuer)
|
||||
{
|
||||
return NFTokenMint::createNFTokenID(kFlags, kFee, issuer, nft::toTaxon(kTaxon), kSequence);
|
||||
}
|
||||
|
||||
// Mint a real NFToken owned by `issuer` (taxon 0) and return its id, read back from the
|
||||
// owner's NFTokenPage. TxTest applies to the open ledger, which produces no metadata, so
|
||||
// the id is recovered from ledger state rather than from the mint's metadata.
|
||||
uint256
|
||||
mintNFT(Account const& issuer, std::optional<std::string_view> uri = std::nullopt)
|
||||
{
|
||||
auto builder = transactions::NFTokenMintBuilder{issuer.id(), 0u};
|
||||
if (uri)
|
||||
builder.setURI(Slice{uri->data(), uri->size()});
|
||||
auto const r = ledger.submit(builder, issuer);
|
||||
EXPECT_EQ(r.ter, tesSUCCESS) << transToken(r.ter);
|
||||
ledger.close();
|
||||
|
||||
// The single minted token lives in the owner's first NFTokenPage.
|
||||
auto const& view = ledger.getOpenLedger();
|
||||
auto const first = keylet::nftokenPageMin(issuer.id()).key;
|
||||
auto const last = keylet::nftokenPageMax(issuer.id()).key;
|
||||
auto const pageKey = view.succ(first, last.next());
|
||||
EXPECT_TRUE(pageKey.has_value());
|
||||
auto const page = pageKey ? view.read(Keylet{ltNFTOKEN_PAGE, *pageKey}) : nullptr;
|
||||
EXPECT_NE(page, nullptr);
|
||||
if (!page)
|
||||
return uint256{};
|
||||
auto const& tokens = page->getFieldArray(sfNFTokens);
|
||||
EXPECT_FALSE(tokens.empty());
|
||||
return tokens.empty() ? uint256{} : tokens[0].getFieldH256(sfNFTokenID);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace xrpl::test
|
||||
@@ -1,85 +1,108 @@
|
||||
#pragma once
|
||||
|
||||
// Base for the "impl" wasm tests: a *real* `WasmHostFunctionsImpl` over a *real* ledger,
|
||||
// built with no Application / jtx / beast::unit_test::Suite. The ledger is a `TxTest`
|
||||
// (genesis ledger + OpenView + real transactor dispatch); the host is constructed from
|
||||
// its `ServiceRegistry` and `OpenView` through an `ApplyContext`.
|
||||
//
|
||||
// This is the counterpart to `HostContextFixture` (mock host, interop): here the host
|
||||
// really computes, so a test asserts a value against the ledger's own source of truth
|
||||
// (`keylet::escrow`, a real field's bytes, `wasm_float`), rather than what a mock was
|
||||
// asked. Pure-computation host functions (keylets, floats, check_sig, sha512_half, nft
|
||||
// decoders) ignore the ledger; the reading getters read the object `leKey` points at.
|
||||
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ApplyView.h> // TapNone
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Asset.h>
|
||||
#include <xrpl/protocol/Fees.h>
|
||||
#include <xrpl/protocol/Indexes.h> // keylet::account
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/KeyType.h>
|
||||
#include <xrpl/protocol/Keylet.h>
|
||||
#include <xrpl/protocol/MPTIssue.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/STArray.h>
|
||||
#include <xrpl/protocol/STNumber.h>
|
||||
#include <xrpl/protocol/STObject.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/SecretKey.h>
|
||||
#include <xrpl/protocol/Serializer.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/TxFormats.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/protocol_autogen/transactions/SignerListSet.h>
|
||||
#include <xrpl/tx/ApplyContext.h>
|
||||
#include <xrpl/tx/wasm/HostFuncImpl.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/CaptureSink.h>
|
||||
#include <helpers/TxTest.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
static Bytes
|
||||
inline Bytes
|
||||
toBytes(std::uint8_t value)
|
||||
{
|
||||
return {value};
|
||||
}
|
||||
|
||||
static Bytes
|
||||
inline Bytes
|
||||
toBytes(std::uint16_t value)
|
||||
{
|
||||
auto const* b = reinterpret_cast<uint8_t const*>(&value);
|
||||
auto const* e = reinterpret_cast<uint8_t const*>(&value + 1);
|
||||
return Bytes{b, e};
|
||||
return {static_cast<std::uint8_t>(value), static_cast<std::uint8_t>(value >> 8)};
|
||||
}
|
||||
|
||||
static Bytes
|
||||
inline Bytes
|
||||
toBytes(std::uint32_t value)
|
||||
{
|
||||
auto const* b = reinterpret_cast<uint8_t const*>(&value);
|
||||
auto const* e = reinterpret_cast<uint8_t const*>(&value + 1);
|
||||
return Bytes{b, e};
|
||||
return {
|
||||
static_cast<std::uint8_t>(value),
|
||||
static_cast<std::uint8_t>(value >> 8),
|
||||
static_cast<std::uint8_t>(value >> 16),
|
||||
static_cast<std::uint8_t>(value >> 24)};
|
||||
}
|
||||
|
||||
static Bytes
|
||||
inline Bytes
|
||||
toBytes(uint256 const& value)
|
||||
{
|
||||
return Bytes{value.begin(), value.end()};
|
||||
return Bytes{std::begin(value), std::end(value)};
|
||||
}
|
||||
|
||||
static Bytes
|
||||
inline Bytes
|
||||
toBytes(std::string_view value)
|
||||
{
|
||||
return Bytes{std::begin(value), std::end(value)};
|
||||
}
|
||||
|
||||
inline Bytes
|
||||
toBytes(std::span<std::uint8_t const> value)
|
||||
{
|
||||
return Bytes{std::begin(value), std::end(value)};
|
||||
}
|
||||
|
||||
inline Bytes
|
||||
toBytes(AccountID const& account)
|
||||
{
|
||||
return Bytes{std::begin(account), std::end(account)};
|
||||
}
|
||||
|
||||
inline Bytes
|
||||
toBytes(Issue const& issue)
|
||||
{
|
||||
Serializer s;
|
||||
auto s = Serializer{};
|
||||
s.addBitString(issue.currency);
|
||||
if (!isXRP(issue.currency))
|
||||
s.addBitString(issue.account);
|
||||
auto const data = s.getData();
|
||||
return data;
|
||||
return s.getData();
|
||||
}
|
||||
|
||||
static Bytes
|
||||
inline Bytes
|
||||
toBytes(Asset const& asset)
|
||||
{
|
||||
if (asset.holds<Issue>())
|
||||
@@ -90,61 +113,247 @@ toBytes(Asset const& asset)
|
||||
return Bytes{mptID.cbegin(), mptID.cend()};
|
||||
}
|
||||
|
||||
static Bytes
|
||||
inline Bytes
|
||||
toBytes(STAmount const& amount)
|
||||
{
|
||||
Serializer msg;
|
||||
auto msg = Serializer{};
|
||||
amount.add(msg);
|
||||
auto const data = msg.getData();
|
||||
|
||||
return data;
|
||||
return msg.getData();
|
||||
}
|
||||
|
||||
static Bytes
|
||||
inline Bytes
|
||||
toBytes(STNumber const& number)
|
||||
{
|
||||
Serializer msg;
|
||||
auto msg = Serializer{};
|
||||
number.add(msg);
|
||||
auto const data = msg.getData();
|
||||
|
||||
return data;
|
||||
return msg.getData();
|
||||
}
|
||||
|
||||
class WasmImplTest : public testing::Test
|
||||
template <typename T, typename U>
|
||||
void
|
||||
expectValue(std::expected<T, HostFunctionError> const& result, U const& expected)
|
||||
{
|
||||
ASSERT_TRUE(result.has_value())
|
||||
<< "expected a value, got error " << static_cast<int>(result.error());
|
||||
EXPECT_EQ(*result, expected);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
expectError(std::expected<T, HostFunctionError> const& result, HostFunctionError expected)
|
||||
{
|
||||
ASSERT_FALSE(result.has_value()) << "expected error, got a value";
|
||||
EXPECT_EQ(result.error(), expected);
|
||||
}
|
||||
|
||||
inline void
|
||||
expectKeyletMatches(std::expected<Bytes, HostFunctionError> const& result, Keylet const& expected)
|
||||
{
|
||||
expectValue(result, toBytes(expected.key));
|
||||
}
|
||||
|
||||
struct SignedMessage
|
||||
{
|
||||
Bytes message;
|
||||
Bytes signature;
|
||||
Bytes publicKey;
|
||||
};
|
||||
|
||||
inline SignedMessage
|
||||
signMessage(std::string_view message, KeyType keyType = KeyType::Secp256k1)
|
||||
{
|
||||
auto const [pk, sk] = randomKeyPair(keyType);
|
||||
auto const msg = Bytes{std::begin(message), std::end(message)};
|
||||
auto const sig = sign(pk, sk, Slice{msg.data(), msg.size()});
|
||||
return {
|
||||
.message = msg,
|
||||
.signature = Bytes{sig.data(), sig.data() + sig.size()},
|
||||
.publicKey = Bytes{pk.data(), pk.data() + pk.size()}};
|
||||
}
|
||||
|
||||
inline uint256
|
||||
credentialId(
|
||||
std::string_view hex = "0011223344556677889900112233445566778899001122334455667788990011")
|
||||
{
|
||||
auto id = uint256{};
|
||||
EXPECT_TRUE(id.parseHex(std::string{hex}));
|
||||
return id;
|
||||
}
|
||||
|
||||
inline STObject
|
||||
makeMemo(Bytes const& data)
|
||||
{
|
||||
auto memo = STObject::makeInnerObject(sfMemo);
|
||||
memo.setFieldVL(sfMemoData, data);
|
||||
return memo;
|
||||
}
|
||||
|
||||
struct TxAssembler
|
||||
{
|
||||
TxType type;
|
||||
std::function<void(STObject&)> build;
|
||||
};
|
||||
|
||||
inline TxAssembler
|
||||
bareTx(TxType type = ttESCROW_FINISH)
|
||||
{
|
||||
return {.type = type, .build = [](STObject&) {}};
|
||||
}
|
||||
|
||||
inline TxAssembler
|
||||
escrowFinishTx(TxTest& ledger, Account const& acct)
|
||||
{
|
||||
return {.type = ttESCROW_FINISH, .build = [&ledger, acct](STObject& obj) {
|
||||
auto credId = uint256{};
|
||||
EXPECT_TRUE(credId.parseHex(
|
||||
"0011223344556677889900112233445566778899001122334455667788990011"));
|
||||
|
||||
obj.setAccountID(sfAccount, acct.id());
|
||||
obj.setAccountID(sfOwner, acct.id());
|
||||
obj.setFieldU32(sfOfferSequence, ledger.getAccountRoot(acct.id()).getSequence());
|
||||
obj.setFieldArray(sfMemos, STArray{});
|
||||
auto credIds = STVector256{};
|
||||
credIds.pushBack(credId);
|
||||
obj.setFieldV256(sfCredentialIDs, credIds);
|
||||
}};
|
||||
}
|
||||
|
||||
inline TxAssembler
|
||||
ammDepositTx(Account const& acct, Asset const& asset1, Asset const& asset2)
|
||||
{
|
||||
return {.type = ttAMM_DEPOSIT, .build = [acct, asset1, asset2](STObject& obj) {
|
||||
obj.setAccountID(sfAccount, acct.id());
|
||||
obj.setFieldIssue(sfAsset, STIssue{sfAsset, asset1});
|
||||
obj.setFieldIssue(sfAsset2, STIssue{sfAsset2, asset2});
|
||||
}};
|
||||
}
|
||||
|
||||
inline TxAssembler
|
||||
mptIssuanceCreateTx(Account const& acct, std::uint8_t scale)
|
||||
{
|
||||
return {.type = ttMPTOKEN_ISSUANCE_CREATE, .build = [acct, scale](STObject& obj) {
|
||||
obj.setAccountID(sfAccount, acct.id());
|
||||
obj.setFieldU8(sfAssetScale, scale);
|
||||
}};
|
||||
}
|
||||
|
||||
class WasmHost
|
||||
{
|
||||
public:
|
||||
// The real ledger. Tests populate it with `ledger.createAccount()` / `submit()` /
|
||||
// `close()` before reading through the host.
|
||||
TxTest ledger;
|
||||
|
||||
// A real host bound to `leKey` — the "current"/home object the `*_field` and
|
||||
// `*_arr_len` getters read. Defaults to a throwaway keylet for the many functions
|
||||
// (keylets, floats, sig, hash, nft decoders) that never touch the current object.
|
||||
//
|
||||
// Returns a reference into a fixture-owned host so its `ApplyContext&` outlives it;
|
||||
// call once per test.
|
||||
WasmHostFunctionsImpl&
|
||||
host(Keylet const& leKey = keylet::account(AccountID{}))
|
||||
WasmHost(
|
||||
std::shared_ptr<STTx const> tx,
|
||||
std::unique_ptr<ApplyContext> context,
|
||||
std::unique_ptr<WasmHostFunctionsImpl> host)
|
||||
: tx_{std::move(tx)}, context_{std::move(context)}, host_{std::move(host)}
|
||||
{
|
||||
}
|
||||
|
||||
WasmHostFunctionsImpl*
|
||||
operator->() const
|
||||
{
|
||||
return host_.get();
|
||||
}
|
||||
WasmHostFunctionsImpl&
|
||||
operator*() const
|
||||
{
|
||||
// The finish tx the host runs under. Its contents are irrelevant to the
|
||||
// functions these tests exercise; it only has to be a well-formed shell.
|
||||
finishTx_ = std::make_shared<STTx>(ttESCROW_FINISH, [](STObject&) {});
|
||||
context_.emplace(
|
||||
ledger.getServiceRegistry(),
|
||||
ledger.getOpenLedger(),
|
||||
*finishTx_,
|
||||
tesSUCCESS,
|
||||
ledger.getOpenLedger().fees().base,
|
||||
TapNone,
|
||||
beast::Journal{beast::Journal::getNullSink()});
|
||||
host_.emplace(*context_, leKey);
|
||||
return *host_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<STTx const> finishTx_;
|
||||
std::optional<ApplyContext> context_;
|
||||
std::optional<WasmHostFunctionsImpl> host_;
|
||||
std::shared_ptr<STTx const> tx_;
|
||||
std::unique_ptr<ApplyContext> context_;
|
||||
std::unique_ptr<WasmHostFunctionsImpl> host_;
|
||||
};
|
||||
|
||||
class WasmImplTest : public testing::Test
|
||||
{
|
||||
public:
|
||||
TxTest ledger;
|
||||
|
||||
Account
|
||||
fund(char const* name, XRPAmount amount = XRP(1000))
|
||||
{
|
||||
auto const account = Account{name};
|
||||
ledger.createAccount(account, amount);
|
||||
return account;
|
||||
}
|
||||
|
||||
WasmHost
|
||||
makeHost(
|
||||
beast::Journal journal,
|
||||
Keylet const& leKey = keylet::account(AccountID{}),
|
||||
TxType txType = ttESCROW_FINISH,
|
||||
std::function<void(STObject&)> assembler = [](STObject&) {})
|
||||
{
|
||||
auto tx = std::make_shared<STTx>(
|
||||
txType, [assembler = std::move(assembler)](STObject& obj) { assembler(obj); });
|
||||
auto context = std::make_unique<ApplyContext>(
|
||||
ledger.getServiceRegistry(),
|
||||
ledger.getOpenLedger(),
|
||||
*tx,
|
||||
tesSUCCESS,
|
||||
ledger.getOpenLedger().fees().base,
|
||||
TapNone,
|
||||
journal);
|
||||
auto host = std::make_unique<WasmHostFunctionsImpl>(*context, leKey);
|
||||
return WasmHost{std::move(tx), std::move(context), std::move(host)};
|
||||
}
|
||||
|
||||
// The common case: a host that discards its log output.
|
||||
WasmHost
|
||||
makeHost(
|
||||
Keylet const& leKey = keylet::account(AccountID{}),
|
||||
TxType txType = ttESCROW_FINISH,
|
||||
std::function<void(STObject&)> assembler = [](STObject&) {})
|
||||
{
|
||||
return makeHost(
|
||||
beast::Journal{beast::Journal::getNullSink()}, leKey, txType, std::move(assembler));
|
||||
}
|
||||
|
||||
// A host whose `trace` output is captured, so a test can read it back with `logged()`.
|
||||
// The sink is a fixture member, so it outlives the host and accumulates across a test.
|
||||
WasmHost
|
||||
makeTracingHost(
|
||||
Keylet const& leKey = keylet::account(AccountID{}),
|
||||
TxType txType = ttESCROW_FINISH,
|
||||
std::function<void(STObject&)> assembler = [](STObject&) {})
|
||||
{
|
||||
return makeHost(beast::Journal{traceSink_}, leKey, txType, std::move(assembler));
|
||||
}
|
||||
|
||||
// Everything `trace` has written to the tracing host so far.
|
||||
[[nodiscard]] std::string
|
||||
logged() const
|
||||
{
|
||||
return traceSink_.messages();
|
||||
}
|
||||
|
||||
// Submit a real SignerListSet so `keylet::signerList(owner)` exists — the object the
|
||||
// signer-list nested-field / array-length getters read. `signers` pairs each signer
|
||||
// account with its weight.
|
||||
void
|
||||
makeSignerList(
|
||||
Account const& owner,
|
||||
std::uint32_t quorum,
|
||||
std::vector<std::pair<Account, std::uint16_t>> const& signers)
|
||||
{
|
||||
auto entries = STArray{};
|
||||
for (auto const& [signer, weight] : signers)
|
||||
{
|
||||
auto entry = STObject::makeInnerObject(sfSignerEntry);
|
||||
entry.setAccountID(sfAccount, signer.id());
|
||||
entry.setFieldU16(sfSignerWeight, weight);
|
||||
entries.push_back(std::move(entry));
|
||||
}
|
||||
auto const r = ledger.submit(
|
||||
transactions::SignerListSetBuilder{owner.id(), quorum}.setSignerEntries(entries),
|
||||
owner);
|
||||
EXPECT_EQ(r.ter, tesSUCCESS) << transToken(r.ter);
|
||||
ledger.close();
|
||||
}
|
||||
|
||||
private:
|
||||
CaptureSink traceSink_{beast::Severity::Trace};
|
||||
};
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -4,12 +4,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct AccountKeyletImpl : WasmImplTest
|
||||
@@ -18,22 +14,14 @@ struct AccountKeyletImpl : WasmImplTest
|
||||
|
||||
TEST_F(AccountKeyletImpl, MatchesAccountKeyletFunction)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto const expected = keylet::account(owner.id());
|
||||
auto const expectedBytes = Bytes{std::begin(expected.key), std::end(expected.key)};
|
||||
auto const result = host().accountKeylet(owner);
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, expectedBytes);
|
||||
expectKeyletMatches(makeHost()->accountKeylet(owner), keylet::account(owner.id()));
|
||||
}
|
||||
|
||||
TEST_F(AccountKeyletImpl, UnsetAccountIsInvalidAccount)
|
||||
{
|
||||
auto const result = host().accountKeylet(AccountID{});
|
||||
|
||||
ASSERT_FALSE(result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(makeHost()->accountKeylet(AccountID{}), HostFunctionError::InvalidAccount);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -5,12 +5,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct AmmKeyletImpl : WasmImplTest
|
||||
@@ -19,35 +15,26 @@ struct AmmKeyletImpl : WasmImplTest
|
||||
|
||||
TEST_F(AmmKeyletImpl, MatchesAmmKeyletFunction)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto usdIssue = Issue{toCurrency("USD"), owner.id()};
|
||||
|
||||
auto const expected = keylet::amm(xrpIssue(), usdIssue);
|
||||
auto const expectedBytes = Bytes{std::begin(expected.key), std::end(expected.key)};
|
||||
auto const result = host().ammKeylet(usdIssue, xrpIssue());
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, expectedBytes);
|
||||
expectKeyletMatches(
|
||||
makeHost()->ammKeylet(usdIssue, xrpIssue()), keylet::amm(xrpIssue(), usdIssue));
|
||||
}
|
||||
|
||||
TEST_F(AmmKeyletImpl, InvalidIssue1)
|
||||
{
|
||||
auto const result = host().ammKeylet(xrpIssue(), xrpIssue());
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidParams);
|
||||
expectError(makeHost()->ammKeylet(xrpIssue(), xrpIssue()), HostFunctionError::InvalidParams);
|
||||
}
|
||||
|
||||
TEST_F(AmmKeyletImpl, InvalidIssue2)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto baseMpt = makeMptID(1, owner.id());
|
||||
|
||||
auto const result = host().ammKeylet(baseMpt, xrpIssue());
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidParams);
|
||||
expectError(makeHost()->ammKeylet(baseMpt, xrpIssue()), HostFunctionError::InvalidParams);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct BaseFeeImpl : WasmImplTest
|
||||
@@ -11,9 +9,7 @@ struct BaseFeeImpl : WasmImplTest
|
||||
|
||||
TEST_F(BaseFeeImpl, MatchesLedger)
|
||||
{
|
||||
auto const result = host().getBaseFee();
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, ledger.getOpenLedger().fees().base.drops());
|
||||
expectValue(makeHost()->getBaseFee(), ledger.getOpenLedger().fees().base.drops());
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
@@ -21,16 +20,16 @@ struct CacheLedgerObjImpl : WasmImplTest
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
|
||||
auto& h = host();
|
||||
auto h = makeHost();
|
||||
auto const key = keylet::account(owner.id()).key;
|
||||
|
||||
for (auto i = int32_t{1}; i < 257; ++i)
|
||||
{
|
||||
auto const slot = h.cacheLedgerObj(key, i);
|
||||
auto const slot = h->cacheLedgerObj(key, i);
|
||||
ASSERT_TRUE(slot.has_value()) << "cacheLedgerObj should find the created account";
|
||||
EXPECT_EQ(*slot, i);
|
||||
|
||||
auto const account = h.getLedgerObjField(*slot, sfAccount);
|
||||
auto const account = h->getLedgerObjField(*slot, sfAccount);
|
||||
ASSERT_TRUE(account.has_value());
|
||||
Bytes const ownerBytes{owner.id().begin(), owner.id().end()};
|
||||
EXPECT_EQ(*account, ownerBytes);
|
||||
@@ -43,7 +42,7 @@ struct CacheLedgerObjImpl : WasmImplTest
|
||||
|
||||
// Every slot is now occupied, so asking to auto-allocate (cacheIdx == 0) has nowhere
|
||||
// to put the object.
|
||||
auto const result = h.cacheLedgerObj(key, 0);
|
||||
auto const result = h->cacheLedgerObj(key, 0);
|
||||
ASSERT_FALSE(result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::SlotsFull);
|
||||
}
|
||||
@@ -61,11 +60,11 @@ TEST_F(CacheLedgerObjImpl, MatchesLedgerImplicitIndices)
|
||||
|
||||
TEST_F(CacheLedgerObjImpl, OutOfRange)
|
||||
{
|
||||
auto result = host().cacheLedgerObj(uint256{}, -1);
|
||||
auto result = makeHost()->cacheLedgerObj(uint256{}, -1);
|
||||
ASSERT_FALSE(result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::SlotOutRange);
|
||||
|
||||
result = host().cacheLedgerObj(uint256{}, 257);
|
||||
result = makeHost()->cacheLedgerObj(uint256{}, 257);
|
||||
ASSERT_FALSE(result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::SlotOutRange);
|
||||
}
|
||||
@@ -73,9 +72,26 @@ TEST_F(CacheLedgerObjImpl, OutOfRange)
|
||||
TEST_F(CacheLedgerObjImpl, LedgerObjNotFound)
|
||||
{
|
||||
auto const ghost = keylet::account(Account{"ghost"}.id()).key;
|
||||
auto result = host().cacheLedgerObj(ghost, 0);
|
||||
auto result = makeHost()->cacheLedgerObj(ghost, 0);
|
||||
ASSERT_FALSE(result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::LedgerObjNotFound);
|
||||
}
|
||||
|
||||
// Two hosts built from the same fixture are fully independent: each owns its own slot
|
||||
// table, so caching into one leaves the other's slots empty. (This is what the `WasmHost`
|
||||
// handle buys over the old shared-fixture-state design.)
|
||||
TEST_F(CacheLedgerObjImpl, IndependentHostsDoNotShareSlots)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto const key = keylet::account(owner.id()).key;
|
||||
|
||||
auto a = makeHost();
|
||||
auto b = makeHost();
|
||||
|
||||
ASSERT_TRUE(a->cacheLedgerObj(key, 1).has_value());
|
||||
expectValue(a->getLedgerObjField(1, sfAccount), toBytes(owner.id()));
|
||||
// `b` never cached anything, so its slot 1 is still empty.
|
||||
expectError(b->getLedgerObjField(1, sfAccount), HostFunctionError::EmptySlot);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -5,12 +5,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct CheckKeyletImpl : WasmImplTest
|
||||
@@ -19,22 +15,16 @@ struct CheckKeyletImpl : WasmImplTest
|
||||
|
||||
TEST_F(CheckKeyletImpl, MatchesCheckKeyletFunction)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto const expected = keylet::check(owner.id(), SeqProxy::rawSequence(1u));
|
||||
auto const expectedBytes = Bytes{std::begin(expected.key), std::end(expected.key)};
|
||||
auto const result = host().checkKeylet(owner.id(), 1u);
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, expectedBytes);
|
||||
expectKeyletMatches(
|
||||
makeHost()->checkKeylet(owner.id(), 1u),
|
||||
keylet::check(owner.id(), SeqProxy::rawSequence(1u)));
|
||||
}
|
||||
|
||||
TEST_F(CheckKeyletImpl, UnsetAccountIsInvalidAccount)
|
||||
{
|
||||
auto const result = host().checkKeylet(AccountID{}, 1u);
|
||||
|
||||
ASSERT_FALSE(result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(makeHost()->checkKeylet(AccountID{}, 1u), HostFunctionError::InvalidAccount);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
80
src/tests/libxrpl/tx/wasm/host_functions/CheckSignature.cpp
Normal file
80
src/tests/libxrpl/tx/wasm/host_functions/CheckSignature.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#include <xrpl/protocol/KeyType.h>
|
||||
#include <xrpl/protocol/SecretKey.h>
|
||||
#include <xrpl/protocol/Seed.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct CheckSignatureImpl : WasmImplTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(CheckSignatureImpl, ValidSignature)
|
||||
{
|
||||
auto const kp = generateKeyPair(KeyType::Secp256k1, randomSeed());
|
||||
auto const& pk = kp.first;
|
||||
auto const& sk = kp.second;
|
||||
auto const& message = std::string{"hello signature"};
|
||||
auto const sig = sign(pk, sk, Slice(message.data(), message.size()));
|
||||
|
||||
auto const result = makeHost()->checkSignature(
|
||||
Slice{message.data(), message.size()}, Slice{sig.data(), sig.size()}, pk);
|
||||
expectValue(result, std::int32_t{1});
|
||||
}
|
||||
|
||||
TEST_F(CheckSignatureImpl, InvalidSignature)
|
||||
{
|
||||
auto const kp = generateKeyPair(KeyType::Secp256k1, randomSeed());
|
||||
auto const& pk = kp.first;
|
||||
auto const& sk = kp.second;
|
||||
auto const& message = std::string{"hello signature"};
|
||||
auto const sig = sign(pk, sk, Slice(message.data(), message.size()));
|
||||
auto const badSignature = std::string(sig.size(), 0xFF);
|
||||
|
||||
auto const result = makeHost()->checkSignature(
|
||||
Slice{message.data(), message.size()}, Slice{badSignature.data(), badSignature.size()}, pk);
|
||||
expectValue(result, std::int32_t{0});
|
||||
}
|
||||
|
||||
TEST_F(CheckSignatureImpl, InvalidPublicKey)
|
||||
{
|
||||
auto const kp = generateKeyPair(KeyType::Secp256k1, randomSeed());
|
||||
auto const kp2 = generateKeyPair(KeyType::Secp256k1, randomSeed());
|
||||
auto const& pk = kp.first;
|
||||
auto const& sk = kp.second;
|
||||
auto const& message = std::string{"hello signature"};
|
||||
auto const sig = sign(pk, sk, Slice(message.data(), message.size()));
|
||||
|
||||
auto const result = makeHost()->checkSignature(
|
||||
Slice{message.data(), message.size()}, Slice{sig.data(), sig.size()}, kp2.first);
|
||||
expectValue(result, std::int32_t{0});
|
||||
}
|
||||
|
||||
TEST_F(CheckSignatureImpl, EmptySignature)
|
||||
{
|
||||
auto const kp = generateKeyPair(KeyType::Secp256k1, randomSeed());
|
||||
auto const& pk = kp.first;
|
||||
auto const& message = std::string{"hello signature"};
|
||||
|
||||
auto const result =
|
||||
makeHost()->checkSignature(Slice{message.data(), message.size()}, Slice{}, pk);
|
||||
expectValue(result, std::int32_t{0});
|
||||
}
|
||||
|
||||
TEST_F(CheckSignatureImpl, EmptyMessage)
|
||||
{
|
||||
auto const kp = generateKeyPair(KeyType::Secp256k1, randomSeed());
|
||||
auto const& pk = kp.first;
|
||||
auto const& sk = kp.second;
|
||||
auto const& message = std::string{"hello signature"};
|
||||
auto const sig = sign(pk, sk, Slice(message.data(), message.size()));
|
||||
|
||||
auto const result = makeHost()->checkSignature(Slice{}, Slice{sig.data(), sig.size()}, pk);
|
||||
expectValue(result, std::int32_t{0});
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
@@ -6,12 +6,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct CredentialKeyletImpl : WasmImplTest
|
||||
@@ -20,23 +16,19 @@ struct CredentialKeyletImpl : WasmImplTest
|
||||
|
||||
TEST_F(CredentialKeyletImpl, MatchesCredentialKeyletFunction)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto const credTypeStr = std::string{"test"};
|
||||
auto const credType = Slice{credTypeStr.data(), credTypeStr.size()};
|
||||
|
||||
auto const expected = keylet::credential(owner.id(), owner.id(), credType);
|
||||
auto const expectedBytes = Bytes{std::begin(expected.key), std::end(expected.key)};
|
||||
auto const result = host().credentialKeylet(owner.id(), owner.id(), credType);
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, expectedBytes);
|
||||
expectKeyletMatches(
|
||||
makeHost()->credentialKeylet(owner.id(), owner.id(), credType),
|
||||
keylet::credential(owner.id(), owner.id(), credType));
|
||||
}
|
||||
|
||||
TEST_F(CredentialKeyletImpl, CredentialTypeStringTooLong)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto constexpr credTypeStr = std::string_view{
|
||||
"abcdefghijklmnopqrstuvwxyz01234567890qwertyuiop[]"
|
||||
@@ -44,26 +36,25 @@ TEST_F(CredentialKeyletImpl, CredentialTypeStringTooLong)
|
||||
static_assert(credTypeStr.size() > kMaxCredentialTypeLength);
|
||||
auto const credType = Slice{credTypeStr.data(), credTypeStr.size()};
|
||||
|
||||
auto const result = host().credentialKeylet(owner.id(), owner.id(), credType);
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidParams);
|
||||
expectError(
|
||||
makeHost()->credentialKeylet(owner.id(), owner.id(), credType),
|
||||
HostFunctionError::InvalidParams);
|
||||
}
|
||||
|
||||
TEST_F(CredentialKeyletImpl, InvalidAccount)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto const credTypeStr = std::string{"test"};
|
||||
auto const credType = Slice{credTypeStr.data(), credTypeStr.size()};
|
||||
|
||||
auto result = host().credentialKeylet(AccountID{}, owner.id(), credType);
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(
|
||||
makeHost()->credentialKeylet(AccountID{}, owner.id(), credType),
|
||||
HostFunctionError::InvalidAccount);
|
||||
|
||||
result = host().credentialKeylet(owner.id(), AccountID{}, credType);
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(
|
||||
makeHost()->credentialKeylet(owner.id(), AccountID{}, credType),
|
||||
HostFunctionError::InvalidAccount);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct CurrentLedgerObjArrayLenImpl : WasmImplTest
|
||||
{
|
||||
using WasmImplTest::makeHost;
|
||||
|
||||
WasmHost
|
||||
makeHost(Account const& acct)
|
||||
{
|
||||
makeSignerList(acct, 2, {{Account{"alice"}, 1}, {Account{"becky"}, 1}});
|
||||
auto assembler = bareTx();
|
||||
return makeHost(keylet::signerList(acct.id()), assembler.type, std::move(assembler.build));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(CurrentLedgerObjArrayLenImpl, SignerEntriesLength)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectValue(h->getCurrentLedgerObjArrayLen(sfSignerEntries), 2);
|
||||
}
|
||||
|
||||
TEST_F(CurrentLedgerObjArrayLenImpl, NonArrayFieldNoArray)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectError(h->getCurrentLedgerObjArrayLen(sfAccount), HostFunctionError::NoArray);
|
||||
}
|
||||
|
||||
TEST_F(CurrentLedgerObjArrayLenImpl, MissingArrayFieldNotFound)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectError(h->getCurrentLedgerObjArrayLen(sfMemos), HostFunctionError::FieldNotFound);
|
||||
}
|
||||
|
||||
TEST_F(CurrentLedgerObjArrayLenImpl, MissingCurrentObjectNotFound)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto assembler = bareTx();
|
||||
auto h = makeHost(keylet::signerList(owner.id()), assembler.type, std::move(assembler.build));
|
||||
expectError(
|
||||
h->getCurrentLedgerObjArrayLen(sfSignerEntries), HostFunctionError::LedgerObjNotFound);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
@@ -12,9 +12,6 @@
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct CurrentLedgerObjFieldImpl : WasmImplTest
|
||||
@@ -49,11 +46,7 @@ TEST_F(CurrentLedgerObjFieldImpl, ReadsfAccount)
|
||||
auto const escrow = makeEscrow(owner, Account{"dest"});
|
||||
ASSERT_NE(ledger.getOpenLedger().read(escrow), nullptr) << "escrow object should exist";
|
||||
|
||||
auto const account = host(escrow).getCurrentLedgerObjField(sfAccount);
|
||||
|
||||
ASSERT_TRUE(account.has_value());
|
||||
auto const ownerBytes = Bytes{std::begin(owner.id()), std::end(owner.id())};
|
||||
EXPECT_EQ(*account, ownerBytes);
|
||||
expectValue(makeHost(escrow)->getCurrentLedgerObjField(sfAccount), toBytes(owner.id()));
|
||||
}
|
||||
|
||||
TEST_F(CurrentLedgerObjFieldImpl, ReadsfAccountDummyEscrow)
|
||||
@@ -63,10 +56,9 @@ TEST_F(CurrentLedgerObjFieldImpl, ReadsfAccountDummyEscrow)
|
||||
auto const ownerSeq = ledger.getAccountRoot(owner.id()).getSequence();
|
||||
auto const escrow = keylet::escrow(owner.id(), SeqProxy::rawSequence(ownerSeq));
|
||||
|
||||
auto const account = host(escrow).getCurrentLedgerObjField(sfAccount);
|
||||
|
||||
ASSERT_TRUE(!account.has_value());
|
||||
ASSERT_TRUE(account.error() == HostFunctionError::LedgerObjNotFound);
|
||||
expectError(
|
||||
makeHost(escrow)->getCurrentLedgerObjField(sfAccount),
|
||||
HostFunctionError::LedgerObjNotFound);
|
||||
}
|
||||
|
||||
TEST_F(CurrentLedgerObjFieldImpl, ReadAmount)
|
||||
@@ -75,9 +67,7 @@ TEST_F(CurrentLedgerObjFieldImpl, ReadAmount)
|
||||
auto const escrow = makeEscrow(owner, Account{"dest"});
|
||||
ASSERT_NE(ledger.getOpenLedger().read(escrow), nullptr) << "escrow object should exist";
|
||||
|
||||
auto const amount = host(escrow).getCurrentLedgerObjField(sfAmount);
|
||||
ASSERT_TRUE(amount.has_value());
|
||||
EXPECT_EQ(*amount, toBytes(XRP(100)));
|
||||
expectValue(makeHost(escrow)->getCurrentLedgerObjField(sfAmount), toBytes(XRP(100)));
|
||||
}
|
||||
|
||||
TEST_F(CurrentLedgerObjFieldImpl, ReadPreviousTxnID)
|
||||
@@ -87,10 +77,8 @@ TEST_F(CurrentLedgerObjFieldImpl, ReadPreviousTxnID)
|
||||
auto const escrow = makeEscrow(owner, Account{"dest"}, &transactionId);
|
||||
ASSERT_NE(ledger.getOpenLedger().read(escrow), nullptr) << "escrow object should exist";
|
||||
|
||||
auto const previousTxnId = host(escrow).getCurrentLedgerObjField(sfPreviousTxnID);
|
||||
|
||||
ASSERT_TRUE(previousTxnId.has_value());
|
||||
EXPECT_EQ(*previousTxnId, toBytes(transactionId));
|
||||
expectValue(
|
||||
makeHost(escrow)->getCurrentLedgerObjField(sfPreviousTxnID), toBytes(transactionId));
|
||||
}
|
||||
|
||||
TEST_F(CurrentLedgerObjFieldImpl, ReadOwner)
|
||||
@@ -99,10 +87,8 @@ TEST_F(CurrentLedgerObjFieldImpl, ReadOwner)
|
||||
auto const escrow = makeEscrow(owner, Account{"dest"});
|
||||
ASSERT_NE(ledger.getOpenLedger().read(escrow), nullptr) << "escrow object should exist";
|
||||
|
||||
auto const ownerField = host(escrow).getCurrentLedgerObjField(sfOwner);
|
||||
|
||||
ASSERT_TRUE(!ownerField.has_value());
|
||||
ASSERT_TRUE(ownerField.error() == HostFunctionError::FieldNotFound);
|
||||
expectError(
|
||||
makeHost(escrow)->getCurrentLedgerObjField(sfOwner), HostFunctionError::FieldNotFound);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct CurrentLedgerObjNestedArrayLenImpl : WasmImplTest
|
||||
{
|
||||
using WasmImplTest::makeHost;
|
||||
|
||||
WasmHost
|
||||
makeHost(Account const& acct)
|
||||
{
|
||||
makeSignerList(acct, 2, {{Account{"alice"}, 1}, {Account{"becky"}, 1}});
|
||||
auto assembler = bareTx();
|
||||
return makeHost(keylet::signerList(acct.id()), assembler.type, std::move(assembler.build));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(CurrentLedgerObjNestedArrayLenImpl, SignerEntriesLength)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectValue(h->getCurrentLedgerObjNestedArrayLen(FieldLocator{{sfSignerEntries.getCode()}}), 2);
|
||||
}
|
||||
|
||||
TEST_F(CurrentLedgerObjNestedArrayLenImpl, NonArrayFieldNoArray)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectError(
|
||||
h->getCurrentLedgerObjNestedArrayLen(FieldLocator{{sfSignerQuorum.getCode()}}),
|
||||
HostFunctionError::NoArray);
|
||||
}
|
||||
|
||||
TEST_F(CurrentLedgerObjNestedArrayLenImpl, MissingFieldNotFound)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectError(
|
||||
h->getCurrentLedgerObjNestedArrayLen(FieldLocator{{sfSigners.getCode()}}),
|
||||
HostFunctionError::FieldNotFound);
|
||||
}
|
||||
|
||||
TEST_F(CurrentLedgerObjNestedArrayLenImpl, MissingCurrentObjectNotFound)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto assembler = bareTx();
|
||||
auto h = makeHost(keylet::signerList(owner.id()), assembler.type, std::move(assembler.build));
|
||||
expectError(
|
||||
h->getCurrentLedgerObjNestedArrayLen(FieldLocator{{sfSignerEntries.getCode()}}),
|
||||
HostFunctionError::LedgerObjNotFound);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
@@ -0,0 +1,122 @@
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STArray.h>
|
||||
#include <xrpl/protocol/STObject.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct CurrentLedgerObjNestedFieldImpl : WasmImplTest
|
||||
{
|
||||
using WasmImplTest::makeHost;
|
||||
|
||||
WasmHost
|
||||
makeHost(Account const& acct)
|
||||
{
|
||||
makeSignerList(acct, 2, {{Account{"alice"}, 1}, {Account{"becky"}, 1}});
|
||||
auto assembler = bareTx();
|
||||
return makeHost(keylet::signerList(acct.id()), assembler.type, std::move(assembler.build));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(CurrentLedgerObjNestedFieldImpl, MatchesNestedSignerQuorum)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectValue(
|
||||
h->getCurrentLedgerObjNestedField(FieldLocator{{sfSignerQuorum.getCode()}}),
|
||||
toBytes(static_cast<std::uint32_t>(2)));
|
||||
}
|
||||
|
||||
TEST_F(CurrentLedgerObjNestedFieldImpl, MatchesNestedSignerWeight)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectValue(
|
||||
h->getCurrentLedgerObjNestedField(
|
||||
FieldLocator{{sfSignerEntries.getCode(), 0, sfSignerWeight.getCode()}}),
|
||||
toBytes(static_cast<std::uint16_t>(1)));
|
||||
}
|
||||
|
||||
TEST_F(CurrentLedgerObjNestedFieldImpl, MatchesNestedSignerAccount)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
|
||||
auto const sle = ledger.getOpenLedger().read(keylet::signerList(owner.id()));
|
||||
ASSERT_NE(sle, nullptr);
|
||||
auto const& entry0 = sle->getFieldArray(sfSignerEntries)[0];
|
||||
|
||||
expectValue(
|
||||
h->getCurrentLedgerObjNestedField(
|
||||
FieldLocator{{sfSignerEntries.getCode(), 0, sfAccount.getCode()}}),
|
||||
toBytes(entry0.getAccountID(sfAccount)));
|
||||
}
|
||||
|
||||
TEST_F(CurrentLedgerObjNestedFieldImpl, MissingFieldNotFound)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectError(
|
||||
h->getCurrentLedgerObjNestedField(
|
||||
FieldLocator{{sfSigners.getCode(), 0, sfAccount.getCode()}}),
|
||||
HostFunctionError::FieldNotFound);
|
||||
}
|
||||
|
||||
TEST_F(CurrentLedgerObjNestedFieldImpl, IndexOutOfBounds)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
auto const err = HostFunctionError::IndexOutOfBounds;
|
||||
|
||||
expectError(
|
||||
h->getCurrentLedgerObjNestedField(
|
||||
FieldLocator{{sfSignerEntries.getCode(), 2, sfAccount.getCode()}}),
|
||||
err);
|
||||
expectError(
|
||||
h->getCurrentLedgerObjNestedField(
|
||||
FieldLocator{{sfSignerEntries.getCode(), -1, sfAccount.getCode()}}),
|
||||
err);
|
||||
}
|
||||
|
||||
TEST_F(CurrentLedgerObjNestedFieldImpl, UnknownFieldCodeInvalidField)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
auto const err = HostFunctionError::InvalidField;
|
||||
|
||||
expectError(h->getCurrentLedgerObjNestedField(FieldLocator{{fieldCode(20000, 20000)}}), err);
|
||||
expectError(
|
||||
h->getCurrentLedgerObjNestedField(
|
||||
FieldLocator{{sfSignerEntries.getCode(), 0, fieldCode(20000, 20000)}}),
|
||||
err);
|
||||
}
|
||||
|
||||
TEST_F(CurrentLedgerObjNestedFieldImpl, NestIntoNonContainerMalformed)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectError(
|
||||
h->getCurrentLedgerObjNestedField(
|
||||
FieldLocator{{sfSignerQuorum.getCode(), 0, sfAccount.getCode()}}),
|
||||
HostFunctionError::LocatorMalformed);
|
||||
}
|
||||
|
||||
TEST_F(CurrentLedgerObjNestedFieldImpl, MissingCurrentObjectNotFound)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto assembler = bareTx();
|
||||
auto h = makeHost(keylet::signerList(owner.id()), assembler.type, std::move(assembler.build));
|
||||
expectError(
|
||||
h->getCurrentLedgerObjNestedField(FieldLocator{{sfSignerQuorum.getCode()}}),
|
||||
HostFunctionError::LedgerObjNotFound);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
@@ -4,12 +4,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct DelegateKeyletImpl : WasmImplTest
|
||||
@@ -18,40 +14,31 @@ struct DelegateKeyletImpl : WasmImplTest
|
||||
|
||||
TEST_F(DelegateKeyletImpl, MatchesDelegateKeyletFunction)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const delegate = Account{"delegate"};
|
||||
ledger.createAccount(delegate, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
auto const delegate = fund("delegate");
|
||||
|
||||
auto const expected = keylet::delegate(owner.id(), delegate.id());
|
||||
auto const expectedBytes = Bytes{std::begin(expected.key), std::end(expected.key)};
|
||||
auto const result = host().delegateKeylet(owner.id(), delegate.id());
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, expectedBytes);
|
||||
expectKeyletMatches(
|
||||
makeHost()->delegateKeylet(owner.id(), delegate.id()),
|
||||
keylet::delegate(owner.id(), delegate.id()));
|
||||
}
|
||||
|
||||
TEST_F(DelegateKeyletImpl, CantDelegateToSelf)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto const result = host().delegateKeylet(owner.id(), owner.id());
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidParams);
|
||||
expectError(
|
||||
makeHost()->delegateKeylet(owner.id(), owner.id()), HostFunctionError::InvalidParams);
|
||||
}
|
||||
|
||||
TEST_F(DelegateKeyletImpl, InvalidAccount)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto result = host().delegateKeylet(AccountID{}, owner.id());
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(
|
||||
makeHost()->delegateKeylet(AccountID{}, owner.id()), HostFunctionError::InvalidAccount);
|
||||
|
||||
result = host().delegateKeylet(owner.id(), AccountID{});
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(
|
||||
makeHost()->delegateKeylet(owner.id(), AccountID{}), HostFunctionError::InvalidAccount);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -4,12 +4,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct DepositPreauthKeyletImpl : WasmImplTest
|
||||
@@ -18,40 +14,33 @@ struct DepositPreauthKeyletImpl : WasmImplTest
|
||||
|
||||
TEST_F(DepositPreauthKeyletImpl, MatchesDepositPreauthKeyletFunction)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const destination = Account{"destination"};
|
||||
ledger.createAccount(destination, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
auto const destination = fund("destination");
|
||||
|
||||
auto const expected = keylet::depositPreauth(owner.id(), destination.id());
|
||||
auto const expectedBytes = Bytes{std::begin(expected.key), std::end(expected.key)};
|
||||
auto const result = host().depositPreauthKeylet(owner.id(), destination.id());
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, expectedBytes);
|
||||
expectKeyletMatches(
|
||||
makeHost()->depositPreauthKeylet(owner.id(), destination.id()),
|
||||
keylet::depositPreauth(owner.id(), destination.id()));
|
||||
}
|
||||
|
||||
TEST_F(DepositPreauthKeyletImpl, CantPreauthToSelf)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto const result = host().depositPreauthKeylet(owner.id(), owner.id());
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidParams);
|
||||
expectError(
|
||||
makeHost()->depositPreauthKeylet(owner.id(), owner.id()), HostFunctionError::InvalidParams);
|
||||
}
|
||||
|
||||
TEST_F(DepositPreauthKeyletImpl, InvalidAccount)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto result = host().depositPreauthKeylet(AccountID{}, owner.id());
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(
|
||||
makeHost()->depositPreauthKeylet(AccountID{}, owner.id()),
|
||||
HostFunctionError::InvalidAccount);
|
||||
|
||||
result = host().depositPreauthKeylet(owner.id(), AccountID{});
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(
|
||||
makeHost()->depositPreauthKeylet(owner.id(), AccountID{}),
|
||||
HostFunctionError::InvalidAccount);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -4,12 +4,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct DidKeyletImpl : WasmImplTest
|
||||
@@ -18,21 +14,14 @@ struct DidKeyletImpl : WasmImplTest
|
||||
|
||||
TEST_F(DidKeyletImpl, MatchesDidKeyletFunction)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto const expected = keylet::did(owner.id());
|
||||
auto const expectedBytes = Bytes{std::begin(expected.key), std::end(expected.key)};
|
||||
auto const result = host().didKeylet(owner.id());
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, expectedBytes);
|
||||
expectKeyletMatches(makeHost()->didKeylet(owner.id()), keylet::did(owner.id()));
|
||||
}
|
||||
|
||||
TEST_F(DidKeyletImpl, InvalidAccount)
|
||||
{
|
||||
auto result = host().didKeylet(AccountID{});
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(makeHost()->didKeylet(AccountID{}), HostFunctionError::InvalidAccount);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
@@ -22,18 +20,15 @@ TEST_F(EscrowKeyletImpl, MatchesLedgerKeyletFunction)
|
||||
auto const owner = Account{"owner"};
|
||||
auto const seq = std::uint32_t{42};
|
||||
|
||||
auto const result = host().escrowKeylet(owner.id(), seq);
|
||||
|
||||
ASSERT_TRUE(result.has_value());
|
||||
auto const expected = keylet::escrow(owner.id(), SeqProxy::rawSequence(seq)).key;
|
||||
auto const expectedBytes = Bytes{std::begin(expected), std::end(expected)};
|
||||
EXPECT_EQ(*result, expectedBytes);
|
||||
expectKeyletMatches(
|
||||
makeHost()->escrowKeylet(owner.id(), seq),
|
||||
keylet::escrow(owner.id(), SeqProxy::rawSequence(seq)));
|
||||
}
|
||||
|
||||
TEST_F(EscrowKeyletImpl, DifferentAccountsGiveDifferentKeylets)
|
||||
{
|
||||
auto const a = host().escrowKeylet(Account{"alice"}.id(), 7);
|
||||
auto const b = host().escrowKeylet(Account{"becky"}.id(), 7);
|
||||
auto const a = makeHost()->escrowKeylet(Account{"alice"}.id(), 7);
|
||||
auto const b = makeHost()->escrowKeylet(Account{"becky"}.id(), 7);
|
||||
|
||||
ASSERT_TRUE(a.has_value() && b.has_value());
|
||||
EXPECT_NE(*a, *b);
|
||||
@@ -41,10 +36,7 @@ TEST_F(EscrowKeyletImpl, DifferentAccountsGiveDifferentKeylets)
|
||||
|
||||
TEST_F(EscrowKeyletImpl, UnsetAccountIsInvalidAccount)
|
||||
{
|
||||
auto const result = host().escrowKeylet(AccountID{}, 1);
|
||||
|
||||
ASSERT_FALSE(result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(makeHost()->escrowKeylet(AccountID{}, 1), HostFunctionError::InvalidAccount);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
46
src/tests/libxrpl/tx/wasm/host_functions/FloatAdd.cpp
Normal file
46
src/tests/libxrpl/tx/wasm/host_functions/FloatAdd.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/FloatFixture.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct FloatAddImpl : FloatTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(FloatAddImpl, BadModeIsMalformed)
|
||||
{
|
||||
expectError(
|
||||
makeHost()->floatAdd(slice(floats::kOne), slice(floats::kOne), -1),
|
||||
HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatAddImpl, MalformedInput)
|
||||
{
|
||||
expectError(
|
||||
makeHost()->floatAdd(slice(floats::kOne), Slice{}, 0),
|
||||
HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatAddImpl, MaxIouPlusMaxExpIsMaxExp)
|
||||
{
|
||||
expectValue(
|
||||
makeHost()->floatAdd(slice(floats::kMaxIOU), slice(floats::kMaxExp), 0), floats::kMaxExp);
|
||||
}
|
||||
|
||||
TEST_F(FloatAddImpl, MinPlusZeroIsMin)
|
||||
{
|
||||
expectValue(
|
||||
makeHost()->floatAdd(slice(floats::kIntMin), slice(floats::kIntZero), 0), floats::kIntMin);
|
||||
}
|
||||
|
||||
TEST_F(FloatAddImpl, MaxPlusMinIsZero)
|
||||
{
|
||||
expectValue(
|
||||
makeHost()->floatAdd(slice(floats::kIntMax), slice(floats::kIntMin), 0), floats::kIntZero);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
48
src/tests/libxrpl/tx/wasm/host_functions/FloatCompare.cpp
Normal file
48
src/tests/libxrpl/tx/wasm/host_functions/FloatCompare.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/FloatFixture.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct FloatCompareImpl : FloatTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(FloatCompareImpl, MalformedInputs)
|
||||
{
|
||||
// A wrong-size (here empty) buffer is malformed; the impl normalizes any well-formed
|
||||
// 12-byte buffer, so size is the only rejection.
|
||||
expectError(makeHost()->floatCompare(Slice{}, Slice{}), HostFunctionError::FloatInputMalformed);
|
||||
expectError(
|
||||
makeHost()->floatCompare(slice(floats::kOne), Slice{}),
|
||||
HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatCompareImpl, Less)
|
||||
{
|
||||
expectValue(makeHost()->floatCompare(slice(floats::kIntMin), slice(floats::kIntZero)), 2);
|
||||
}
|
||||
|
||||
TEST_F(FloatCompareImpl, Greater)
|
||||
{
|
||||
expectValue(makeHost()->floatCompare(slice(floats::kIntMax), slice(floats::kIntZero)), 1);
|
||||
}
|
||||
|
||||
TEST_F(FloatCompareImpl, Equal)
|
||||
{
|
||||
expectValue(makeHost()->floatCompare(slice(floats::kOne), slice(floats::kOne)), 0);
|
||||
}
|
||||
|
||||
// A non-canonical encoding of 10 (mantissa 100000, exponent -4) is normalized on decode, so
|
||||
// it compares equal to the canonical 10 — the impl accepts any well-formed 12-byte buffer.
|
||||
TEST_F(FloatCompareImpl, NonCanonicalNormalizes)
|
||||
{
|
||||
Bytes const nonCanonicalTen{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x86, 0xA0, 0xFF, 0xFF, 0xFF, 0xFC};
|
||||
expectValue(makeHost()->floatCompare(slice(nonCanonicalTen), slice(floats::kTen)), 0);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
70
src/tests/libxrpl/tx/wasm/host_functions/FloatDivide.cpp
Normal file
70
src/tests/libxrpl/tx/wasm/host_functions/FloatDivide.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/FloatFixture.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct FloatDivideImpl : FloatTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(FloatDivideImpl, BadModeIsMalformed)
|
||||
{
|
||||
expectError(
|
||||
makeHost()->floatDivide(slice(floats::kOne), slice(floats::kOne), -1),
|
||||
HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatDivideImpl, MalformedInput)
|
||||
{
|
||||
expectError(
|
||||
makeHost()->floatDivide(slice(floats::kOne), Slice{}, 0),
|
||||
HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatDivideImpl, DivideByZeroIsComputationError)
|
||||
{
|
||||
expectError(
|
||||
makeHost()->floatDivide(slice(floats::kOne), slice(floats::kIntZero), 0),
|
||||
HostFunctionError::FloatComputationError);
|
||||
}
|
||||
|
||||
TEST_F(FloatDivideImpl, OverflowIsComputationError)
|
||||
{
|
||||
// A divisor just below 1, so max / it overflows.
|
||||
auto const y = makeHost()->floatFromMantExp(STAmount::kMaxValue, -floats::kNormalExp - 1, 0);
|
||||
ASSERT_TRUE(y.has_value());
|
||||
expectError(
|
||||
makeHost()->floatDivide(slice(floats::kMax), slice(*y), 0),
|
||||
HostFunctionError::FloatComputationError);
|
||||
}
|
||||
|
||||
TEST_F(FloatDivideImpl, ZeroDividedByOneIsZero)
|
||||
{
|
||||
expectValue(
|
||||
makeHost()->floatDivide(slice(floats::kIntZero), slice(floats::kOne), 0), floats::kIntZero);
|
||||
}
|
||||
|
||||
TEST_F(FloatDivideImpl, MaxExpDividedByTenIsPreMaxExp)
|
||||
{
|
||||
expectValue(
|
||||
makeHost()->floatDivide(slice(floats::kMaxExp), slice(floats::kTen), 0),
|
||||
floats::kPreMaxExp);
|
||||
}
|
||||
|
||||
// The rounding mode changes an inexact result: 1/3 rounded Downward differs from Upward.
|
||||
TEST_F(FloatDivideImpl, RoundingModeAffectsInexactResult)
|
||||
{
|
||||
auto const three = makeHost()->floatFromInt(3, 0);
|
||||
ASSERT_TRUE(three.has_value());
|
||||
auto const down = makeHost()->floatDivide(slice(floats::kOne), slice(*three), 2);
|
||||
auto const up = makeHost()->floatDivide(slice(floats::kOne), slice(*three), 3);
|
||||
ASSERT_TRUE(down.has_value() && up.has_value());
|
||||
EXPECT_NE(*down, *up);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
34
src/tests/libxrpl/tx/wasm/host_functions/FloatFromInt.cpp
Normal file
34
src/tests/libxrpl/tx/wasm/host_functions/FloatFromInt.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/FloatFixture.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct FloatFromIntImpl : FloatTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(FloatFromIntImpl, BadModeIsMalformed)
|
||||
{
|
||||
expectError(makeHost()->floatFromInt(kMin64, -1), HostFunctionError::FloatInputMalformed);
|
||||
expectError(makeHost()->floatFromInt(kMin64, 4), HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatFromIntImpl, MinInt)
|
||||
{
|
||||
expectValue(makeHost()->floatFromInt(kMin64, 0), floats::kIntMin);
|
||||
}
|
||||
|
||||
TEST_F(FloatFromIntImpl, Zero)
|
||||
{
|
||||
expectValue(makeHost()->floatFromInt(0, 0), floats::kIntZero);
|
||||
}
|
||||
|
||||
TEST_F(FloatFromIntImpl, MaxInt)
|
||||
{
|
||||
expectValue(makeHost()->floatFromInt(kMax64, 0), floats::kIntMax);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
@@ -0,0 +1,68 @@
|
||||
#include <xrpl/basics/Number.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/FloatFixture.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct FloatFromMantExpImpl : FloatTest
|
||||
{
|
||||
static constexpr int kMaxRawExp = Number::kMaxExponent + floats::kNormalExp;
|
||||
static constexpr int kMinRawExp = Number::kMinExponent + floats::kNormalExp;
|
||||
};
|
||||
|
||||
TEST_F(FloatFromMantExpImpl, BadModeIsMalformed)
|
||||
{
|
||||
expectError(makeHost()->floatFromMantExp(1, 0, -1), HostFunctionError::FloatInputMalformed);
|
||||
expectError(makeHost()->floatFromMantExp(1, 0, 4), HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatFromMantExpImpl, ExponentTooHighIsMalformed)
|
||||
{
|
||||
expectError(
|
||||
makeHost()->floatFromMantExp(1, kMaxRawExp + 1, 0), HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatFromMantExpImpl, UnderflowIsZero)
|
||||
{
|
||||
expectValue(makeHost()->floatFromMantExp(1, kMinRawExp - 1, 0), floats::kIntZero);
|
||||
}
|
||||
|
||||
TEST_F(FloatFromMantExpImpl, MaxExponent)
|
||||
{
|
||||
expectValue(makeHost()->floatFromMantExp(1, kMaxRawExp, 0), floats::kMaxExp);
|
||||
}
|
||||
|
||||
TEST_F(FloatFromMantExpImpl, MinusMaxExponent)
|
||||
{
|
||||
expectValue(makeHost()->floatFromMantExp(-1, kMaxRawExp, 0), floats::kMinusMaxExp);
|
||||
}
|
||||
|
||||
TEST_F(FloatFromMantExpImpl, PreMaxExponent)
|
||||
{
|
||||
expectValue(makeHost()->floatFromMantExp(1, kMaxRawExp - 1, 0), floats::kPreMaxExp);
|
||||
}
|
||||
|
||||
TEST_F(FloatFromMantExpImpl, MaxIou)
|
||||
{
|
||||
expectValue(
|
||||
makeHost()->floatFromMantExp(STAmount::kMaxValue, STAmount::kMaxOffset, 0),
|
||||
floats::kMaxIOU);
|
||||
}
|
||||
|
||||
TEST_F(FloatFromMantExpImpl, MinExponent)
|
||||
{
|
||||
expectValue(
|
||||
makeHost()->floatFromMantExp(1, Number::kMinExponent - floats::kNormalExp, 0),
|
||||
floats::kMinExp);
|
||||
}
|
||||
|
||||
TEST_F(FloatFromMantExpImpl, TenTimesTenthIsOne)
|
||||
{
|
||||
expectValue(makeHost()->floatFromMantExp(10, -1, 0), floats::kOne);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
@@ -0,0 +1,67 @@
|
||||
#include <xrpl/protocol/IOUAmount.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/FloatFixture.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct FloatFromStAmountImpl : FloatTest
|
||||
{
|
||||
static Issue
|
||||
usd()
|
||||
{
|
||||
return Issue{toCurrency("USD"), Account{"gw"}.id()};
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(FloatFromStAmountImpl, BadModeIsMalformed)
|
||||
{
|
||||
auto const amount = STAmount{XRP(100)};
|
||||
expectError(makeHost()->floatFromSTAmount(amount, -1), HostFunctionError::FloatInputMalformed);
|
||||
expectError(makeHost()->floatFromSTAmount(amount, 4), HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatFromStAmountImpl, ZeroXrp)
|
||||
{
|
||||
expectValue(makeHost()->floatFromSTAmount(STAmount{XRP(0)}, 0), floats::kIntZero);
|
||||
}
|
||||
|
||||
TEST_F(FloatFromStAmountImpl, MinusOneXrp)
|
||||
{
|
||||
// -1 XRP == -1'000'000 drops.
|
||||
auto const expected = makeHost()->floatFromMantExp(-1'000'000, 0, 0);
|
||||
ASSERT_TRUE(expected.has_value());
|
||||
expectValue(makeHost()->floatFromSTAmount(STAmount{XRP(-1)}, 0), *expected);
|
||||
}
|
||||
|
||||
TEST_F(FloatFromStAmountImpl, MaxDrops)
|
||||
{
|
||||
auto const expected = makeHost()->floatFromMantExp(9'223'372'036'854'776, 3, 0);
|
||||
ASSERT_TRUE(expected.has_value());
|
||||
expectValue(makeHost()->floatFromSTAmount(STAmount{noIssue(), kMax64}, 0), *expected);
|
||||
}
|
||||
|
||||
TEST_F(FloatFromStAmountImpl, MinIou)
|
||||
{
|
||||
auto const amount = STAmount{
|
||||
IOUAmount{static_cast<std::int64_t>(STAmount::kMinValue), STAmount::kMinOffset}, usd()};
|
||||
expectValue(makeHost()->floatFromSTAmount(amount, 0), floats::kMinIOU);
|
||||
}
|
||||
|
||||
TEST_F(FloatFromStAmountImpl, MaxIou)
|
||||
{
|
||||
auto const amount = STAmount{
|
||||
IOUAmount{static_cast<std::int64_t>(STAmount::kMaxValue), STAmount::kMaxOffset}, usd()};
|
||||
expectValue(makeHost()->floatFromSTAmount(amount, 0), floats::kMaxIOU);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
@@ -0,0 +1,39 @@
|
||||
#include <xrpl/basics/Number.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STNumber.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/FloatFixture.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct FloatFromStNumberImpl : FloatTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(FloatFromStNumberImpl, BadModeIsMalformed)
|
||||
{
|
||||
auto const n = STNumber{sfNumber, Number(123, 0)};
|
||||
expectError(makeHost()->floatFromSTNumber(n, -1), HostFunctionError::FloatInputMalformed);
|
||||
expectError(makeHost()->floatFromSTNumber(n, 4), HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatFromStNumberImpl, MaxUint)
|
||||
{
|
||||
auto const n = STNumber{
|
||||
sfNumber, Number(std::numeric_limits<std::uint64_t>::max(), 0, Number::Normalized{})};
|
||||
expectValue(makeHost()->floatFromSTNumber(n, 0), floats::kUintMax);
|
||||
}
|
||||
|
||||
TEST_F(FloatFromStNumberImpl, MinusMaxExponent)
|
||||
{
|
||||
auto const n = STNumber{sfNumber, Number(-1, Number::kMaxExponent + floats::kNormalExp)};
|
||||
expectValue(makeHost()->floatFromSTNumber(n, 0), floats::kMinusMaxExp);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
33
src/tests/libxrpl/tx/wasm/host_functions/FloatFromUint.cpp
Normal file
33
src/tests/libxrpl/tx/wasm/host_functions/FloatFromUint.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/FloatFixture.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct FloatFromUintImpl : FloatTest
|
||||
{
|
||||
static constexpr std::uint64_t kMaxU64 = std::numeric_limits<std::uint64_t>::max();
|
||||
};
|
||||
|
||||
TEST_F(FloatFromUintImpl, BadModeIsMalformed)
|
||||
{
|
||||
expectError(makeHost()->floatFromUint(0, -1), HostFunctionError::FloatInputMalformed);
|
||||
expectError(makeHost()->floatFromUint(0, 4), HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatFromUintImpl, Zero)
|
||||
{
|
||||
expectValue(makeHost()->floatFromUint(0, 0), floats::kIntZero);
|
||||
}
|
||||
|
||||
TEST_F(FloatFromUintImpl, MaxUint)
|
||||
{
|
||||
expectValue(makeHost()->floatFromUint(kMaxU64, 0), floats::kUintMax);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
55
src/tests/libxrpl/tx/wasm/host_functions/FloatMultiply.cpp
Normal file
55
src/tests/libxrpl/tx/wasm/host_functions/FloatMultiply.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/FloatFixture.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct FloatMultiplyImpl : FloatTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(FloatMultiplyImpl, BadModeIsMalformed)
|
||||
{
|
||||
expectError(
|
||||
makeHost()->floatMultiply(slice(floats::kOne), slice(floats::kOne), -1),
|
||||
HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatMultiplyImpl, MalformedInput)
|
||||
{
|
||||
expectError(
|
||||
makeHost()->floatMultiply(slice(floats::kOne), Slice{}, 0),
|
||||
HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatMultiplyImpl, OverflowIsComputationError)
|
||||
{
|
||||
expectError(
|
||||
makeHost()->floatMultiply(slice(floats::kMax), slice(floats::kOneMore), 0),
|
||||
HostFunctionError::FloatComputationError);
|
||||
}
|
||||
|
||||
TEST_F(FloatMultiplyImpl, OneTimesOneIsOne)
|
||||
{
|
||||
expectValue(
|
||||
makeHost()->floatMultiply(slice(floats::kOne), slice(floats::kOne), 0), floats::kOne);
|
||||
}
|
||||
|
||||
TEST_F(FloatMultiplyImpl, ZeroTimesMaxIouIsZero)
|
||||
{
|
||||
expectValue(
|
||||
makeHost()->floatMultiply(slice(floats::kIntZero), slice(floats::kMaxIOU), 0),
|
||||
floats::kIntZero);
|
||||
}
|
||||
|
||||
TEST_F(FloatMultiplyImpl, TenTimesPreMaxExpIsMaxExp)
|
||||
{
|
||||
expectValue(
|
||||
makeHost()->floatMultiply(slice(floats::kTen), slice(floats::kPreMaxExp), 0),
|
||||
floats::kMaxExp);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
71
src/tests/libxrpl/tx/wasm/host_functions/FloatPower.cpp
Normal file
71
src/tests/libxrpl/tx/wasm/host_functions/FloatPower.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#include <xrpl/basics/Number.h>
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/FloatFixture.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct FloatPowerImpl : FloatTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(FloatPowerImpl, BadModeIsMalformed)
|
||||
{
|
||||
expectError(
|
||||
makeHost()->floatPower(slice(floats::kOne), 2, -1), HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatPowerImpl, MalformedInput)
|
||||
{
|
||||
expectError(makeHost()->floatPower(Slice{}, 3, 0), HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatPowerImpl, NegativeDegreeIsMalformed)
|
||||
{
|
||||
expectError(
|
||||
makeHost()->floatPower(slice(floats::kOne), -2, 0), HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatPowerImpl, OverflowIsComputationError)
|
||||
{
|
||||
expectError(
|
||||
makeHost()->floatPower(slice(floats::kMax), 2, 0),
|
||||
HostFunctionError::FloatComputationError);
|
||||
}
|
||||
|
||||
TEST_F(FloatPowerImpl, DegreeTooLargeIsMalformed)
|
||||
{
|
||||
expectError(
|
||||
makeHost()->floatPower(slice(floats::kMax), Number::kMaxExponent + 1, 0),
|
||||
HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatPowerImpl, DegreeZeroIsOne)
|
||||
{
|
||||
expectValue(makeHost()->floatPower(slice(floats::kMaxIOU), 0, 0), floats::kOne);
|
||||
}
|
||||
|
||||
TEST_F(FloatPowerImpl, DegreeOneIsIdentity)
|
||||
{
|
||||
expectValue(makeHost()->floatPower(slice(floats::kMaxIOU), 1, 0), floats::kMaxIOU);
|
||||
}
|
||||
|
||||
TEST_F(FloatPowerImpl, TenSquaredIsHundred)
|
||||
{
|
||||
auto const hundred = makeHost()->floatFromMantExp(100, 0, 0);
|
||||
ASSERT_TRUE(hundred.has_value());
|
||||
expectValue(makeHost()->floatPower(slice(floats::kTen), 2, 0), *hundred);
|
||||
}
|
||||
|
||||
TEST_F(FloatPowerImpl, TenthSquaredIsHundredth)
|
||||
{
|
||||
auto const tenth = makeHost()->floatFromMantExp(1, -1, 0);
|
||||
auto const hundredth = makeHost()->floatFromMantExp(1, -2, 0);
|
||||
ASSERT_TRUE(tenth.has_value() && hundredth.has_value());
|
||||
expectValue(makeHost()->floatPower(slice(*tenth), 2, 0), *hundredth);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
63
src/tests/libxrpl/tx/wasm/host_functions/FloatRoot.cpp
Normal file
63
src/tests/libxrpl/tx/wasm/host_functions/FloatRoot.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/FloatFixture.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct FloatRootImpl : FloatTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(FloatRootImpl, BadModeIsMalformed)
|
||||
{
|
||||
expectError(
|
||||
makeHost()->floatRoot(slice(floats::kOne), 2, -1), HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatRootImpl, MalformedInput)
|
||||
{
|
||||
expectError(makeHost()->floatRoot(Slice{}, 3, 0), HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatRootImpl, NegativeDegreeIsMalformed)
|
||||
{
|
||||
expectError(
|
||||
makeHost()->floatRoot(slice(floats::kOne), -2, 0), HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatRootImpl, RootOfZeroIsZero)
|
||||
{
|
||||
expectValue(makeHost()->floatRoot(slice(floats::kIntZero), 2, 0), floats::kIntZero);
|
||||
}
|
||||
|
||||
TEST_F(FloatRootImpl, FirstRootIsIdentity)
|
||||
{
|
||||
expectValue(makeHost()->floatRoot(slice(floats::kMaxIOU), 1, 0), floats::kMaxIOU);
|
||||
}
|
||||
|
||||
TEST_F(FloatRootImpl, SquareRootOfHundredIsTen)
|
||||
{
|
||||
auto const hundred = makeHost()->floatFromMantExp(100, 0, 0);
|
||||
ASSERT_TRUE(hundred.has_value());
|
||||
expectValue(makeHost()->floatRoot(slice(*hundred), 2, 0), floats::kTen);
|
||||
}
|
||||
|
||||
TEST_F(FloatRootImpl, CubeRootOfThousandIsTen)
|
||||
{
|
||||
auto const thousand = makeHost()->floatFromMantExp(1000, 0, 0);
|
||||
ASSERT_TRUE(thousand.has_value());
|
||||
expectValue(makeHost()->floatRoot(slice(*thousand), 3, 0), floats::kTen);
|
||||
}
|
||||
|
||||
TEST_F(FloatRootImpl, SquareRootOfHundredthIsTenth)
|
||||
{
|
||||
auto const hundredth = makeHost()->floatFromMantExp(1, -2, 0);
|
||||
auto const tenth = makeHost()->floatFromMantExp(1, -1, 0);
|
||||
ASSERT_TRUE(hundredth.has_value() && tenth.has_value());
|
||||
expectValue(makeHost()->floatRoot(slice(*hundredth), 2, 0), *tenth);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
49
src/tests/libxrpl/tx/wasm/host_functions/FloatSubtract.cpp
Normal file
49
src/tests/libxrpl/tx/wasm/host_functions/FloatSubtract.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/FloatFixture.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct FloatSubtractImpl : FloatTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(FloatSubtractImpl, BadModeIsMalformed)
|
||||
{
|
||||
expectError(
|
||||
makeHost()->floatSubtract(slice(floats::kOne), slice(floats::kOne), -1),
|
||||
HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatSubtractImpl, MalformedInput)
|
||||
{
|
||||
expectError(
|
||||
makeHost()->floatSubtract(slice(floats::kOne), Slice{}, 0),
|
||||
HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatSubtractImpl, MinusMaxExpMinusMaxIouIsMinusMaxExp)
|
||||
{
|
||||
expectValue(
|
||||
makeHost()->floatSubtract(slice(floats::kMinusMaxExp), slice(floats::kMaxIOU), 0),
|
||||
floats::kMinusMaxExp);
|
||||
}
|
||||
|
||||
TEST_F(FloatSubtractImpl, MinMinusZeroIsMin)
|
||||
{
|
||||
expectValue(
|
||||
makeHost()->floatSubtract(slice(floats::kIntMin), slice(floats::kIntZero), 0),
|
||||
floats::kIntMin);
|
||||
}
|
||||
|
||||
TEST_F(FloatSubtractImpl, ZeroMinusOneIsMinusOne)
|
||||
{
|
||||
expectValue(
|
||||
makeHost()->floatSubtract(slice(floats::kIntZero), slice(floats::kOne), 0),
|
||||
floats::kMinusOne);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
70
src/tests/libxrpl/tx/wasm/host_functions/FloatToInt.cpp
Normal file
70
src/tests/libxrpl/tx/wasm/host_functions/FloatToInt.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/FloatFixture.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct FloatToIntImpl : FloatTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(FloatToIntImpl, BadModeIsMalformed)
|
||||
{
|
||||
expectError(
|
||||
makeHost()->floatToInt(slice(floats::kOne), -1), HostFunctionError::FloatInputMalformed);
|
||||
expectError(
|
||||
makeHost()->floatToInt(slice(floats::kOne), 4), HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatToIntImpl, MalformedInputs)
|
||||
{
|
||||
expectError(makeHost()->floatToInt(Slice{}, 0), HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatToIntImpl, Zero)
|
||||
{
|
||||
expectValue(makeHost()->floatToInt(slice(floats::kIntZero), 0), std::int64_t{0});
|
||||
}
|
||||
|
||||
TEST_F(FloatToIntImpl, One)
|
||||
{
|
||||
expectValue(makeHost()->floatToInt(slice(floats::kOne), 0), std::int64_t{1});
|
||||
}
|
||||
|
||||
TEST_F(FloatToIntImpl, MinusOne)
|
||||
{
|
||||
expectValue(makeHost()->floatToInt(slice(floats::kMinusOne), 0), std::int64_t{-1});
|
||||
}
|
||||
|
||||
TEST_F(FloatToIntImpl, Max)
|
||||
{
|
||||
expectValue(makeHost()->floatToInt(slice(floats::kIntMax), 0), kMax64);
|
||||
}
|
||||
|
||||
TEST_F(FloatToIntImpl, Min)
|
||||
{
|
||||
// floatIntMin rounds to -(2^63-1), i.e. -kMax64.
|
||||
expectValue(makeHost()->floatToInt(slice(floats::kIntMin), 0), -kMax64);
|
||||
}
|
||||
|
||||
TEST_F(FloatToIntImpl, OverflowsInt64IsComputationError)
|
||||
{
|
||||
expectError(
|
||||
makeHost()->floatToInt(slice(floats::kUintMax), 0),
|
||||
HostFunctionError::FloatComputationError);
|
||||
}
|
||||
|
||||
TEST_F(FloatToIntImpl, PiRoundsByMode)
|
||||
{
|
||||
expectValue(makeHost()->floatToInt(slice(floats::kPi), 0), std::int64_t{3}); // ToNearest
|
||||
expectValue(makeHost()->floatToInt(slice(floats::kPi), 1), std::int64_t{3}); // TowardsZero
|
||||
expectValue(makeHost()->floatToInt(slice(floats::kPi), 2), std::int64_t{3}); // Downward
|
||||
expectValue(makeHost()->floatToInt(slice(floats::kPi), 3), std::int64_t{4}); // Upward
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
80
src/tests/libxrpl/tx/wasm/host_functions/FloatToMantExp.cpp
Normal file
80
src/tests/libxrpl/tx/wasm/host_functions/FloatToMantExp.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#include <xrpl/basics/Number.h>
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/FloatFixture.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct FloatToMantExpImpl : FloatTest
|
||||
{
|
||||
static constexpr std::int32_t kExpMin = std::numeric_limits<std::int32_t>::min();
|
||||
|
||||
static FloatPair
|
||||
pair(std::int64_t mantissa, std::int32_t exponent)
|
||||
{
|
||||
return FloatPair{mantissa, exponent};
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(FloatToMantExpImpl, MalformedInput)
|
||||
{
|
||||
expectError(makeHost()->floatToMantExp(Slice{}), HostFunctionError::FloatInputMalformed);
|
||||
}
|
||||
|
||||
TEST_F(FloatToMantExpImpl, Zero)
|
||||
{
|
||||
expectValue(makeHost()->floatToMantExp(slice(floats::kIntZero)), pair(0, kExpMin));
|
||||
}
|
||||
|
||||
TEST_F(FloatToMantExpImpl, One)
|
||||
{
|
||||
expectValue(
|
||||
makeHost()->floatToMantExp(slice(floats::kOne)),
|
||||
pair(1'000'000'000'000'000'000, -floats::kNormalExp));
|
||||
}
|
||||
|
||||
TEST_F(FloatToMantExpImpl, MinusOne)
|
||||
{
|
||||
expectValue(
|
||||
makeHost()->floatToMantExp(slice(floats::kMinusOne)),
|
||||
pair(-1'000'000'000'000'000'000, -floats::kNormalExp));
|
||||
}
|
||||
|
||||
TEST_F(FloatToMantExpImpl, Ten)
|
||||
{
|
||||
expectValue(
|
||||
makeHost()->floatToMantExp(slice(floats::kTen)),
|
||||
pair(1'000'000'000'000'000'000, -floats::kNormalExp + 1));
|
||||
}
|
||||
|
||||
TEST_F(FloatToMantExpImpl, Pi)
|
||||
{
|
||||
expectValue(
|
||||
makeHost()->floatToMantExp(slice(floats::kPi)),
|
||||
pair(3'141'592'653'589'793'000, -floats::kNormalExp));
|
||||
}
|
||||
|
||||
TEST_F(FloatToMantExpImpl, IntMax)
|
||||
{
|
||||
expectValue(makeHost()->floatToMantExp(slice(floats::kIntMax)), pair(kMax64, 0));
|
||||
}
|
||||
|
||||
TEST_F(FloatToMantExpImpl, IntMin)
|
||||
{
|
||||
expectValue(makeHost()->floatToMantExp(slice(floats::kIntMin)), pair(-kMax64, 0));
|
||||
}
|
||||
|
||||
TEST_F(FloatToMantExpImpl, Max)
|
||||
{
|
||||
expectValue(
|
||||
makeHost()->floatToMantExp(slice(floats::kMax)),
|
||||
pair(Number::kMaxRep, Number::kMaxExponent));
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
54
src/tests/libxrpl/tx/wasm/host_functions/GetNFT.cpp
Normal file
54
src/tests/libxrpl/tx/wasm/host_functions/GetNFT.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <tx/wasm/NFTFixture.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct GetNFTImpl : NFTTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(GetNFTImpl, UnsetAccountIsInvalidAccount)
|
||||
{
|
||||
auto const issuer = Account{"issuer"};
|
||||
expectError(
|
||||
makeHost()->getNFT(AccountID{}, makeNftId(issuer.id())), HostFunctionError::InvalidAccount);
|
||||
}
|
||||
|
||||
TEST_F(GetNFTImpl, ZeroIdIsInvalidParams)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
expectError(makeHost()->getNFT(owner.id(), uint256{}), HostFunctionError::InvalidParams);
|
||||
}
|
||||
|
||||
TEST_F(GetNFTImpl, MissingTokenIsNotFound)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
expectError(
|
||||
makeHost()->getNFT(owner.id(), makeNftId(owner.id())),
|
||||
HostFunctionError::LedgerObjNotFound);
|
||||
}
|
||||
|
||||
TEST_F(GetNFTImpl, ReturnsUri)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto const uri = std::string_view{"https://example.com/nft"};
|
||||
auto const id = mintNFT(owner, uri);
|
||||
expectValue(makeHost()->getNFT(owner.id(), id), toBytes(uri));
|
||||
}
|
||||
|
||||
TEST_F(GetNFTImpl, WithoutUriFieldNotFound)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto const id = mintNFT(owner);
|
||||
expectError(makeHost()->getNFT(owner.id(), id), HostFunctionError::FieldNotFound);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <string_view>
|
||||
|
||||
namespace xrpl::test {
|
||||
@@ -17,34 +16,30 @@ TEST_F(IsAmendmentEnabledImpl, EnabledAmendmentByIdReadsOne)
|
||||
{
|
||||
auto const id = getRegisteredFeature("TokenEscrow");
|
||||
ASSERT_TRUE(id.has_value());
|
||||
auto const result = host().isAmendmentEnabled(id.value_or(uint256{}));
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, 1);
|
||||
auto const result = makeHost()->isAmendmentEnabled(id.value_or(uint256{}));
|
||||
expectValue(result, 1);
|
||||
}
|
||||
|
||||
TEST_F(IsAmendmentEnabledImpl, EnabledAmendmentByNameReadsOne)
|
||||
{
|
||||
auto const result = host().isAmendmentEnabled(std::string_view{"TokenEscrow"});
|
||||
auto const result = makeHost()->isAmendmentEnabled(std::string_view{"TokenEscrow"});
|
||||
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, 1);
|
||||
expectValue(result, 1);
|
||||
}
|
||||
|
||||
TEST_F(IsAmendmentEnabledImpl, UnknownAmendmentByIdReadsZero)
|
||||
{
|
||||
auto const result = host().isAmendmentEnabled(
|
||||
auto const result = makeHost()->isAmendmentEnabled(
|
||||
uint256{"DEADBEEF00000000000000000000000000000000000000000000000000000000"});
|
||||
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, 0);
|
||||
expectValue(result, 0);
|
||||
}
|
||||
|
||||
TEST_F(IsAmendmentEnabledImpl, UnknownAmendmentNameReadsZero)
|
||||
{
|
||||
auto const result = host().isAmendmentEnabled(std::string_view{"DEADBEEF"});
|
||||
auto const result = makeHost()->isAmendmentEnabled(std::string_view{"DEADBEEF"});
|
||||
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, 0);
|
||||
expectValue(result, 0);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct LedgerObjArrayLenImpl : WasmImplTest
|
||||
{
|
||||
using WasmImplTest::makeHost;
|
||||
|
||||
WasmHost
|
||||
makeHost(Account const& acct)
|
||||
{
|
||||
makeSignerList(acct, 2, {{Account{"alice"}, 1}, {Account{"becky"}, 1}});
|
||||
auto assembler = bareTx();
|
||||
auto h = makeHost(keylet::account(AccountID{}), assembler.type, std::move(assembler.build));
|
||||
h->cacheLedgerObj(keylet::signerList(acct.id()).key, 1);
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(LedgerObjArrayLenImpl, SignerEntriesLength)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectValue(h->getLedgerObjArrayLen(1, sfSignerEntries), 2);
|
||||
}
|
||||
|
||||
TEST_F(LedgerObjArrayLenImpl, NonArrayFieldNoArray)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectError(h->getLedgerObjArrayLen(1, sfAccount), HostFunctionError::NoArray);
|
||||
}
|
||||
|
||||
TEST_F(LedgerObjArrayLenImpl, MissingArrayFieldNotFound)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectError(h->getLedgerObjArrayLen(1, sfMemos), HostFunctionError::FieldNotFound);
|
||||
}
|
||||
|
||||
TEST_F(LedgerObjArrayLenImpl, SlotErrors)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectError(h->getLedgerObjArrayLen(0, sfSignerEntries), HostFunctionError::SlotOutRange);
|
||||
expectError(h->getLedgerObjArrayLen(257, sfSignerEntries), HostFunctionError::SlotOutRange);
|
||||
expectError(h->getLedgerObjArrayLen(2, sfSignerEntries), HostFunctionError::EmptySlot);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
80
src/tests/libxrpl/tx/wasm/host_functions/LedgerObjField.cpp
Normal file
80
src/tests/libxrpl/tx/wasm/host_functions/LedgerObjField.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct LedgerObjFieldImpl : WasmImplTest
|
||||
{
|
||||
template <typename Functor>
|
||||
void
|
||||
checkCachedField(
|
||||
Account const& acct,
|
||||
std::uint32_t index,
|
||||
SField const& field,
|
||||
TxAssembler assembler,
|
||||
Functor&& f)
|
||||
{
|
||||
auto const accountKeylet = keylet::account(acct.id());
|
||||
auto h = makeHost(accountKeylet, assembler.type, std::move(assembler.build));
|
||||
h->cacheLedgerObj(accountKeylet.key, 1);
|
||||
expectValue(h->getLedgerObjField(index, field), f());
|
||||
}
|
||||
|
||||
void
|
||||
checkCachedFieldError(
|
||||
Account const& acct,
|
||||
std::uint32_t index,
|
||||
SField const& field,
|
||||
TxAssembler assembler,
|
||||
HostFunctionError error)
|
||||
{
|
||||
auto const accountKeylet = keylet::account(acct.id());
|
||||
auto h = makeHost(accountKeylet, assembler.type, std::move(assembler.build));
|
||||
h->cacheLedgerObj(accountKeylet.key, 1);
|
||||
expectError(h->getLedgerObjField(index, field), error);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(LedgerObjFieldImpl, MatchesAccount)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
checkCachedField(owner, 1, sfAccount, bareTx(), [&] { return toBytes(owner.id()); });
|
||||
}
|
||||
|
||||
TEST_F(LedgerObjFieldImpl, MatchesBalance)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto const root = ledger.getOpenLedger().read(keylet::account(owner.id()));
|
||||
checkCachedField(
|
||||
owner, 1, sfBalance, bareTx(), [&] { return toBytes(root->getFieldAmount(sfBalance)); });
|
||||
}
|
||||
|
||||
TEST_F(LedgerObjFieldImpl, MatchesAccountSlotOutOfRange)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
checkCachedFieldError(owner, 0, sfAccount, bareTx(), HostFunctionError::SlotOutRange);
|
||||
checkCachedFieldError(owner, 257, sfAccount, bareTx(), HostFunctionError::SlotOutRange);
|
||||
}
|
||||
|
||||
TEST_F(LedgerObjFieldImpl, MatchesAccountEmptySlot)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
checkCachedFieldError(owner, 2, sfAccount, bareTx(), HostFunctionError::EmptySlot);
|
||||
}
|
||||
|
||||
TEST_F(LedgerObjFieldImpl, MatchesOwnerFieldNotFound)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
checkCachedFieldError(owner, 1, sfOwner, bareTx(), HostFunctionError::FieldNotFound);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
@@ -0,0 +1,79 @@
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct LedgerObjNestedArrayLenImpl : WasmImplTest
|
||||
{
|
||||
using WasmImplTest::makeHost;
|
||||
|
||||
WasmHost
|
||||
makeHost(Account const& acct)
|
||||
{
|
||||
makeSignerList(acct, 2, {{Account{"alice"}, 1}, {Account{"becky"}, 1}});
|
||||
auto assembler = bareTx();
|
||||
auto h = makeHost(keylet::account(AccountID{}), assembler.type, std::move(assembler.build));
|
||||
h->cacheLedgerObj(keylet::signerList(acct.id()).key, 1);
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(LedgerObjNestedArrayLenImpl, SignerEntriesLength)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectValue(h->getLedgerObjNestedArrayLen(1, FieldLocator{{sfSignerEntries.getCode()}}), 2);
|
||||
}
|
||||
|
||||
TEST_F(LedgerObjNestedArrayLenImpl, NonArrayFieldNoArray)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectError(
|
||||
h->getLedgerObjNestedArrayLen(1, FieldLocator{{sfSignerQuorum.getCode()}}),
|
||||
HostFunctionError::NoArray);
|
||||
}
|
||||
|
||||
TEST_F(LedgerObjNestedArrayLenImpl, MissingFieldNotFound)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectError(
|
||||
h->getLedgerObjNestedArrayLen(1, FieldLocator{{sfSigners.getCode()}}),
|
||||
HostFunctionError::FieldNotFound);
|
||||
}
|
||||
|
||||
TEST_F(LedgerObjNestedArrayLenImpl, SlotErrors)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectError(
|
||||
h->getLedgerObjNestedArrayLen(0, FieldLocator{{sfSignerEntries.getCode()}}),
|
||||
HostFunctionError::SlotOutRange);
|
||||
expectError(
|
||||
h->getLedgerObjNestedArrayLen(257, FieldLocator{{sfSignerEntries.getCode()}}),
|
||||
HostFunctionError::SlotOutRange);
|
||||
expectError(
|
||||
h->getLedgerObjNestedArrayLen(2, FieldLocator{{sfSignerEntries.getCode()}}),
|
||||
HostFunctionError::EmptySlot);
|
||||
}
|
||||
|
||||
TEST_F(LedgerObjNestedArrayLenImpl, NestIntoNonContainerMalformed)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectError(
|
||||
h->getLedgerObjNestedArrayLen(
|
||||
1, FieldLocator{{sfSignerQuorum.getCode(), 0, sfAccount.getCode()}}),
|
||||
HostFunctionError::LocatorMalformed);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
@@ -0,0 +1,155 @@
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STArray.h>
|
||||
#include <xrpl/protocol/STObject.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct LedgerObjNestedFieldImpl : WasmImplTest
|
||||
{
|
||||
using WasmImplTest::makeHost;
|
||||
|
||||
WasmHost
|
||||
makeHost(Account const& acct)
|
||||
{
|
||||
makeSignerList(acct, 2, {{Account{"alice"}, 1}, {Account{"becky"}, 1}});
|
||||
auto assembler = bareTx();
|
||||
auto h = makeHost(keylet::account(AccountID{}), assembler.type, std::move(assembler.build));
|
||||
h->cacheLedgerObj(keylet::signerList(acct.id()).key, 1);
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(LedgerObjNestedFieldImpl, MatchesNestedSignerAccountsByIndex)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
|
||||
auto const sle = ledger.getOpenLedger().read(keylet::signerList(owner.id()));
|
||||
ASSERT_NE(sle, nullptr);
|
||||
auto const& entries = sle->getFieldArray(sfSignerEntries);
|
||||
|
||||
expectValue(
|
||||
h->getLedgerObjNestedField(
|
||||
1, FieldLocator{{sfSignerEntries.getCode(), 0, sfAccount.getCode()}}),
|
||||
toBytes(entries[0].getAccountID(sfAccount)));
|
||||
expectValue(
|
||||
h->getLedgerObjNestedField(
|
||||
1, FieldLocator{{sfSignerEntries.getCode(), 1, sfAccount.getCode()}}),
|
||||
toBytes(entries[1].getAccountID(sfAccount)));
|
||||
EXPECT_NE(entries[0].getAccountID(sfAccount), entries[1].getAccountID(sfAccount));
|
||||
}
|
||||
|
||||
TEST_F(LedgerObjNestedFieldImpl, MatchesNestedSignerWeight)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectValue(
|
||||
h->getLedgerObjNestedField(
|
||||
1, FieldLocator{{sfSignerEntries.getCode(), 0, sfSignerWeight.getCode()}}),
|
||||
toBytes(static_cast<std::uint16_t>(1)));
|
||||
}
|
||||
|
||||
TEST_F(LedgerObjNestedFieldImpl, MatchesBaseSignerQuorum)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectValue(
|
||||
h->getLedgerObjNestedField(1, FieldLocator{{sfSignerQuorum.getCode()}}),
|
||||
toBytes(static_cast<std::uint32_t>(2)));
|
||||
}
|
||||
|
||||
TEST_F(LedgerObjNestedFieldImpl, MissingFieldNotFound)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
auto const err = HostFunctionError::FieldNotFound;
|
||||
|
||||
expectError(
|
||||
h->getLedgerObjNestedField(1, FieldLocator{{sfSigners.getCode(), 0, sfAccount.getCode()}}),
|
||||
err);
|
||||
expectError(
|
||||
h->getLedgerObjNestedField(
|
||||
1, FieldLocator{{sfSignerEntries.getCode(), 0, sfDestination.getCode()}}),
|
||||
err);
|
||||
}
|
||||
|
||||
TEST_F(LedgerObjNestedFieldImpl, IndexOutOfBounds)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
auto const err = HostFunctionError::IndexOutOfBounds;
|
||||
|
||||
expectError(
|
||||
h->getLedgerObjNestedField(
|
||||
1, FieldLocator{{sfSignerEntries.getCode(), 2, sfAccount.getCode()}}),
|
||||
err);
|
||||
expectError(
|
||||
h->getLedgerObjNestedField(
|
||||
1, FieldLocator{{sfSignerEntries.getCode(), -1, sfAccount.getCode()}}),
|
||||
err);
|
||||
}
|
||||
|
||||
TEST_F(LedgerObjNestedFieldImpl, UnknownFieldCodeInvalidField)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
auto const err = HostFunctionError::InvalidField;
|
||||
|
||||
expectError(
|
||||
h->getLedgerObjNestedField(
|
||||
1, FieldLocator{{fieldCode(99999, 99999), 0, sfAccount.getCode()}}),
|
||||
err);
|
||||
expectError(
|
||||
h->getLedgerObjNestedField(
|
||||
1, FieldLocator{{sfSignerEntries.getCode(), 0, fieldCode(99999, 99999)}}),
|
||||
err);
|
||||
}
|
||||
|
||||
TEST_F(LedgerObjNestedFieldImpl, SlotErrors)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
|
||||
// 0 and 257 are outside the 1..256 slot range.
|
||||
expectError(
|
||||
h->getLedgerObjNestedField(0, FieldLocator{{sfSignerQuorum.getCode()}}),
|
||||
HostFunctionError::SlotOutRange);
|
||||
expectError(
|
||||
h->getLedgerObjNestedField(257, FieldLocator{{sfSignerQuorum.getCode()}}),
|
||||
HostFunctionError::SlotOutRange);
|
||||
// Slot 2 is in range but nothing was cached there.
|
||||
expectError(
|
||||
h->getLedgerObjNestedField(2, FieldLocator{{sfSignerQuorum.getCode()}}),
|
||||
HostFunctionError::EmptySlot);
|
||||
}
|
||||
|
||||
TEST_F(LedgerObjNestedFieldImpl, ContainerWithoutIndexNotLeaf)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectError(
|
||||
h->getLedgerObjNestedField(1, FieldLocator{{sfSignerEntries.getCode()}}),
|
||||
HostFunctionError::NotLeafField);
|
||||
}
|
||||
|
||||
TEST_F(LedgerObjNestedFieldImpl, NestIntoNonContainerMalformed)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectError(
|
||||
h->getLedgerObjNestedField(
|
||||
1, FieldLocator{{sfSignerQuorum.getCode(), 0, sfAccount.getCode()}}),
|
||||
HostFunctionError::LocatorMalformed);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
@@ -1,8 +1,6 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct LedgerSqnImpl : WasmImplTest
|
||||
@@ -11,9 +9,7 @@ struct LedgerSqnImpl : WasmImplTest
|
||||
|
||||
TEST_F(LedgerSqnImpl, MatchesLedger)
|
||||
{
|
||||
auto const result = host().getLedgerSqn();
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, ledger.getOpenLedger().header().seq);
|
||||
expectValue(makeHost()->getLedgerSqn(), ledger.getOpenLedger().header().seq);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -4,12 +4,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct MptokenIssuanceKeyletImpl : WasmImplTest
|
||||
@@ -18,21 +14,17 @@ struct MptokenIssuanceKeyletImpl : WasmImplTest
|
||||
|
||||
TEST_F(MptokenIssuanceKeyletImpl, MatchesMptokenIssuanceKeyletFunction)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto const expected = keylet::mptokenIssuance(makeMptID(1u, owner.id()));
|
||||
auto const expectedBytes = Bytes{std::begin(expected.key), std::end(expected.key)};
|
||||
auto const result = host().mptokenIssuanceKeylet(owner.id(), 1u);
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, expectedBytes);
|
||||
expectKeyletMatches(
|
||||
makeHost()->mptokenIssuanceKeylet(owner.id(), 1u),
|
||||
keylet::mptokenIssuance(makeMptID(1u, owner.id())));
|
||||
}
|
||||
|
||||
TEST_F(MptokenIssuanceKeyletImpl, InvalidAccount)
|
||||
{
|
||||
auto result = host().mptokenIssuanceKeylet(AccountID{}, 1u);
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(
|
||||
makeHost()->mptokenIssuanceKeylet(AccountID{}, 1u), HostFunctionError::InvalidAccount);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -4,12 +4,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct MptokenKeyletImpl : WasmImplTest
|
||||
@@ -18,37 +14,27 @@ struct MptokenKeyletImpl : WasmImplTest
|
||||
|
||||
TEST_F(MptokenKeyletImpl, MatchesMptokenKeyletFunction)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const anotherAccount = Account{"account"};
|
||||
ledger.createAccount(anotherAccount, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
auto const anotherAccount = fund("account");
|
||||
|
||||
auto const mpt = makeMptID(1u, owner.id());
|
||||
auto const expected = keylet::mptoken(mpt, anotherAccount.id());
|
||||
auto const expectedBytes = Bytes{std::begin(expected.key), std::end(expected.key)};
|
||||
auto const result = host().mptokenKeylet(mpt, anotherAccount.id());
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, expectedBytes);
|
||||
expectKeyletMatches(
|
||||
makeHost()->mptokenKeylet(mpt, anotherAccount.id()),
|
||||
keylet::mptoken(mpt, anotherAccount.id()));
|
||||
}
|
||||
|
||||
TEST_F(MptokenKeyletImpl, InvalidMpt)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto result = host().mptokenKeylet(MPTID{}, owner.id());
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidParams);
|
||||
auto const owner = fund("owner");
|
||||
expectError(makeHost()->mptokenKeylet(MPTID{}, owner.id()), HostFunctionError::InvalidParams);
|
||||
}
|
||||
|
||||
TEST_F(MptokenKeyletImpl, InvalidAccount)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto const mpt = makeMptID(1u, owner.id());
|
||||
auto result = host().mptokenKeylet(mpt, AccountID{});
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(makeHost()->mptokenKeylet(mpt, AccountID{}), HostFunctionError::InvalidAccount);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/SeqProxy.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct NFTImpl : WasmImplTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(NFTImpl, MatchesVaultFunction)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
|
||||
auto const expected = keylet::vault(owner.id(), SeqProxy::rawSequence(1u));
|
||||
auto const expectedBytes = Bytes{std::begin(expected.key), std::end(expected.key)};
|
||||
auto const result = host().vaultKeylet(owner.id(), 1u);
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, expectedBytes);
|
||||
}
|
||||
|
||||
TEST_F(NFTImpl, InvalidAccount)
|
||||
{
|
||||
auto result = host().vaultKeylet(AccountID{}, 1u);
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
26
src/tests/libxrpl/tx/wasm/host_functions/NFTFlags.cpp
Normal file
26
src/tests/libxrpl/tx/wasm/host_functions/NFTFlags.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <tx/wasm/NFTFixture.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct NFTFlagsImpl : NFTTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(NFTFlagsImpl, FlagsDecodeFromId)
|
||||
{
|
||||
auto const issuer = Account{"issuer"};
|
||||
expectValue(makeHost()->getNFTFlags(makeNftId(issuer.id())), std::int32_t{kFlags});
|
||||
}
|
||||
|
||||
TEST_F(NFTFlagsImpl, FlagsShouldBeZeroWithZeroNftId)
|
||||
{
|
||||
expectValue(makeHost()->getNFTFlags(uint256{}), std::int32_t{});
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
28
src/tests/libxrpl/tx/wasm/host_functions/NFTIssuer.cpp
Normal file
28
src/tests/libxrpl/tx/wasm/host_functions/NFTIssuer.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <tx/wasm/NFTFixture.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct NFTIssuerImpl : NFTTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(NFTIssuerImpl, IssuerDecodesFromId)
|
||||
{
|
||||
auto const issuer = Account{"issuer"};
|
||||
expectValue(makeHost()->getNFTIssuer(makeNftId(issuer.id())), toBytes(issuer.id()));
|
||||
}
|
||||
|
||||
TEST_F(NFTIssuerImpl, IssuerZeroIsInvalidParams)
|
||||
{
|
||||
expectError(makeHost()->getNFTIssuer(makeNftId(AccountID{})), HostFunctionError::InvalidParams);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
26
src/tests/libxrpl/tx/wasm/host_functions/NFTSequence.cpp
Normal file
26
src/tests/libxrpl/tx/wasm/host_functions/NFTSequence.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <tx/wasm/NFTFixture.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct NFTSequenceImpl : NFTTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(NFTSequenceImpl, SequenceDecodesFromId)
|
||||
{
|
||||
auto const issuer = Account{"issuer"};
|
||||
expectValue(makeHost()->getNFTSequence(makeNftId(issuer.id())), kSequence);
|
||||
}
|
||||
|
||||
TEST_F(NFTSequenceImpl, SequenceShouldBeZeroWithZeroNftId)
|
||||
{
|
||||
expectValue(makeHost()->getNFTSequence(uint256{}), std::int32_t{});
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
19
src/tests/libxrpl/tx/wasm/host_functions/NFTTaxon.cpp
Normal file
19
src/tests/libxrpl/tx/wasm/host_functions/NFTTaxon.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <tx/wasm/NFTFixture.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct NFTTaxonImpl : NFTTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(NFTTaxonImpl, TaxonDecodesFromId)
|
||||
{
|
||||
auto const issuer = Account{"issuer"};
|
||||
expectValue(makeHost()->getNFTTaxon(makeNftId(issuer.id())), kTaxon);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
26
src/tests/libxrpl/tx/wasm/host_functions/NFTTransferFee.cpp
Normal file
26
src/tests/libxrpl/tx/wasm/host_functions/NFTTransferFee.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <tx/wasm/NFTFixture.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct NFTTransferFeeImpl : NFTTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(NFTTransferFeeImpl, TransferFeeDecodesFromId)
|
||||
{
|
||||
auto const issuer = Account{"issuer"};
|
||||
expectValue(makeHost()->getNFTTransferFee(makeNftId(issuer.id())), std::int32_t{kFee});
|
||||
}
|
||||
|
||||
TEST_F(NFTTransferFeeImpl, TransferFeeShouldBeZeroWithZeroNftId)
|
||||
{
|
||||
expectValue(makeHost()->getNFTTransferFee(uint256{}), std::int32_t{});
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
@@ -5,12 +5,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct NftokenOfferKeyletImpl : WasmImplTest
|
||||
@@ -19,21 +15,16 @@ struct NftokenOfferKeyletImpl : WasmImplTest
|
||||
|
||||
TEST_F(NftokenOfferKeyletImpl, MatchesNftokenOfferFunction)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto const expected = keylet::nftokenOffer(owner.id(), SeqProxy::rawSequence(1u));
|
||||
auto const expectedBytes = Bytes{std::begin(expected.key), std::end(expected.key)};
|
||||
auto const result = host().nftokenOfferKeylet(owner.id(), 1u);
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, expectedBytes);
|
||||
expectKeyletMatches(
|
||||
makeHost()->nftokenOfferKeylet(owner.id(), 1u),
|
||||
keylet::nftokenOffer(owner.id(), SeqProxy::rawSequence(1u)));
|
||||
}
|
||||
|
||||
TEST_F(NftokenOfferKeyletImpl, InvalidAccount)
|
||||
{
|
||||
auto result = host().nftokenOfferKeylet(AccountID{}, 1u);
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(makeHost()->nftokenOfferKeylet(AccountID{}, 1u), HostFunctionError::InvalidAccount);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -5,12 +5,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct OfferKeyletImpl : WasmImplTest
|
||||
@@ -19,21 +15,16 @@ struct OfferKeyletImpl : WasmImplTest
|
||||
|
||||
TEST_F(OfferKeyletImpl, MatchesOfferFunction)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto const expected = keylet::offer(owner.id(), SeqProxy::rawSequence(1u));
|
||||
auto const expectedBytes = Bytes{std::begin(expected.key), std::end(expected.key)};
|
||||
auto const result = host().offerKeylet(owner.id(), 1u);
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, expectedBytes);
|
||||
expectKeyletMatches(
|
||||
makeHost()->offerKeylet(owner.id(), 1u),
|
||||
keylet::offer(owner.id(), SeqProxy::rawSequence(1u)));
|
||||
}
|
||||
|
||||
TEST_F(OfferKeyletImpl, InvalidAccount)
|
||||
{
|
||||
auto result = host().offerKeylet(AccountID{}, 1u);
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(makeHost()->offerKeylet(AccountID{}, 1u), HostFunctionError::InvalidAccount);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -4,12 +4,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct OracleKeyletImpl : WasmImplTest
|
||||
@@ -18,21 +14,14 @@ struct OracleKeyletImpl : WasmImplTest
|
||||
|
||||
TEST_F(OracleKeyletImpl, MatchesOracleFunction)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto const expected = keylet::oracle(owner.id(), 1u);
|
||||
auto const expectedBytes = Bytes{std::begin(expected.key), std::end(expected.key)};
|
||||
auto const result = host().oracleKeylet(owner.id(), 1u);
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, expectedBytes);
|
||||
expectKeyletMatches(makeHost()->oracleKeylet(owner.id(), 1u), keylet::oracle(owner.id(), 1u));
|
||||
}
|
||||
|
||||
TEST_F(OracleKeyletImpl, InvalidAccount)
|
||||
{
|
||||
auto result = host().oracleKeylet(AccountID{}, 1u);
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(makeHost()->oracleKeylet(AccountID{}, 1u), HostFunctionError::InvalidAccount);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct ParentLedgerHashImpl : WasmImplTest
|
||||
@@ -11,9 +9,7 @@ struct ParentLedgerHashImpl : WasmImplTest
|
||||
|
||||
TEST_F(ParentLedgerHashImpl, MatchesLedger)
|
||||
{
|
||||
auto const result = host().getParentLedgerHash();
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, ledger.getOpenLedger().header().parentHash);
|
||||
expectValue(makeHost()->getParentLedgerHash(), ledger.getOpenLedger().header().parentHash);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct ParentLedgerTimeImpl : WasmImplTest
|
||||
@@ -11,9 +9,9 @@ struct ParentLedgerTimeImpl : WasmImplTest
|
||||
|
||||
TEST_F(ParentLedgerTimeImpl, MatchesLedger)
|
||||
{
|
||||
auto const result = host().getParentLedgerTime();
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, ledger.getOpenLedger().parentCloseTime().time_since_epoch().count());
|
||||
expectValue(
|
||||
makeHost()->getParentLedgerTime(),
|
||||
ledger.getOpenLedger().parentCloseTime().time_since_epoch().count());
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -5,12 +5,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct PaychannelKeyletImpl : WasmImplTest
|
||||
@@ -19,41 +15,33 @@ struct PaychannelKeyletImpl : WasmImplTest
|
||||
|
||||
TEST_F(PaychannelKeyletImpl, MatchesPaychannelFunction)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const destination = Account{"destination"};
|
||||
ledger.createAccount(destination, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
auto const destination = fund("destination");
|
||||
|
||||
auto const expected =
|
||||
keylet::payChannel(owner.id(), destination.id(), SeqProxy::rawSequence(1u));
|
||||
auto const expectedBytes = Bytes{std::begin(expected.key), std::end(expected.key)};
|
||||
auto const result = host().paychannelKeylet(owner.id(), destination.id(), 1u);
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, expectedBytes);
|
||||
expectKeyletMatches(
|
||||
makeHost()->paychannelKeylet(owner.id(), destination.id(), 1u),
|
||||
keylet::payChannel(owner.id(), destination.id(), SeqProxy::rawSequence(1u)));
|
||||
}
|
||||
|
||||
TEST_F(PaychannelKeyletImpl, CantUseSelf)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto result = host().paychannelKeylet(owner.id(), owner.id(), 1u);
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidParams);
|
||||
expectError(
|
||||
makeHost()->paychannelKeylet(owner.id(), owner.id(), 1u), HostFunctionError::InvalidParams);
|
||||
}
|
||||
|
||||
TEST_F(PaychannelKeyletImpl, InvalidAccount)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto result = host().paychannelKeylet(AccountID{}, owner.id(), 1u);
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(
|
||||
makeHost()->paychannelKeylet(AccountID{}, owner.id(), 1u),
|
||||
HostFunctionError::InvalidAccount);
|
||||
|
||||
result = host().paychannelKeylet(owner.id(), AccountID{}, 1u);
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(
|
||||
makeHost()->paychannelKeylet(owner.id(), AccountID{}, 1u),
|
||||
HostFunctionError::InvalidAccount);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -5,12 +5,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct PermissionedDomainKeyletImpl : WasmImplTest
|
||||
@@ -19,21 +15,17 @@ struct PermissionedDomainKeyletImpl : WasmImplTest
|
||||
|
||||
TEST_F(PermissionedDomainKeyletImpl, MatchesPermissionedDomainFunction)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto const expected = keylet::permissionedDomain(owner.id(), SeqProxy::rawSequence(1u));
|
||||
auto const expectedBytes = Bytes{std::begin(expected.key), std::end(expected.key)};
|
||||
auto const result = host().permissionedDomainKeylet(owner.id(), 1u);
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, expectedBytes);
|
||||
expectKeyletMatches(
|
||||
makeHost()->permissionedDomainKeylet(owner.id(), 1u),
|
||||
keylet::permissionedDomain(owner.id(), SeqProxy::rawSequence(1u)));
|
||||
}
|
||||
|
||||
TEST_F(PermissionedDomainKeyletImpl, InvalidAccount)
|
||||
{
|
||||
auto result = host().permissionedDomainKeylet(AccountID{}, 1u);
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(
|
||||
makeHost()->permissionedDomainKeylet(AccountID{}, 1u), HostFunctionError::InvalidAccount);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
21
src/tests/libxrpl/tx/wasm/host_functions/Sha512Half.cpp
Normal file
21
src/tests/libxrpl/tx/wasm/host_functions/Sha512Half.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <xrpl/protocol/digest.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct Sha512HalfImpl : WasmImplTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(Sha512HalfImpl, LogsMessageAndData)
|
||||
{
|
||||
static constexpr auto data = std::string_view{"hello world"};
|
||||
auto const result = makeHost()->computeSha512HalfHash({data.data(), data.size()});
|
||||
expectValue(result, sha512Half(Slice{data.data(), data.size()}));
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
@@ -4,12 +4,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct SignerListKeyletImpl : WasmImplTest
|
||||
@@ -18,21 +14,14 @@ struct SignerListKeyletImpl : WasmImplTest
|
||||
|
||||
TEST_F(SignerListKeyletImpl, MatchesSignerListFunction)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto const expected = keylet::signerList(owner.id());
|
||||
auto const expectedBytes = Bytes{std::begin(expected.key), std::end(expected.key)};
|
||||
auto const result = host().signerListKeylet(owner.id());
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, expectedBytes);
|
||||
expectKeyletMatches(makeHost()->signerListKeylet(owner.id()), keylet::signerList(owner.id()));
|
||||
}
|
||||
|
||||
TEST_F(SignerListKeyletImpl, InvalidAccount)
|
||||
{
|
||||
auto result = host().signerListKeylet(AccountID{});
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(makeHost()->signerListKeylet(AccountID{}), HostFunctionError::InvalidAccount);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -5,12 +5,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct TicketKeyletImpl : WasmImplTest
|
||||
@@ -19,21 +15,16 @@ struct TicketKeyletImpl : WasmImplTest
|
||||
|
||||
TEST_F(TicketKeyletImpl, MatchesTicketFunction)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto const expected = keylet::ticket(owner.id(), SeqProxy::rawTicket(1u));
|
||||
auto const expectedBytes = Bytes{std::begin(expected.key), std::end(expected.key)};
|
||||
auto const result = host().ticketKeylet(owner.id(), 1u);
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, expectedBytes);
|
||||
expectKeyletMatches(
|
||||
makeHost()->ticketKeylet(owner.id(), 1u),
|
||||
keylet::ticket(owner.id(), SeqProxy::rawTicket(1u)));
|
||||
}
|
||||
|
||||
TEST_F(TicketKeyletImpl, InvalidAccount)
|
||||
{
|
||||
auto result = host().ticketKeylet(AccountID{}, 1u);
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(makeHost()->ticketKeylet(AccountID{}, 1u), HostFunctionError::InvalidAccount);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
30
src/tests/libxrpl/tx/wasm/host_functions/Trace.cpp
Normal file
30
src/tests/libxrpl/tx/wasm/host_functions/Trace.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/CaptureSink.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct TraceImpl : WasmImplTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(TraceImpl, LogsMessageAndData)
|
||||
{
|
||||
auto h = makeTracingHost();
|
||||
h->trace("hello", "world");
|
||||
EXPECT_NE(logged().find("hello world"), std::string::npos) << logged();
|
||||
}
|
||||
|
||||
TEST_F(TraceImpl, NothingLoggedBelowTraceSeverity)
|
||||
{
|
||||
CaptureSink sink{beast::Severity::Error};
|
||||
auto h = makeHost(beast::Journal{sink});
|
||||
h->trace("hello", "world");
|
||||
EXPECT_TRUE(sink.messages().empty()) << sink.messages();
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
@@ -5,12 +5,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct TrustlineKeyletImpl : WasmImplTest
|
||||
@@ -19,58 +15,49 @@ struct TrustlineKeyletImpl : WasmImplTest
|
||||
|
||||
TEST_F(TrustlineKeyletImpl, MatchesTrustlineKeyletFunction)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const destination = Account{"destination"};
|
||||
ledger.createAccount(destination, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
auto const destination = fund("destination");
|
||||
|
||||
auto const usd = toCurrency("USD");
|
||||
|
||||
auto const expected = keylet::trustLine(owner.id(), destination.id(), usd);
|
||||
auto const expectedBytes = Bytes{std::begin(expected.key), std::end(expected.key)};
|
||||
auto const result = host().trustLineKeylet(owner.id(), destination.id(), usd);
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, expectedBytes);
|
||||
expectKeyletMatches(
|
||||
makeHost()->trustLineKeylet(owner.id(), destination.id(), usd),
|
||||
keylet::trustLine(owner.id(), destination.id(), usd));
|
||||
}
|
||||
|
||||
TEST_F(TrustlineKeyletImpl, InvalidCurrency)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const destination = Account{"destination"};
|
||||
ledger.createAccount(destination, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
auto const destination = fund("destination");
|
||||
|
||||
auto const result = host().trustLineKeylet(owner.id(), destination.id(), toCurrency(""));
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidParams);
|
||||
expectError(
|
||||
makeHost()->trustLineKeylet(owner.id(), destination.id(), toCurrency("")),
|
||||
HostFunctionError::InvalidParams);
|
||||
}
|
||||
|
||||
TEST_F(TrustlineKeyletImpl, CantTrustlineToSelf)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto const usd = toCurrency("USD");
|
||||
|
||||
auto const result = host().trustLineKeylet(owner.id(), owner.id(), usd);
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidParams);
|
||||
expectError(
|
||||
makeHost()->trustLineKeylet(owner.id(), owner.id(), usd), HostFunctionError::InvalidParams);
|
||||
}
|
||||
|
||||
TEST_F(TrustlineKeyletImpl, InvalidAccount)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto const usd = toCurrency("USD");
|
||||
|
||||
auto result = host().trustLineKeylet(AccountID{}, owner.id(), usd);
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(
|
||||
makeHost()->trustLineKeylet(AccountID{}, owner.id(), usd),
|
||||
HostFunctionError::InvalidAccount);
|
||||
|
||||
result = host().trustLineKeylet(owner.id(), AccountID{}, usd);
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(
|
||||
makeHost()->trustLineKeylet(owner.id(), AccountID{}, usd),
|
||||
HostFunctionError::InvalidAccount);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
62
src/tests/libxrpl/tx/wasm/host_functions/TxArrayLen.cpp
Normal file
62
src/tests/libxrpl/tx/wasm/host_functions/TxArrayLen.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STArray.h>
|
||||
#include <xrpl/protocol/STObject.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct TxArrayLenImpl : WasmImplTest
|
||||
{
|
||||
using WasmImplTest::makeHost;
|
||||
|
||||
WasmHost
|
||||
makeHost(Account const& acct)
|
||||
{
|
||||
auto assembler = escrowFinishTx(ledger, acct);
|
||||
assembler.build = [inner = std::move(assembler.build)](STObject& obj) {
|
||||
inner(obj);
|
||||
auto memos = STArray{};
|
||||
memos.push_back(makeMemo(toBytes("hello")));
|
||||
memos.push_back(makeMemo(toBytes("world")));
|
||||
obj.setFieldArray(sfMemos, memos);
|
||||
};
|
||||
return makeHost(keylet::account(acct.id()), assembler.type, std::move(assembler.build));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TxArrayLenImpl, MemosLength)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectValue(h->getTxArrayLen(sfMemos), 2);
|
||||
}
|
||||
|
||||
TEST_F(TxArrayLenImpl, CredentialIdsLength)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectValue(h->getTxArrayLen(sfCredentialIDs), 1);
|
||||
}
|
||||
|
||||
TEST_F(TxArrayLenImpl, NonArrayFieldNoArray)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectError(h->getTxArrayLen(sfAccount), HostFunctionError::NoArray);
|
||||
}
|
||||
|
||||
TEST_F(TxArrayLenImpl, MissingArrayFieldNotFound)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectError(h->getTxArrayLen(sfSigners), HostFunctionError::FieldNotFound);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
@@ -1,7 +1,9 @@
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/MPTIssue.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/SeqProxy.h>
|
||||
#include <xrpl/protocol/TxFormats.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
@@ -10,73 +12,160 @@
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct CacheLedgerObjImpl : WasmImplTest
|
||||
struct TxFieldImpl : WasmImplTest
|
||||
{
|
||||
template <typename Functor>
|
||||
void
|
||||
runMatchesLedger(bool implicit)
|
||||
checkTxField(Account const& acct, SField const& field, TxAssembler assembler, Functor&& f)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto h = makeHost(keylet::account(acct.id()), assembler.type, std::move(assembler.build));
|
||||
expectValue(h->getTxField(field), f());
|
||||
}
|
||||
|
||||
auto& h = host();
|
||||
auto const key = keylet::account(owner.id()).key;
|
||||
|
||||
for (auto i = int32_t{1}; i < 257; ++i)
|
||||
{
|
||||
auto const slot = h.cacheLedgerObj(key, i);
|
||||
ASSERT_TRUE(slot.has_value()) << "cacheLedgerObj should find the created account";
|
||||
EXPECT_EQ(*slot, i);
|
||||
|
||||
auto const account = h.getLedgerObjField(*slot, sfAccount);
|
||||
ASSERT_TRUE(account.has_value());
|
||||
Bytes const ownerBytes{owner.id().begin(), owner.id().end()};
|
||||
EXPECT_EQ(*account, ownerBytes);
|
||||
|
||||
auto const sle = ledger.getOpenLedger().read(keylet::account(owner.id()));
|
||||
ASSERT_NE(sle, nullptr);
|
||||
auto const& ledgerAccount = sle->getAccountID(sfAccount);
|
||||
EXPECT_EQ(*account, (Bytes{ledgerAccount.begin(), ledgerAccount.end()}));
|
||||
}
|
||||
|
||||
// Every slot is now occupied, so asking to auto-allocate (cacheIdx == 0) has nowhere
|
||||
// to put the object.
|
||||
auto const result = h.cacheLedgerObj(key, 0);
|
||||
ASSERT_FALSE(result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::SlotsFull);
|
||||
void
|
||||
checkTxFieldError(
|
||||
Account const& acct,
|
||||
SField const& field,
|
||||
TxAssembler assembler,
|
||||
HostFunctionError error)
|
||||
{
|
||||
auto h = makeHost(keylet::account(acct.id()), assembler.type, std::move(assembler.build));
|
||||
expectError(h->getTxField(field), error);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(CacheLedgerObjImpl, MatchesLedgerExplicitIndices)
|
||||
TEST_F(TxFieldImpl, MPTokenIssuanceCreateTxMatchesScale)
|
||||
{
|
||||
runMatchesLedger(false);
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const expectedScale = std::uint8_t{8};
|
||||
checkTxField(owner, sfAssetScale, mptIssuanceCreateTx(owner, expectedScale), [&] {
|
||||
return toBytes(expectedScale);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(CacheLedgerObjImpl, MatchesLedgerImplicitIndices)
|
||||
TEST_F(TxFieldImpl, AmmDepositTxUSDMatchesAsset)
|
||||
{
|
||||
runMatchesLedger(true);
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto usdIssue = Issue{toCurrency("USD"), owner.id()};
|
||||
checkTxField(
|
||||
owner, sfAsset, ammDepositTx(owner, xrpIssue(), usdIssue), [&] { return Bytes(20, 0); });
|
||||
}
|
||||
|
||||
TEST_F(CacheLedgerObjImpl, OutOfRange)
|
||||
TEST_F(TxFieldImpl, AmmDepositTxUSDMatchesAsset2)
|
||||
{
|
||||
auto result = host().cacheLedgerObj(uint256{}, -1);
|
||||
ASSERT_FALSE(result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::SlotOutRange);
|
||||
|
||||
result = host().cacheLedgerObj(uint256{}, 257);
|
||||
ASSERT_FALSE(result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::SlotOutRange);
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto usdIssue = Issue{toCurrency("USD"), owner.id()};
|
||||
checkTxField(owner, sfAsset2, ammDepositTx(owner, xrpIssue(), usdIssue), [&] {
|
||||
return toBytes(Asset{usdIssue});
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(CacheLedgerObjImpl, LedgerObjNotFound)
|
||||
TEST_F(TxFieldImpl, AmmDepositTxGBPMatchesAsset)
|
||||
{
|
||||
auto const ghost = keylet::account(Account{"ghost"}.id()).key;
|
||||
auto result = host().cacheLedgerObj(ghost, 0);
|
||||
ASSERT_FALSE(result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::LedgerObjNotFound);
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto gbpIssue = Issue{toCurrency("GBP"), owner.id()};
|
||||
auto mptId = makeMptID(1, owner);
|
||||
auto mptIssue = MPTIssue{mptId};
|
||||
checkTxField(owner, sfAsset, ammDepositTx(owner, gbpIssue, mptIssue), [&] {
|
||||
return toBytes(Asset{gbpIssue});
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(TxFieldImpl, AmmDepositTxGBPMatchesAsset2)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto gbpIssue = Issue{toCurrency("GBP"), owner.id()};
|
||||
auto mptId = makeMptID(1, owner);
|
||||
auto mptIssue = MPTIssue{mptId};
|
||||
checkTxField(owner, sfAsset2, ammDepositTx(owner, gbpIssue, mptIssue), [&] {
|
||||
return toBytes(Asset{mptId});
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(TxFieldImpl, EscrowTxMatchesAccount)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
checkTxField(owner, sfAccount, escrowFinishTx(ledger, owner), [&] {
|
||||
return Bytes{std::begin(owner.id()), std::end(owner.id())};
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(TxFieldImpl, EscrowTxMatchesOwner)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
checkTxField(owner, sfOwner, escrowFinishTx(ledger, owner), [&] {
|
||||
return Bytes{std::begin(owner.id()), std::end(owner.id())};
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(TxFieldImpl, EscrowTxMatchesTransactionType)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
checkTxField(owner, sfTransactionType, escrowFinishTx(ledger, owner), [] {
|
||||
return toBytes(ttESCROW_FINISH);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(TxFieldImpl, EscrowTxMatchesOfferSequence)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
checkTxField(owner, sfOfferSequence, escrowFinishTx(ledger, owner), [&] {
|
||||
return toBytes(ledger.getAccountRoot(owner.id()).getSequence());
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(TxFieldImpl, EscrowTxMatchesDestination)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
checkTxFieldError(
|
||||
owner, sfDestination, escrowFinishTx(ledger, owner), HostFunctionError::FieldNotFound);
|
||||
}
|
||||
|
||||
TEST_F(TxFieldImpl, EscrowTxMatchesMemos)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
checkTxFieldError(
|
||||
owner, sfMemos, escrowFinishTx(ledger, owner), HostFunctionError::NotLeafField);
|
||||
}
|
||||
|
||||
TEST_F(TxFieldImpl, EscrowTxMatchesCredentialIDs)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
checkTxFieldError(
|
||||
owner, sfCredentialIDs, escrowFinishTx(ledger, owner), HostFunctionError::NotLeafField);
|
||||
}
|
||||
|
||||
TEST_F(TxFieldImpl, EscrowTxMatchesInvalid)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
checkTxFieldError(
|
||||
owner, sfInvalid, escrowFinishTx(ledger, owner), HostFunctionError::FieldNotFound);
|
||||
}
|
||||
|
||||
TEST_F(TxFieldImpl, EscrowTxMatchesGeneric)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
checkTxFieldError(
|
||||
owner, sfGeneric, escrowFinishTx(ledger, owner), HostFunctionError::FieldNotFound);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STArray.h>
|
||||
#include <xrpl/protocol/STObject.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct TxNestedArrayLenImpl : WasmImplTest
|
||||
{
|
||||
using WasmImplTest::makeHost;
|
||||
|
||||
WasmHost
|
||||
makeHost(Account const& acct)
|
||||
{
|
||||
auto assembler = escrowFinishTx(ledger, acct);
|
||||
assembler.build = [inner = std::move(assembler.build)](STObject& obj) {
|
||||
inner(obj);
|
||||
auto memos = STArray{};
|
||||
memos.push_back(makeMemo(toBytes("hello")));
|
||||
obj.setFieldArray(sfMemos, memos);
|
||||
};
|
||||
return makeHost(keylet::account(acct.id()), assembler.type, std::move(assembler.build));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TxNestedArrayLenImpl, MemosLength)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectValue(h->getTxNestedArrayLen(FieldLocator{{sfMemos.getCode()}}), 1);
|
||||
}
|
||||
|
||||
TEST_F(TxNestedArrayLenImpl, CredentialIdsLength)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectValue(h->getTxNestedArrayLen(FieldLocator{{sfCredentialIDs.getCode()}}), 1);
|
||||
}
|
||||
|
||||
TEST_F(TxNestedArrayLenImpl, NonArrayFieldNoArray)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectError(
|
||||
h->getTxNestedArrayLen(FieldLocator{{sfAccount.getCode()}}), HostFunctionError::NoArray);
|
||||
}
|
||||
|
||||
TEST_F(TxNestedArrayLenImpl, MissingFieldNotFound)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectError(
|
||||
h->getTxNestedArrayLen(FieldLocator{{sfSigners.getCode()}}),
|
||||
HostFunctionError::FieldNotFound);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
133
src/tests/libxrpl/tx/wasm/host_functions/TxNestedField.cpp
Normal file
133
src/tests/libxrpl/tx/wasm/host_functions/TxNestedField.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STArray.h>
|
||||
#include <xrpl/protocol/STObject.h>
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct TxNestedFieldImpl : WasmImplTest
|
||||
{
|
||||
TxAssembler
|
||||
assemble(Account const& acct)
|
||||
{
|
||||
auto assembler = escrowFinishTx(ledger, acct);
|
||||
assembler.build = [inner = std::move(assembler.build)](STObject& obj) {
|
||||
inner(obj);
|
||||
auto memos = STArray{};
|
||||
auto memo = STObject::makeInnerObject(sfMemo);
|
||||
memo.setFieldVL(sfMemoData, Slice{"hello", 5});
|
||||
memos.push_back(std::move(memo));
|
||||
obj.setFieldArray(sfMemos, memos);
|
||||
};
|
||||
return assembler;
|
||||
}
|
||||
|
||||
using WasmImplTest::makeHost;
|
||||
|
||||
WasmHost
|
||||
makeHost(Account const& acct)
|
||||
{
|
||||
auto assembler = assemble(acct);
|
||||
return makeHost(keylet::account(acct.id()), assembler.type, std::move(assembler.build));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TxNestedFieldImpl, MatchesNestedMemo)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectValue(
|
||||
h->getTxNestedField(FieldLocator{{sfMemos.getCode(), 0, sfMemoData.getCode()}}),
|
||||
toBytes("hello"));
|
||||
}
|
||||
|
||||
TEST_F(TxNestedFieldImpl, MatchesCredId)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectValue(
|
||||
h->getTxNestedField(FieldLocator{{sfCredentialIDs.getCode(), 0}}), toBytes(credentialId()));
|
||||
}
|
||||
|
||||
TEST_F(TxNestedFieldImpl, MatchesBaseFieldViaNestedLocator)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectValue(h->getTxNestedField(FieldLocator{{sfAccount.getCode()}}), toBytes(owner.id()));
|
||||
}
|
||||
|
||||
TEST_F(TxNestedFieldImpl, MissingFieldNotFound)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
auto const err = HostFunctionError::FieldNotFound;
|
||||
|
||||
expectError(
|
||||
h->getTxNestedField(FieldLocator{{sfSigners.getCode(), 0, sfAccount.getCode()}}), err);
|
||||
expectError(h->getTxNestedField(FieldLocator{{sfMemos.getCode(), 0, sfURI.getCode()}}), err);
|
||||
expectError(h->getTxNestedField(FieldLocator{{sfMemos.getCode(), 0, -1}}), err);
|
||||
expectError(h->getTxNestedField(FieldLocator{{-1, 0, sfAccount.getCode()}}), err);
|
||||
expectError(h->getTxNestedField(FieldLocator{{0, 0, sfAccount.getCode()}}), err);
|
||||
}
|
||||
|
||||
TEST_F(TxNestedFieldImpl, IndexOutOfBounds)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
auto const err = HostFunctionError::IndexOutOfBounds;
|
||||
|
||||
expectError(
|
||||
h->getTxNestedField(FieldLocator{{sfMemos.getCode(), 1, sfMemoData.getCode()}}), err);
|
||||
expectError(h->getTxNestedField(FieldLocator{{sfCredentialIDs.getCode(), 1}}), err);
|
||||
expectError(
|
||||
h->getTxNestedField(FieldLocator{{sfMemos.getCode(), -1, sfMemoData.getCode()}}), err);
|
||||
expectError(h->getTxNestedField(FieldLocator{{sfCredentialIDs.getCode(), -1}}), err);
|
||||
}
|
||||
|
||||
TEST_F(TxNestedFieldImpl, UnknownFieldCodeInvalidField)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
auto const err = HostFunctionError::InvalidField;
|
||||
|
||||
expectError(
|
||||
h->getTxNestedField(FieldLocator{{fieldCode(20000, 20000), 0, sfAccount.getCode()}}), err);
|
||||
expectError(
|
||||
h->getTxNestedField(FieldLocator{{sfMemos.getCode(), 0, fieldCode(20000, 20000)}}), err);
|
||||
// Far-negative code: not in the SField map at all.
|
||||
expectError(
|
||||
h->getTxNestedField(
|
||||
FieldLocator{{std::numeric_limits<std::int32_t>::min(), 0, sfAccount.getCode()}}),
|
||||
err);
|
||||
}
|
||||
|
||||
TEST_F(TxNestedFieldImpl, ContainerWithoutIndexNotLeaf)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
auto const err = HostFunctionError::NotLeafField;
|
||||
|
||||
expectError(h->getTxNestedField(FieldLocator{{sfMemos.getCode()}}), err);
|
||||
expectError(h->getTxNestedField(FieldLocator{{sfCredentialIDs.getCode()}}), err);
|
||||
}
|
||||
|
||||
TEST_F(TxNestedFieldImpl, NestIntoNonContainerMalformed)
|
||||
{
|
||||
auto const owner = fund("owner");
|
||||
auto h = makeHost(owner);
|
||||
expectError(
|
||||
h->getTxNestedField(FieldLocator{{sfAccount.getCode(), 0, sfAccount.getCode()}}),
|
||||
HostFunctionError::LocatorMalformed);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
@@ -4,8 +4,6 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct UpdateDataImpl : WasmImplTest
|
||||
@@ -14,22 +12,19 @@ struct UpdateDataImpl : WasmImplTest
|
||||
|
||||
TEST_F(UpdateDataImpl, SmallData)
|
||||
{
|
||||
auto& h = host();
|
||||
auto h = makeHost();
|
||||
auto data = Bytes(10, 0x42);
|
||||
auto result = h.updateData(Slice{data.data(), data.size()});
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, data.size());
|
||||
expectValue(h->updateData(Slice{data.data(), data.size()}), data.size());
|
||||
// TODO: getData() does not seem to be called when the smart escrow finishes.
|
||||
EXPECT_EQ(h.getData(), data);
|
||||
EXPECT_EQ(h->getData(), data);
|
||||
}
|
||||
|
||||
TEST_F(UpdateDataImpl, LargeData)
|
||||
{
|
||||
auto& h = host();
|
||||
auto h = makeHost();
|
||||
auto data = Bytes(kMaxWasmDataLength + 1, 0x42);
|
||||
auto result = h.updateData(Slice{data.data(), data.size()});
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::DataFieldTooLarge);
|
||||
expectError(
|
||||
h->updateData(Slice{data.data(), data.size()}), HostFunctionError::DataFieldTooLarge);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
@@ -5,12 +5,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <helpers/Account.h>
|
||||
#include <helpers/TxTest.h>
|
||||
#include <tx/wasm/RealHostFixture.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
struct VaultKeyletImpl : WasmImplTest
|
||||
@@ -19,21 +15,16 @@ struct VaultKeyletImpl : WasmImplTest
|
||||
|
||||
TEST_F(VaultKeyletImpl, MatchesVaultFunction)
|
||||
{
|
||||
auto const owner = Account{"owner"};
|
||||
ledger.createAccount(owner, XRP(1000));
|
||||
auto const owner = fund("owner");
|
||||
|
||||
auto const expected = keylet::vault(owner.id(), SeqProxy::rawSequence(1u));
|
||||
auto const expectedBytes = Bytes{std::begin(expected.key), std::end(expected.key)};
|
||||
auto const result = host().vaultKeylet(owner.id(), 1u);
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, expectedBytes);
|
||||
expectKeyletMatches(
|
||||
makeHost()->vaultKeylet(owner.id(), 1u),
|
||||
keylet::vault(owner.id(), SeqProxy::rawSequence(1u)));
|
||||
}
|
||||
|
||||
TEST_F(VaultKeyletImpl, InvalidAccount)
|
||||
{
|
||||
auto result = host().vaultKeylet(AccountID{}, 1u);
|
||||
ASSERT_TRUE(!result.has_value());
|
||||
EXPECT_EQ(result.error(), HostFunctionError::InvalidAccount);
|
||||
expectError(makeHost()->vaultKeylet(AccountID{}, 1u), HostFunctionError::InvalidAccount);
|
||||
}
|
||||
|
||||
} // namespace xrpl::test
|
||||
|
||||
Reference in New Issue
Block a user