rippled
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 <ripple/beast/unit_test.h>
20 #include <ripple/protocol/SField.h>
21 #include <ripple/protocol/jss.h>
22 #include <cstdlib>
23 #include <test/jtx.h>
24 
25 #include <ripple/rpc/GRPCHandlers.h>
26 #include <ripple/rpc/impl/RPCHelpers.h>
27 #include <test/rpc/GRPCTestClientBase.h>
28 
29 namespace ripple {
30 
31 class AccountTxPaging_test : public beast::unit_test::suite
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 
266 public:
267  void
268  run() override
269  {
271  }
272 };
273 
274 BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple);
275 
276 } // namespace ripple
ripple::AccountTxPaging_test
Definition: AccountTxPaging_test.cpp:31
ripple::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple)
ripple::AccountTxPaging_test::run
void run() override
Definition: AccountTxPaging_test.cpp:268
ripple::AccountTxPaging_test::checkTransaction
bool checkTransaction(Json::Value const &tx, int sequence, int ledger)
Definition: AccountTxPaging_test.cpp:34
ripple::AccountTxPaging_test::testAccountTxPaging
void testAccountTxPaging()
Definition: AccountTxPaging_test.cpp:64
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
cstdlib
ripple::AccountTxPaging_test::next
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)
Definition: AccountTxPaging_test.cpp:42
Json::nullValue
@ nullValue
'null' value
Definition: json_value.h:36
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::test::jtx::Account
Immutable cryptographic account descriptor.
Definition: Account.h:37
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:116
ripple::test::jtx::Env::rpc
Json::Value rpc(std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition: Env.h:687
Json::Value
Represents a JSON value.
Definition: json_value.h:145