Files
rippled/src/test/app/AccountTxPaging_test.cpp
Ayaz Salikhov 5f638f5553 chore: Set ColumnLimit to 120 in clang-format (#6288)
This change updates the ColumnLimit from 80 to 120, and applies clang-format to reformat the code.
2026-01-28 18:09:50 +00:00

255 lines
8.8 KiB
C++

#include <test/jtx.h>
#include <test/rpc/GRPCTestClientBase.h>
#include <xrpl/beast/unit_test.h>
#include <xrpl/protocol/jss.h>
#include <cstdlib>
namespace xrpl {
class AccountTxPaging_test : public beast::unit_test::suite
{
bool
checkTransaction(Json::Value const& tx, int sequence, int ledger)
{
return (tx[jss::tx][jss::Sequence].asInt() == sequence && tx[jss::tx][jss::ledger_index].asInt() == ledger);
}
auto
next(
test::jtx::Env& env,
test::jtx::Account const& account,
int ledger_min,
int ledger_max,
int limit,
bool forward,
Json::Value const& marker = Json::nullValue)
{
Json::Value jvc;
jvc[jss::account] = account.human();
jvc[jss::ledger_index_min] = ledger_min;
jvc[jss::ledger_index_max] = ledger_max;
jvc[jss::forward] = forward;
jvc[jss::limit] = limit;
if (marker)
jvc[jss::marker] = marker;
return env.rpc("json", "account_tx", to_string(jvc))[jss::result];
}
void
testAccountTxPaging()
{
testcase("Paging for Single Account");
using namespace test::jtx;
Env env(*this);
Account A1{"A1"};
Account A2{"A2"};
Account A3{"A3"};
env.fund(XRP(10000), A1, A2, A3);
env.close();
env.trust(A3["USD"](1000), A1);
env.trust(A2["USD"](1000), A1);
env.trust(A3["USD"](1000), A2);
env.close();
for (auto i = 0; i < 5; ++i)
{
env(pay(A2, A1, A2["USD"](2)));
env(pay(A3, A1, A3["USD"](2)));
env(offer(A1, XRP(11), A1["USD"](1)));
env(offer(A2, XRP(10), A2["USD"](1)));
env(offer(A3, XRP(9), A3["USD"](1)));
env.close();
}
/* The sequence/ledger for A3 are as follows:
* seq ledger_index
* 3 ----> 3
* 1 ----> 3
* 2 ----> 4
* 2 ----> 4
* 2 ----> 5
* 3 ----> 5
* 4 ----> 6
* 5 ----> 6
* 6 ----> 7
* 7 ----> 7
* 8 ----> 8
* 9 ----> 8
* 10 ----> 9
* 11 ----> 9
*/
// page through the results in several ways.
{
// limit = 2, 3 batches giving the first 6 txs
auto jrr = next(env, A3, 2, 5, 2, true);
auto txs = jrr[jss::transactions];
if (!BEAST_EXPECT(txs.isArray() && txs.size() == 2))
return;
BEAST_EXPECT(checkTransaction(txs[0u], 3, 3));
BEAST_EXPECT(checkTransaction(txs[1u], 3, 3));
if (!BEAST_EXPECT(jrr[jss::marker]))
return;
jrr = next(env, A3, 2, 5, 2, true, jrr[jss::marker]);
txs = jrr[jss::transactions];
if (!BEAST_EXPECT(txs.isArray() && txs.size() == 2))
return;
BEAST_EXPECT(checkTransaction(txs[0u], 4, 4));
BEAST_EXPECT(checkTransaction(txs[1u], 4, 4));
if (!BEAST_EXPECT(jrr[jss::marker]))
return;
jrr = next(env, A3, 2, 5, 2, true, jrr[jss::marker]);
txs = jrr[jss::transactions];
if (!BEAST_EXPECT(txs.isArray() && txs.size() == 2))
return;
BEAST_EXPECT(checkTransaction(txs[0u], 4, 5));
BEAST_EXPECT(checkTransaction(txs[1u], 5, 5));
BEAST_EXPECT(!jrr[jss::marker]);
}
{
// limit 1, 3 requests giving the first 3 txs
auto jrr = next(env, A3, 3, 9, 1, true);
auto txs = jrr[jss::transactions];
if (!BEAST_EXPECT(txs.isArray() && txs.size() == 1))
return;
BEAST_EXPECT(checkTransaction(txs[0u], 3, 3));
if (!BEAST_EXPECT(jrr[jss::marker]))
return;
jrr = next(env, A3, 3, 9, 1, true, jrr[jss::marker]);
txs = jrr[jss::transactions];
if (!BEAST_EXPECT(txs.isArray() && txs.size() == 1))
return;
BEAST_EXPECT(checkTransaction(txs[0u], 3, 3));
if (!BEAST_EXPECT(jrr[jss::marker]))
return;
jrr = next(env, A3, 3, 9, 1, true, jrr[jss::marker]);
txs = jrr[jss::transactions];
if (!BEAST_EXPECT(txs.isArray() && txs.size() == 1))
return;
BEAST_EXPECT(checkTransaction(txs[0u], 4, 4));
if (!BEAST_EXPECT(jrr[jss::marker]))
return;
// continue with limit 3, to end of all txs
jrr = next(env, A3, 3, 9, 3, true, jrr[jss::marker]);
txs = jrr[jss::transactions];
if (!BEAST_EXPECT(txs.isArray() && txs.size() == 3))
return;
BEAST_EXPECT(checkTransaction(txs[0u], 4, 4));
BEAST_EXPECT(checkTransaction(txs[1u], 4, 5));
BEAST_EXPECT(checkTransaction(txs[2u], 5, 5));
if (!BEAST_EXPECT(jrr[jss::marker]))
return;
jrr = next(env, A3, 3, 9, 3, true, jrr[jss::marker]);
txs = jrr[jss::transactions];
if (!BEAST_EXPECT(txs.isArray() && txs.size() == 3))
return;
BEAST_EXPECT(checkTransaction(txs[0u], 6, 6));
BEAST_EXPECT(checkTransaction(txs[1u], 7, 6));
BEAST_EXPECT(checkTransaction(txs[2u], 8, 7));
if (!BEAST_EXPECT(jrr[jss::marker]))
return;
jrr = next(env, A3, 3, 9, 3, true, jrr[jss::marker]);
txs = jrr[jss::transactions];
if (!BEAST_EXPECT(txs.isArray() && txs.size() == 3))
return;
BEAST_EXPECT(checkTransaction(txs[0u], 9, 7));
BEAST_EXPECT(checkTransaction(txs[1u], 10, 8));
BEAST_EXPECT(checkTransaction(txs[2u], 11, 8));
if (!BEAST_EXPECT(jrr[jss::marker]))
return;
jrr = next(env, A3, 3, 9, 3, true, jrr[jss::marker]);
txs = jrr[jss::transactions];
if (!BEAST_EXPECT(txs.isArray() && txs.size() == 2))
return;
BEAST_EXPECT(checkTransaction(txs[0u], 12, 9));
BEAST_EXPECT(checkTransaction(txs[1u], 13, 9));
BEAST_EXPECT(!jrr[jss::marker]);
}
{
// limit 2, descending, 2 batches giving last 4 txs
auto jrr = next(env, A3, 3, 9, 2, false);
auto txs = jrr[jss::transactions];
if (!BEAST_EXPECT(txs.isArray() && txs.size() == 2))
return;
BEAST_EXPECT(checkTransaction(txs[0u], 13, 9));
BEAST_EXPECT(checkTransaction(txs[1u], 12, 9));
if (!BEAST_EXPECT(jrr[jss::marker]))
return;
jrr = next(env, A3, 3, 9, 2, false, jrr[jss::marker]);
txs = jrr[jss::transactions];
if (!BEAST_EXPECT(txs.isArray() && txs.size() == 2))
return;
BEAST_EXPECT(checkTransaction(txs[0u], 11, 8));
BEAST_EXPECT(checkTransaction(txs[1u], 10, 8));
if (!BEAST_EXPECT(jrr[jss::marker]))
return;
// continue with limit 3 until all txs have been seen
jrr = next(env, A3, 3, 9, 3, false, jrr[jss::marker]);
txs = jrr[jss::transactions];
if (!BEAST_EXPECT(txs.isArray() && txs.size() == 3))
return;
BEAST_EXPECT(checkTransaction(txs[0u], 9, 7));
BEAST_EXPECT(checkTransaction(txs[1u], 8, 7));
BEAST_EXPECT(checkTransaction(txs[2u], 7, 6));
if (!BEAST_EXPECT(jrr[jss::marker]))
return;
jrr = next(env, A3, 3, 9, 3, false, jrr[jss::marker]);
txs = jrr[jss::transactions];
if (!BEAST_EXPECT(txs.isArray() && txs.size() == 3))
return;
BEAST_EXPECT(checkTransaction(txs[0u], 6, 6));
BEAST_EXPECT(checkTransaction(txs[1u], 5, 5));
BEAST_EXPECT(checkTransaction(txs[2u], 4, 5));
if (!BEAST_EXPECT(jrr[jss::marker]))
return;
jrr = next(env, A3, 3, 9, 3, false, jrr[jss::marker]);
txs = jrr[jss::transactions];
if (!BEAST_EXPECT(txs.isArray() && txs.size() == 3))
return;
BEAST_EXPECT(checkTransaction(txs[0u], 4, 4));
BEAST_EXPECT(checkTransaction(txs[1u], 4, 4));
BEAST_EXPECT(checkTransaction(txs[2u], 3, 3));
if (!BEAST_EXPECT(jrr[jss::marker]))
return;
jrr = next(env, A3, 3, 9, 3, false, jrr[jss::marker]);
txs = jrr[jss::transactions];
if (!BEAST_EXPECT(txs.isArray() && txs.size() == 1))
return;
BEAST_EXPECT(checkTransaction(txs[0u], 3, 3));
BEAST_EXPECT(!jrr[jss::marker]);
}
}
public:
void
run() override
{
testAccountTxPaging();
}
};
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, xrpl);
} // namespace xrpl