rippled
Loading...
Searching...
No Matches
AccountTxPaging_test.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2016 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19#include <test/jtx.h>
20#include <xrpl/beast/unit_test.h>
21#include <xrpl/protocol/SField.h>
22#include <xrpl/protocol/jss.h>
23#include <cstdlib>
24
25#include <test/rpc/GRPCTestClientBase.h>
26#include <xrpld/rpc/GRPCHandlers.h>
27#include <xrpld/rpc/detail/RPCHelpers.h>
28
29namespace ripple {
30
32{
33 bool
34 checkTransaction(Json::Value const& tx, int sequence, int ledger)
35 {
36 return (
37 tx[jss::tx][jss::Sequence].asInt() == sequence &&
38 tx[jss::tx][jss::ledger_index].asInt() == ledger);
39 }
40
41 auto
43 test::jtx::Env& env,
44 test::jtx::Account const& account,
45 int ledger_min,
46 int ledger_max,
47 int limit,
48 bool forward,
49 Json::Value const& marker = Json::nullValue)
50 {
51 Json::Value jvc;
52 jvc[jss::account] = account.human();
53 jvc[jss::ledger_index_min] = ledger_min;
54 jvc[jss::ledger_index_max] = ledger_max;
55 jvc[jss::forward] = forward;
56 jvc[jss::limit] = limit;
57 if (marker)
58 jvc[jss::marker] = marker;
59
60 return env.rpc("json", "account_tx", to_string(jvc))[jss::result];
61 }
62
63 void
65 {
66 testcase("Paging for Single Account");
67 using namespace test::jtx;
68
69 Env env(*this);
70 Account A1{"A1"};
71 Account A2{"A2"};
72 Account A3{"A3"};
73
74 env.fund(XRP(10000), A1, A2, A3);
75 env.close();
76
77 env.trust(A3["USD"](1000), A1);
78 env.trust(A2["USD"](1000), A1);
79 env.trust(A3["USD"](1000), A2);
80 env.close();
81
82 for (auto i = 0; i < 5; ++i)
83 {
84 env(pay(A2, A1, A2["USD"](2)));
85 env(pay(A3, A1, A3["USD"](2)));
86 env(offer(A1, XRP(11), A1["USD"](1)));
87 env(offer(A2, XRP(10), A2["USD"](1)));
88 env(offer(A3, XRP(9), A3["USD"](1)));
89 env.close();
90 }
91
92 /* The sequence/ledger for A3 are as follows:
93 * seq ledger_index
94 * 3 ----> 3
95 * 1 ----> 3
96 * 2 ----> 4
97 * 2 ----> 4
98 * 2 ----> 5
99 * 3 ----> 5
100 * 4 ----> 6
101 * 5 ----> 6
102 * 6 ----> 7
103 * 7 ----> 7
104 * 8 ----> 8
105 * 9 ----> 8
106 * 10 ----> 9
107 * 11 ----> 9
108 */
109
110 // page through the results in several ways.
111 {
112 // limit = 2, 3 batches giving the first 6 txs
113 auto jrr = next(env, A3, 2, 5, 2, true);
114 auto txs = jrr[jss::transactions];
115 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 2))
116 return;
117 BEAST_EXPECT(checkTransaction(txs[0u], 3, 3));
118 BEAST_EXPECT(checkTransaction(txs[1u], 3, 3));
119 if (!BEAST_EXPECT(jrr[jss::marker]))
120 return;
121
122 jrr = next(env, A3, 2, 5, 2, true, jrr[jss::marker]);
123 txs = jrr[jss::transactions];
124 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 2))
125 return;
126 BEAST_EXPECT(checkTransaction(txs[0u], 4, 4));
127 BEAST_EXPECT(checkTransaction(txs[1u], 4, 4));
128 if (!BEAST_EXPECT(jrr[jss::marker]))
129 return;
130
131 jrr = next(env, A3, 2, 5, 2, true, jrr[jss::marker]);
132 txs = jrr[jss::transactions];
133 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 2))
134 return;
135 BEAST_EXPECT(checkTransaction(txs[0u], 4, 5));
136 BEAST_EXPECT(checkTransaction(txs[1u], 5, 5));
137 BEAST_EXPECT(!jrr[jss::marker]);
138 }
139
140 {
141 // limit 1, 3 requests giving the first 3 txs
142 auto jrr = next(env, A3, 3, 9, 1, true);
143 auto txs = jrr[jss::transactions];
144 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 1))
145 return;
146 BEAST_EXPECT(checkTransaction(txs[0u], 3, 3));
147 if (!BEAST_EXPECT(jrr[jss::marker]))
148 return;
149
150 jrr = next(env, A3, 3, 9, 1, true, jrr[jss::marker]);
151 txs = jrr[jss::transactions];
152 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 1))
153 return;
154 BEAST_EXPECT(checkTransaction(txs[0u], 3, 3));
155 if (!BEAST_EXPECT(jrr[jss::marker]))
156 return;
157
158 jrr = next(env, A3, 3, 9, 1, true, jrr[jss::marker]);
159 txs = jrr[jss::transactions];
160 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 1))
161 return;
162 BEAST_EXPECT(checkTransaction(txs[0u], 4, 4));
163 if (!BEAST_EXPECT(jrr[jss::marker]))
164 return;
165
166 // continue with limit 3, to end of all txs
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], 4, 4));
172 BEAST_EXPECT(checkTransaction(txs[1u], 4, 5));
173 BEAST_EXPECT(checkTransaction(txs[2u], 5, 5));
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() == 3))
180 return;
181 BEAST_EXPECT(checkTransaction(txs[0u], 6, 6));
182 BEAST_EXPECT(checkTransaction(txs[1u], 7, 6));
183 BEAST_EXPECT(checkTransaction(txs[2u], 8, 7));
184 if (!BEAST_EXPECT(jrr[jss::marker]))
185 return;
186
187 jrr = next(env, A3, 3, 9, 3, true, jrr[jss::marker]);
188 txs = jrr[jss::transactions];
189 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 3))
190 return;
191 BEAST_EXPECT(checkTransaction(txs[0u], 9, 7));
192 BEAST_EXPECT(checkTransaction(txs[1u], 10, 8));
193 BEAST_EXPECT(checkTransaction(txs[2u], 11, 8));
194 if (!BEAST_EXPECT(jrr[jss::marker]))
195 return;
196
197 jrr = next(env, A3, 3, 9, 3, true, 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], 12, 9));
202 BEAST_EXPECT(checkTransaction(txs[1u], 13, 9));
203 BEAST_EXPECT(!jrr[jss::marker]);
204 }
205
206 {
207 // limit 2, descending, 2 batches giving last 4 txs
208 auto jrr = next(env, A3, 3, 9, 2, false);
209 auto txs = jrr[jss::transactions];
210 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 2))
211 return;
212 BEAST_EXPECT(checkTransaction(txs[0u], 13, 9));
213 BEAST_EXPECT(checkTransaction(txs[1u], 12, 9));
214 if (!BEAST_EXPECT(jrr[jss::marker]))
215 return;
216
217 jrr = next(env, A3, 3, 9, 2, false, jrr[jss::marker]);
218 txs = jrr[jss::transactions];
219 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 2))
220 return;
221 BEAST_EXPECT(checkTransaction(txs[0u], 11, 8));
222 BEAST_EXPECT(checkTransaction(txs[1u], 10, 8));
223 if (!BEAST_EXPECT(jrr[jss::marker]))
224 return;
225
226 // continue with limit 3 until all txs have been seen
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], 9, 7));
232 BEAST_EXPECT(checkTransaction(txs[1u], 8, 7));
233 BEAST_EXPECT(checkTransaction(txs[2u], 7, 6));
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() == 3))
240 return;
241 BEAST_EXPECT(checkTransaction(txs[0u], 6, 6));
242 BEAST_EXPECT(checkTransaction(txs[1u], 5, 5));
243 BEAST_EXPECT(checkTransaction(txs[2u], 4, 5));
244 if (!BEAST_EXPECT(jrr[jss::marker]))
245 return;
246
247 jrr = next(env, A3, 3, 9, 3, false, jrr[jss::marker]);
248 txs = jrr[jss::transactions];
249 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 3))
250 return;
251 BEAST_EXPECT(checkTransaction(txs[0u], 4, 4));
252 BEAST_EXPECT(checkTransaction(txs[1u], 4, 4));
253 BEAST_EXPECT(checkTransaction(txs[2u], 3, 3));
254 if (!BEAST_EXPECT(jrr[jss::marker]))
255 return;
256
257 jrr = next(env, A3, 3, 9, 3, false, jrr[jss::marker]);
258 txs = jrr[jss::transactions];
259 if (!BEAST_EXPECT(txs.isArray() && txs.size() == 1))
260 return;
261 BEAST_EXPECT(checkTransaction(txs[0u], 3, 3));
262 BEAST_EXPECT(!jrr[jss::marker]);
263 }
264 }
265
266public:
267 void
268 run() override
269 {
271 }
272};
273
274BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple);
275
276} // namespace ripple
Represents a JSON value.
Definition: json_value.h:147
A testsuite class.
Definition: suite.h:53
testcase_t testcase
Memberspace for declaring test cases.
Definition: suite.h:153
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:38
A transaction testing environment.
Definition: Env.h:117
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:764
@ nullValue
'null' value
Definition: json_value.h:36
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
std::string to_string(base_uint< Bits, Tag > const &a)
Definition: base_uint.h:629