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