Skip to content

Commit

Permalink
add rpc tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dangell7 committed Sep 15, 2024
1 parent 60dabed commit 15315f7
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 34 deletions.
117 changes: 117 additions & 0 deletions src/test/rpc/LedgerRPC_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1413,6 +1413,122 @@ class LedgerRPC_test : public beast::unit_test::suite
}
}

void
testLedgerEntrySubscription()
{
testcase("ledger_entry Request Subscription");
using namespace test::jtx;
Env env{*this};
Account const alice{"alice"};
Account const bob{"bob"};
env.fund(XRP(10000), alice, bob);
env.close();

using namespace std::chrono_literals;
env(subscription::create(alice, bob, XRP(10), 100s));
env.close();

std::string const ledgerHash{to_string(env.closed()->info().hash)};
std::string subIndex;
{
// Request the subscription using account, destination and sequence.
Json::Value jvParams;
jvParams[jss::subscription] = Json::objectValue;
jvParams[jss::subscription][jss::account] = alice.human();
jvParams[jss::subscription][jss::destination] = bob.human();
jvParams[jss::subscription][jss::seq] = env.seq(alice) - 1;
Json::Value const jrr = env.rpc(
"json", "ledger_entry", to_string(jvParams))[jss::result];
BEAST_EXPECT(
jrr[jss::node][jss::Amount] == XRP(10).value().getText());
subIndex = jrr[jss::index].asString();
}
{
// Request the subscription by index.
Json::Value jvParams;
jvParams[jss::subscription] = subIndex;
jvParams[jss::ledger_hash] = ledgerHash;
Json::Value const jrr = env.rpc(
"json", "ledger_entry", to_string(jvParams))[jss::result];
BEAST_EXPECT(
jrr[jss::node][jss::Amount] == XRP(10).value().getText());
}
{
// Malformed account entry.
Json::Value jvParams;
jvParams[jss::subscription] = Json::objectValue;

std::string const badAddress = makeBadAddress(alice.human());
jvParams[jss::subscription][jss::account] = badAddress;
jvParams[jss::subscription][jss::destination] = bob.human();
jvParams[jss::subscription][jss::seq] = env.seq(alice) - 1;
jvParams[jss::ledger_hash] = ledgerHash;
Json::Value const jrr = env.rpc(
"json", "ledger_entry", to_string(jvParams))[jss::result];
checkErrorValue(jrr, "malformedAddress", "");
}
{
// Missing account.
Json::Value jvParams;
jvParams[jss::subscription] = Json::objectValue;
jvParams[jss::subscription][jss::destination] = bob.human();
jvParams[jss::subscription][jss::seq] = env.seq(alice) - 1;
jvParams[jss::ledger_hash] = ledgerHash;
Json::Value const jrr = env.rpc(
"json", "ledger_entry", to_string(jvParams))[jss::result];
checkErrorValue(jrr, "malformedRequest", "");
}
{
// Malformed destination entry.
Json::Value jvParams;
jvParams[jss::subscription] = Json::objectValue;

std::string const badAddress = makeBadAddress(alice.human());
jvParams[jss::subscription][jss::account] = alice.human();
jvParams[jss::subscription][jss::destination] = badAddress;
jvParams[jss::subscription][jss::seq] = env.seq(alice) - 1;
jvParams[jss::ledger_hash] = ledgerHash;
Json::Value const jrr = env.rpc(
"json", "ledger_entry", to_string(jvParams))[jss::result];
checkErrorValue(jrr, "malformedAddress", "");
}
{
// Missing destination.
Json::Value jvParams;
jvParams[jss::subscription] = Json::objectValue;
jvParams[jss::subscription][jss::account] = alice.human();
jvParams[jss::subscription][jss::seq] = env.seq(alice) - 1;
jvParams[jss::ledger_hash] = ledgerHash;
Json::Value const jrr = env.rpc(
"json", "ledger_entry", to_string(jvParams))[jss::result];
checkErrorValue(jrr, "malformedRequest", "");
}
{
// Missing sequence.
Json::Value jvParams;
jvParams[jss::subscription] = Json::objectValue;
jvParams[jss::subscription][jss::account] = alice.human();
jvParams[jss::subscription][jss::destination] = bob.human();
jvParams[jss::ledger_hash] = ledgerHash;
Json::Value const jrr = env.rpc(
"json", "ledger_entry", to_string(jvParams))[jss::result];
checkErrorValue(jrr, "malformedRequest", "");
}
{
// Non-integer sequence.
Json::Value jvParams;
jvParams[jss::subscription] = Json::objectValue;
jvParams[jss::subscription][jss::account] = alice.human();
jvParams[jss::subscription][jss::destination] = bob.human();
jvParams[jss::subscription][jss::seq] =
std::to_string(env.seq(alice) - 1);
jvParams[jss::ledger_hash] = ledgerHash;
Json::Value const jrr = env.rpc(
"json", "ledger_entry", to_string(jvParams))[jss::result];
checkErrorValue(jrr, "malformedRequest", "");
}
}

