rippled
Loading...
Searching...
No Matches
AccountTxPaging_test.cpp
1#include <test/jtx.h>
2#include <test/rpc/GRPCTestClientBase.h>
3
4#include <xrpl/beast/unit_test.h>
5#include <xrpl/protocol/jss.h>
6
7#include <cstdlib>
8
9namespace xrpl {
10
12{
13 bool
14 checkTransaction(Json::Value const& tx, int sequence, int ledger)
15 {
16 return (tx[jss::tx][jss::Sequence].asInt() == sequence && tx[jss::tx][jss::ledger_index].asInt() == ledger);
17 }
18
19 auto
21 test::jtx::Env& env,
22 test::jtx::Account const& account,
23 int ledger_min,
24 int ledger_max,
25 int limit,
26 bool forward,
27 Json::Value const& marker = Json::nullValue)
28 {
29 Json::Value jvc;
30 jvc[jss::account] = account.human();
31 jvc[jss::ledger_index_min] = ledger_min;
32 jvc[jss::ledger_index_max] = ledger_max;
33 jvc[jss::forward] = forward;
34 jvc[jss::limit] = limit;
35 if (marker)
36 jvc[jss::marker] = marker;
37
38 return env.rpc("json", "account_tx", to_string(jvc))[jss::result];
39 }
40
41 void
43 {
44 testcase("Paging for Single Account");
45 using namespace test::jtx;
46
47 Env env(*this);
48 Account A1{"A1"};
49 Account A2{"A2"};
50 Account A3{"A3"};
51
52 env.fund(XRP(10000), A1, A2, A3);
53 env.close();
54
55 env.trust(A3["USD"](1000), A1);
56 env.trust(A2["USD"](1000), A1);
57 env.trust(A3["USD"](1000), A2);
58 env.close();
59
60 for (auto i = 0; i < 5; ++i)
61 {
62 env(pay(A2, A1, A2["USD"](2)));
63 env(pay(A3, A1, A3["USD"](2)));
64 env(offer(A1, XRP(11), A1["USD"](1)));
65 env(offer(A2, XRP(10), A2["USD"](1)));
66 env(offer(A3, XRP(9), A3["USD"](1)));
67 env.close();
68 }
69
70 /* The sequence/ledger for A3 are as follows:
71 * seq ledger_index
72 * 3 ----> 3
73 * 1 ----> 3
74 * 2 ----> 4
75 * 2 ----> 4
76 * 2 ----> 5
77 * 3 ----> 5
78 * 4 ----> 6
79 * 5 ----> 6
80 * 6 ----> 7
81 * 7 ----> 7
82 * 8 ----> 8
83 * 9 ----> 8
84 * 10 ----> 9
85 * 11 ----> 9
86 */
87
88 // page through the results in several ways.
89 {
90 // limit = 2, 3 batches giving the first 6 txs
91 auto jrr = next(env, A3, 2, 5, 2, true);
92 auto txs = jrr[jss::transactions];
93 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 2))
94 return;
95 BEAST_EXPECT(checkTransaction(txs[0u], 3, 3));
96 BEAST_EXPECT(checkTransaction(txs[1u], 3, 3));
97 if (!BEAST_EXPECT(jrr[jss::marker]))
98 return;
99
100 jrr = next(env, A3, 2, 5, 2, true, jrr[jss::marker]);
101 txs = jrr[jss::transactions];
102 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 2))
103 return;
104 BEAST_EXPECT(checkTransaction(txs[0u], 4, 4));
105 BEAST_EXPECT(checkTransaction(txs[1u], 4, 4));
106 if (!BEAST_EXPECT(jrr[jss::marker]))
107 return;
108
109 jrr = next(env, A3, 2, 5, 2, true, jrr[jss::marker]);
110 txs = jrr[jss::transactions];
111 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 2))
112 return;
113 BEAST_EXPECT(checkTransaction(txs[0u], 4, 5));
114 BEAST_EXPECT(checkTransaction(txs[1u], 5, 5));
115 BEAST_EXPECT(!jrr[jss::marker]);
116 }
117
118 {
119 // limit 1, 3 requests giving the first 3 txs
120 auto jrr = next(env, A3, 3, 9, 1, true);
121 auto txs = jrr[jss::transactions];
122 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 1))
123 return;
124 BEAST_EXPECT(checkTransaction(txs[0u], 3, 3));
125 if (!BEAST_EXPECT(jrr[jss::marker]))
126 return;
127
128 jrr = next(env, A3, 3, 9, 1, true, jrr[jss::marker]);
129 txs = jrr[jss::transactions];
130 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 1))
131 return;
132 BEAST_EXPECT(checkTransaction(txs[0u], 3, 3));
133 if (!BEAST_EXPECT(jrr[jss::marker]))
134 return;
135
136 jrr = next(env, A3, 3, 9, 1, true, jrr[jss::marker]);
137 txs = jrr[jss::transactions];
138 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 1))
139 return;
140 BEAST_EXPECT(checkTransaction(txs[0u], 4, 4));
141 if (!BEAST_EXPECT(jrr[jss::marker]))
142 return;
143
144 // continue with limit 3, to end of all txs
145 jrr = next(env, A3, 3, 9, 3, true, jrr[jss::marker]);
146 txs = jrr[jss::transactions];
147 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 3))
148 return;
149 BEAST_EXPECT(checkTransaction(txs[0u], 4, 4));
150 BEAST_EXPECT(checkTransaction(txs[1u], 4, 5));
151 BEAST_EXPECT(checkTransaction(txs[2u], 5, 5));
152 if (!BEAST_EXPECT(jrr[jss::marker]))
153 return;
154
155 jrr = next(env, A3, 3, 9, 3, true, jrr[jss::marker]);
156 txs = jrr[jss::transactions];
157 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 3))
158 return;
159 BEAST_EXPECT(checkTransaction(txs[0u], 6, 6));
160 BEAST_EXPECT(checkTransaction(txs[1u], 7, 6));
161 BEAST_EXPECT(checkTransaction(txs[2u], 8, 7));
162 if (!BEAST_EXPECT(jrr[jss::marker]))
163 return;
164
165 jrr = next(env, A3, 3, 9, 3, true, jrr[jss::marker]);
166 txs = jrr[jss::transactions];
167 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 3))
168 return;
169 BEAST_EXPECT(checkTransaction(txs[0u], 9, 7));
170 BEAST_EXPECT(checkTransaction(txs[1u], 10, 8));
171 BEAST_EXPECT(checkTransaction(txs[2u], 11, 8));
172 if (!BEAST_EXPECT(jrr[jss::marker]))
173 return;
174
175 jrr = next(env, A3, 3, 9, 3, true, jrr[jss::marker]);
176 txs = jrr[jss::transactions];
177 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 2))
178 return;
179 BEAST_EXPECT(checkTransaction(txs[0u], 12, 9));
180 BEAST_EXPECT(checkTransaction(txs[1u], 13, 9));
181 BEAST_EXPECT(!jrr[jss::marker]);
182 }
183
184 {
185 // limit 2, descending, 2 batches giving last 4 txs
186 auto jrr = next(env, A3, 3, 9, 2, false);
187 auto txs = jrr[jss::transactions];
188 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 2))
189 return;
190 BEAST_EXPECT(checkTransaction(txs[0u], 13, 9));
191 BEAST_EXPECT(checkTransaction(txs[1u], 12, 9));
192 if (!BEAST_EXPECT(jrr[jss::marker]))
193 return;
194
195 jrr = next(env, A3, 3, 9, 2, false, jrr[jss::marker]);
196 txs = jrr[jss::transactions];
197 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 2))
198 return;
199 BEAST_EXPECT(checkTransaction(txs[0u], 11, 8));
200 BEAST_EXPECT(checkTransaction(txs[1u], 10, 8));
201 if (!BEAST_EXPECT(jrr[jss::marker]))
202 return;
203
204 // continue with limit 3 until all txs have been seen
205 jrr = next(env, A3, 3, 9, 3, false, jrr[jss::marker]);
206 txs = jrr[jss::transactions];
207 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 3))
208 return;
209 BEAST_EXPECT(checkTransaction(txs[0u], 9, 7));
210 BEAST_EXPECT(checkTransaction(txs[1u], 8, 7));
211 BEAST_EXPECT(checkTransaction(txs[2u], 7, 6));
212 if (!BEAST_EXPECT(jrr[jss::marker]))
213 return;
214
215 jrr = next(env, A3, 3, 9, 3, false, jrr[jss::marker]);
216 txs = jrr[jss::transactions];
217 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 3))
218 return;
219 BEAST_EXPECT(checkTransaction(txs[0u], 6, 6));
220 BEAST_EXPECT(checkTransaction(txs[1u], 5, 5));
221 BEAST_EXPECT(checkTransaction(txs[2u], 4, 5));
222 if (!BEAST_EXPECT(jrr[jss::marker]))
223 return;
224
225 jrr = next(env, A3, 3, 9, 3, false, jrr[jss::marker]);
226 txs = jrr[jss::transactions];
227 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 3))
228 return;
229 BEAST_EXPECT(checkTransaction(txs[0u], 4, 4));
230 BEAST_EXPECT(checkTransaction(txs[1u], 4, 4));
231 BEAST_EXPECT(checkTransaction(txs[2u], 3, 3));
232 if (!BEAST_EXPECT(jrr[jss::marker]))
233 return;
234
235 jrr = next(env, A3, 3, 9, 3, false, jrr[jss::marker]);
236 txs = jrr[jss::transactions];
237 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 1))
238 return;
239 BEAST_EXPECT(checkTransaction(txs[0u], 3, 3));
240 BEAST_EXPECT(!jrr[jss::marker]);
241 }
242 }
243
244public:
245 void
246 run() override
247 {
249 }
250};
251
252BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, xrpl);
253
254} // namespace xrpl
Represents a JSON value.
Definition json_value.h:130
A testsuite class.
Definition suite.h:51
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:147
bool checkTransaction(Json::Value const &tx, int sequence, int ledger)
void run() override
Runs the suite.
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)
Immutable cryptographic account descriptor.
Definition Account.h:19
A transaction testing environment.
Definition Env.h:119
Json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition Env.h:792
@ nullValue
'null' value
Definition json_value.h:19
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:597