void
testLedgerEntryTicket()
{
Expand Down Expand Up @@ -2380,6 +2496,7 @@ class LedgerRPC_test : public beast::unit_test::suite
testLedgerEntryOffer();
testLedgerEntryPayChan();
testLedgerEntryRippleState();
testLedgerEntrySubscription();
testLedgerEntryTicket();
testLookupLedger();
testNoQueue();
Expand Down
3 changes: 2 additions & 1 deletion src/xrpld/rpc/detail/RPCHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -915,7 +915,7 @@ chooseLedgerEntryType(Json::Value const& params)
std::pair<RPC::Status, LedgerEntryType> result{RPC::Status::OK, ltANY};
if (params.isMember(jss::type))
{
static constexpr std::array<std::pair<char const*, LedgerEntryType>, 22>
static constexpr std::array<std::pair<char const*, LedgerEntryType>, 23>
types{
{{jss::account, ltACCOUNT_ROOT},
{jss::amendments, ltAMENDMENTS},
Expand All @@ -936,6 +936,7 @@ chooseLedgerEntryType(Json::Value const& params)
{jss::payment_channel, ltPAYCHAN},
{jss::signer_list, ltSIGNER_LIST},
{jss::state, ltRIPPLE_STATE},
{jss::subscription, ltSUBSCRIPTION},
{jss::ticket, ltTICKET},
{jss::xchain_owned_claim_id, ltXCHAIN_OWNED_CLAIM_ID},
{jss::xchain_owned_create_account_claim_id,
Expand Down
61 changes: 28 additions & 33 deletions src/xrpld/rpc/handlers/LedgerEntry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -656,39 +656,34 @@ doLedgerEntry(RPC::JsonContext& context)
jvResult[jss::error] = "malformedRequest";
}
}
// else if (
// !context.params[jss::oracle].isMember(
// jss::oracle_document_id) ||
// !context.params[jss::oracle].isMember(jss::account))
// {
// jvResult[jss::error] = "malformedRequest";
// }
// else
// {
// uNodeIndex = beast::zero;
// auto const& oracle = context.params[jss::oracle];
// auto const documentID = [&]() -> std::optional<std::uint32_t>
// {
// auto const& id = oracle[jss::oracle_document_id];
// if (id.isUInt() || (id.isInt() && id.asInt() >= 0))
// return std::make_optional(id.asUInt());
// else if (id.isString())
// {
// std::uint32_t v;
// if (beast::lexicalCastChecked(v, id.asString()))
// return std::make_optional(v);
// }
// return std::nullopt;
// }();
// auto const account =
// parseBase58<AccountID>(oracle[jss::account].asString());
// if (!account || account->isZero())
// jvResult[jss::error] = "malformedAddress";
// else if (!documentID)
// jvResult[jss::error] = "malformedDocumentID";
// else
// uNodeIndex = keylet::oracle(*account, *documentID).key;
// }
else if (
!context.params[jss::subscription].isMember(jss::account) ||
!context.params[jss::subscription].isMember(jss::destination) ||
!context.params[jss::subscription].isMember(jss::seq) ||
!context.params[jss::subscription][jss::seq].isIntegral())
{
jvResult[jss::error] = "malformedRequest";
}
else
{
uNodeIndex = beast::zero;
auto const& subscription = context.params[jss::subscription];
auto const account = parseBase58<AccountID>(
subscription[jss::account].asString());
auto const destination = parseBase58<AccountID>(
subscription[jss::destination].asString());
if (!account || account->isZero())
jvResult[jss::error] = "malformedAddress";
else if (!destination || destination->isZero())
jvResult[jss::error] = "malformedAddress";
else
uNodeIndex = keylet::subscription(
*account,
*destination,
context.params[jss::subscription][jss::seq]
.asUInt())
.key;
}
}
else
{
Expand Down

0 comments on commit 15315f7

Please sign in to comment.