rippled
AccountObjects_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 
20 #include <ripple/json/json_reader.h>
21 #include <ripple/json/json_value.h>
22 #include <ripple/json/to_string.h>
23 #include <ripple/protocol/jss.h>
24 #include <test/jtx.h>
25 
26 #include <boost/utility/string_ref.hpp>
27 
28 #include <algorithm>
29 
30 namespace ripple {
31 namespace test {
32 
33 static char const* bobs_account_objects[] = {
34  R"json({
35  "Account" : "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
36  "BookDirectory" : "50AD0A9E54D2B381288D535EB724E4275FFBF41580D28A925D038D7EA4C68000",
37  "BookNode" : "0000000000000000",
38  "Flags" : 65536,
39  "LedgerEntryType" : "Offer",
40  "OwnerNode" : "0000000000000000",
41  "Sequence" : 6,
42  "TakerGets" : {
43  "currency" : "USD",
44  "issuer" : "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
45  "value" : "1"
46  },
47  "TakerPays" : "100000000",
48  "index" : "29665262716C19830E26AEEC0916E476FC7D8EF195FF3B4F06829E64F82A3B3E"
49 })json",
50  R"json({
51  "Balance" : {
52  "currency" : "USD",
53  "issuer" : "rrrrrrrrrrrrrrrrrrrrBZbvji",
54  "value" : "-1000"
55  },
56  "Flags" : 131072,
57  "HighLimit" : {
58  "currency" : "USD",
59  "issuer" : "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
60  "value" : "1000"
61  },
62  "HighNode" : "0000000000000000",
63  "LedgerEntryType" : "RippleState",
64  "LowLimit" : {
65  "currency" : "USD",
66  "issuer" : "r9cZvwKU3zzuZK9JFovGg1JC5n7QiqNL8L",
67  "value" : "0"
68  },
69  "LowNode" : "0000000000000000",
70  "index" : "D13183BCFFC9AAC9F96AEBB5F66E4A652AD1F5D10273AEB615478302BEBFD4A4"
71 })json",
72  R"json({
73  "Balance" : {
74  "currency" : "USD",
75  "issuer" : "rrrrrrrrrrrrrrrrrrrrBZbvji",
76  "value" : "-1000"
77  },
78  "Flags" : 131072,
79  "HighLimit" : {
80  "currency" : "USD",
81  "issuer" : "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
82  "value" : "1000"
83  },
84  "HighNode" : "0000000000000000",
85  "LedgerEntryType" : "RippleState",
86  "LowLimit" : {
87  "currency" : "USD",
88  "issuer" : "r32rQHyesiTtdWFU7UJVtff4nCR5SHCbJW",
89  "value" : "0"
90  },
91  "LowNode" : "0000000000000000",
92  "index" : "D89BC239086183EB9458C396E643795C1134963E6550E682A190A5F021766D43"
93 })json",
94  R"json({
95  "Account" : "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
96  "BookDirectory" : "B025997A323F5C3E03DDF1334471F5984ABDE31C59D463525D038D7EA4C68000",
97  "BookNode" : "0000000000000000",
98  "Flags" : 65536,
99  "LedgerEntryType" : "Offer",
100  "OwnerNode" : "0000000000000000",
101  "Sequence" : 7,
102  "TakerGets" : {
103  "currency" : "USD",
104  "issuer" : "r32rQHyesiTtdWFU7UJVtff4nCR5SHCbJW",
105  "value" : "1"
106  },
107  "TakerPays" : "100000000",
108  "index" : "F03ABE26CB8C5F4AFB31A86590BD25C64C5756FCE5CE9704C27AFE291A4A29A1"
109 })json"};
110 
111 class AccountObjects_test : public beast::unit_test::suite
112 {
113 public:
114  void
116  {
117  testcase("error cases");
118 
119  using namespace jtx;
120  Env env(*this);
121 
122  // test error on no account
123  {
124  auto resp = env.rpc("json", "account_objects");
125  BEAST_EXPECT(resp[jss::error_message] == "Syntax error.");
126  }
127  // test error on malformed account string.
128  {
129  Json::Value params;
130  params[jss::account] =
131  "n94JNrQYkDrpt62bbSR7nVEhdyAvcJXRAsjEkFYyqRkh9SUTYEqV";
132  auto resp = env.rpc("json", "account_objects", to_string(params));
133  BEAST_EXPECT(
134  resp[jss::result][jss::error_message] == "Disallowed seed.");
135  }
136  // test error on account that's not in the ledger.
137  {
138  Json::Value params;
139  params[jss::account] = Account{"bogie"}.human();
140  auto resp = env.rpc("json", "account_objects", to_string(params));
141  BEAST_EXPECT(
142  resp[jss::result][jss::error_message] == "Account not found.");
143  }
144  Account const bob{"bob"};
145  // test error on large ledger_index.
146  {
147  Json::Value params;
148  params[jss::account] = bob.human();
149  params[jss::ledger_index] = 10;
150  auto resp = env.rpc("json", "account_objects", to_string(params));
151  BEAST_EXPECT(
152  resp[jss::result][jss::error_message] == "ledgerNotFound");
153  }
154 
155  env.fund(XRP(1000), bob);
156  // test error on type param not a string
157  {
158  Json::Value params;
159  params[jss::account] = bob.human();
160  params[jss::type] = 10;
161  auto resp = env.rpc("json", "account_objects", to_string(params));
162  BEAST_EXPECT(
163  resp[jss::result][jss::error_message] ==
164  "Invalid field 'type', not string.");
165  }
166  // test error on type param not a valid type
167  {
168  Json::Value params;
169  params[jss::account] = bob.human();
170  params[jss::type] = "expedited";
171  auto resp = env.rpc("json", "account_objects", to_string(params));
172  BEAST_EXPECT(
173  resp[jss::result][jss::error_message] ==
174  "Invalid field 'type'.");
175  }
176  // test error on limit -ve
177  {
178  Json::Value params;
179  params[jss::account] = bob.human();
180  params[jss::limit] = -1;
181  auto resp = env.rpc("json", "account_objects", to_string(params));
182  BEAST_EXPECT(
183  resp[jss::result][jss::error_message] ==
184  "Invalid field 'limit', not unsigned integer.");
185  }
186  // test errors on marker
187  {
188  Account const gw{"G"};
189  env.fund(XRP(1000), gw);
190  auto const USD = gw["USD"];
191  env.trust(USD(1000), bob);
192  env(pay(gw, bob, XRP(1)));
193  env(offer(bob, XRP(100), bob["USD"](1)), txflags(tfPassive));
194 
195  Json::Value params;
196  params[jss::account] = bob.human();
197  params[jss::limit] = 1;
198  auto resp = env.rpc("json", "account_objects", to_string(params));
199 
200  auto resume_marker = resp[jss::result][jss::marker];
201  std::string mark = to_string(resume_marker);
202  params[jss::marker] = 10;
203  resp = env.rpc("json", "account_objects", to_string(params));
204  BEAST_EXPECT(
205  resp[jss::result][jss::error_message] ==
206  "Invalid field 'marker', not string.");
207 
208  params[jss::marker] = "This is a string with no comma";
209  resp = env.rpc("json", "account_objects", to_string(params));
210  BEAST_EXPECT(
211  resp[jss::result][jss::error_message] ==
212  "Invalid field 'marker'.");
213 
214  params[jss::marker] = "This string has a comma, but is not hex";
215  resp = env.rpc("json", "account_objects", to_string(params));
216  BEAST_EXPECT(
217  resp[jss::result][jss::error_message] ==
218  "Invalid field 'marker'.");
219 
220  params[jss::marker] = std::string(&mark[1U], 64);
221  resp = env.rpc("json", "account_objects", to_string(params));
222  BEAST_EXPECT(
223  resp[jss::result][jss::error_message] ==
224  "Invalid field 'marker'.");
225 
226  params[jss::marker] = std::string(&mark[1U], 65);
227  resp = env.rpc("json", "account_objects", to_string(params));
228  BEAST_EXPECT(
229  resp[jss::result][jss::error_message] ==
230  "Invalid field 'marker'.");
231 
232  params[jss::marker] = std::string(&mark[1U], 65) + "not hex";
233  resp = env.rpc("json", "account_objects", to_string(params));
234  BEAST_EXPECT(
235  resp[jss::result][jss::error_message] ==
236  "Invalid field 'marker'.");
237 
238  // Should this be an error?
239  // A hex digit is absent from the end of marker.
240  // No account objects returned.
241  params[jss::marker] = std::string(&mark[1U], 128);
242  resp = env.rpc("json", "account_objects", to_string(params));
243  BEAST_EXPECT(resp[jss::result][jss::account_objects].size() == 0);
244  }
245  }
246 
247  void
249  {
250  testcase("unsteppedThenStepped");
251 
252  using namespace jtx;
253  Env env(*this);
254 
255  Account const gw1{"G1"};
256  Account const gw2{"G2"};
257  Account const bob{"bob"};
258 
259  auto const USD1 = gw1["USD"];
260  auto const USD2 = gw2["USD"];
261 
262  env.fund(XRP(1000), gw1, gw2, bob);
263  env.trust(USD1(1000), bob);
264  env.trust(USD2(1000), bob);
265 
266  env(pay(gw1, bob, USD1(1000)));
267  env(pay(gw2, bob, USD2(1000)));
268 
269  env(offer(bob, XRP(100), bob["USD"](1)), txflags(tfPassive));
270  env(offer(bob, XRP(100), USD1(1)), txflags(tfPassive));
271 
272  Json::Value bobj[4];
273  for (int i = 0; i < 4; ++i)
274  Json::Reader{}.parse(bobs_account_objects[i], bobj[i]);
275 
276  // test 'unstepped'
277  // i.e. request account objects without explicit limit/marker paging
278  {
279  Json::Value params;
280  params[jss::account] = bob.human();
281  auto resp = env.rpc("json", "account_objects", to_string(params));
282  BEAST_EXPECT(!resp.isMember(jss::marker));
283 
284  BEAST_EXPECT(resp[jss::result][jss::account_objects].size() == 4);
285  for (int i = 0; i < 4; ++i)
286  {
287  auto& aobj = resp[jss::result][jss::account_objects][i];
288  aobj.removeMember("PreviousTxnID");
289  aobj.removeMember("PreviousTxnLgrSeq");
290 
291  if (aobj != bobj[i])
292  std::cout << "Fail at " << i << ": " << aobj << std::endl;
293  BEAST_EXPECT(aobj == bobj[i]);
294  }
295  }
296  // test request with type parameter as filter, unstepped
297  {
298  Json::Value params;
299  params[jss::account] = bob.human();
300  params[jss::type] = "state";
301  auto resp = env.rpc("json", "account_objects", to_string(params));
302  BEAST_EXPECT(!resp.isMember(jss::marker));
303 
304  BEAST_EXPECT(resp[jss::result][jss::account_objects].size() == 2);
305  for (int i = 0; i < 2; ++i)
306  {
307  auto& aobj = resp[jss::result][jss::account_objects][i];
308  aobj.removeMember("PreviousTxnID");
309  aobj.removeMember("PreviousTxnLgrSeq");
310  BEAST_EXPECT(aobj == bobj[i + 1]);
311  }
312  }
313  // test stepped one-at-a-time with limit=1, resume from prev marker
314  {
315  Json::Value params;
316  params[jss::account] = bob.human();
317  params[jss::limit] = 1;
318  for (int i = 0; i < 4; ++i)
319  {
320  auto resp =
321  env.rpc("json", "account_objects", to_string(params));
322  auto& aobjs = resp[jss::result][jss::account_objects];
323  BEAST_EXPECT(aobjs.size() == 1);
324  auto& aobj = aobjs[0U];
325  if (i < 3)
326  BEAST_EXPECT(resp[jss::result][jss::limit] == 1);
327 
328  aobj.removeMember("PreviousTxnID");
329  aobj.removeMember("PreviousTxnLgrSeq");
330 
331  BEAST_EXPECT(aobj == bobj[i]);
332 
333  auto resume_marker = resp[jss::result][jss::marker];
334  params[jss::marker] = resume_marker;
335  }
336  }
337  }
338 
339  void
341  {
342  testcase("object types");
343 
344  // Give gw a bunch of ledger objects and make sure we can retrieve
345  // them by type.
346  using namespace jtx;
347 
348  Account const alice{"alice"};
349  Account const gw{"gateway"};
350  auto const USD = gw["USD"];
351 
352  // Test for ticket account objects when they are supported.
354 
355  // Make a lambda we can use to get "account_objects" easily.
356  auto acct_objs = [&env](Account const& acct, char const* type) {
357  Json::Value params;
358  params[jss::account] = acct.human();
359  params[jss::type] = type;
360  params[jss::ledger_index] = "validated";
361  return env.rpc("json", "account_objects", to_string(params));
362  };
363 
364  // Make a lambda that easily identifies the size of account objects.
365  auto acct_objs_is_size = [](Json::Value const& resp, unsigned size) {
366  return resp[jss::result][jss::account_objects].isArray() &&
367  (resp[jss::result][jss::account_objects].size() == size);
368  };
369 
370  env.fund(XRP(10000), gw, alice);
371  env.close();
372 
373  // Since the account is empty now, all account objects should come
374  // back empty.
375  BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::account), 0));
376  BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::amendments), 0));
377  BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::check), 0));
378  BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::deposit_preauth), 0));
379  BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::directory), 0));
380  BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::escrow), 0));
381  BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::fee), 0));
382  BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::hashes), 0));
383  BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::offer), 0));
384  BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::payment_channel), 0));
385  BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::signer_list), 0));
386  BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::state), 0));
387  BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::ticket), 0));
388 
389  // Set up a trust line so we can find it.
390  env.trust(USD(1000), alice);
391  env.close();
392  env(pay(gw, alice, USD(5)));
393  env.close();
394  {
395  // Find the trustline and make sure it's the right one.
396  Json::Value const resp = acct_objs(gw, jss::state);
397  BEAST_EXPECT(acct_objs_is_size(resp, 1));
398 
399  auto const& state = resp[jss::result][jss::account_objects][0u];
400  BEAST_EXPECT(state[sfBalance.jsonName][jss::value].asInt() == -5);
401  BEAST_EXPECT(
402  state[sfHighLimit.jsonName][jss::value].asUInt() == 1000);
403  }
404  // gw writes a check for USD(10) to alice.
405  env(check::create(gw, alice, USD(10)));
406  env.close();
407  {
408  // Find the check.
409  Json::Value const resp = acct_objs(gw, jss::check);
410  BEAST_EXPECT(acct_objs_is_size(resp, 1));
411 
412  auto const& check = resp[jss::result][jss::account_objects][0u];
413  BEAST_EXPECT(check[sfAccount.jsonName] == gw.human());
414  BEAST_EXPECT(check[sfDestination.jsonName] == alice.human());
415  BEAST_EXPECT(check[sfSendMax.jsonName][jss::value].asUInt() == 10);
416  }
417  // gw preauthorizes payments from alice.
418  env(deposit::auth(gw, alice));
419  env.close();
420  {
421  // Find the preauthorization.
422  Json::Value const resp = acct_objs(gw, jss::deposit_preauth);
423  BEAST_EXPECT(acct_objs_is_size(resp, 1));
424 
425  auto const& preauth = resp[jss::result][jss::account_objects][0u];
426  BEAST_EXPECT(preauth[sfAccount.jsonName] == gw.human());
427  BEAST_EXPECT(preauth[sfAuthorize.jsonName] == alice.human());
428  }
429  {
430  // gw creates an escrow that we can look for in the ledger.
431  Json::Value jvEscrow;
432  jvEscrow[jss::TransactionType] = jss::EscrowCreate;
433  jvEscrow[jss::Flags] = tfUniversal;
434  jvEscrow[jss::Account] = gw.human();
435  jvEscrow[jss::Destination] = gw.human();
436  jvEscrow[jss::Amount] = XRP(100).value().getJson(JsonOptions::none);
437  jvEscrow[sfFinishAfter.jsonName] =
438  env.now().time_since_epoch().count() + 1;
439  env(jvEscrow);
440  env.close();
441  }
442  {
443  // Find the escrow.
444  Json::Value const resp = acct_objs(gw, jss::escrow);
445  BEAST_EXPECT(acct_objs_is_size(resp, 1));
446 
447  auto const& escrow = resp[jss::result][jss::account_objects][0u];
448  BEAST_EXPECT(escrow[sfAccount.jsonName] == gw.human());
449  BEAST_EXPECT(escrow[sfDestination.jsonName] == gw.human());
450  BEAST_EXPECT(escrow[sfAmount.jsonName].asUInt() == 100'000'000);
451  }
452  // gw creates an offer that we can look for in the ledger.
453  env(offer(gw, USD(7), XRP(14)));
454  env.close();
455  {
456  // Find the offer.
457  Json::Value const resp = acct_objs(gw, jss::offer);
458  BEAST_EXPECT(acct_objs_is_size(resp, 1));
459 
460  auto const& offer = resp[jss::result][jss::account_objects][0u];
461  BEAST_EXPECT(offer[sfAccount.jsonName] == gw.human());
462  BEAST_EXPECT(offer[sfTakerGets.jsonName].asUInt() == 14'000'000);
463  BEAST_EXPECT(offer[sfTakerPays.jsonName][jss::value].asUInt() == 7);
464  }
465  {
466  // Create a payment channel from qw to alice that we can look for.
467  Json::Value jvPayChan;
468  jvPayChan[jss::TransactionType] = jss::PaymentChannelCreate;
469  jvPayChan[jss::Flags] = tfUniversal;
470  jvPayChan[jss::Account] = gw.human();
471  jvPayChan[jss::Destination] = alice.human();
472  jvPayChan[jss::Amount] =
473  XRP(300).value().getJson(JsonOptions::none);
474  jvPayChan[sfSettleDelay.jsonName] = 24 * 60 * 60;
475  jvPayChan[sfPublicKey.jsonName] = strHex(gw.pk().slice());
476  env(jvPayChan);
477  env.close();
478  }
479  {
480  // Find the payment channel.
481  Json::Value const resp = acct_objs(gw, jss::payment_channel);
482  BEAST_EXPECT(acct_objs_is_size(resp, 1));
483 
484  auto const& payChan = resp[jss::result][jss::account_objects][0u];
485  BEAST_EXPECT(payChan[sfAccount.jsonName] == gw.human());
486  BEAST_EXPECT(payChan[sfAmount.jsonName].asUInt() == 300'000'000);
487  BEAST_EXPECT(
488  payChan[sfSettleDelay.jsonName].asUInt() == 24 * 60 * 60);
489  }
490  // Make gw multisigning by adding a signerList.
491  env(signers(gw, 6, {{alice, 7}}));
492  env.close();
493  {
494  // Find the signer list.
495  Json::Value const resp = acct_objs(gw, jss::signer_list);
496  BEAST_EXPECT(acct_objs_is_size(resp, 1));
497 
498  auto const& signerList =
499  resp[jss::result][jss::account_objects][0u];
500  BEAST_EXPECT(signerList[sfSignerQuorum.jsonName] == 6);
501  auto const& entry = signerList[sfSignerEntries.jsonName][0u]
503  BEAST_EXPECT(entry[sfAccount.jsonName] == alice.human());
504  BEAST_EXPECT(entry[sfSignerWeight.jsonName].asUInt() == 7);
505  }
506  // Create a Ticket for gw.
507  env(ticket::create(gw, gw));
508  env.close();
509  {
510  // Find the ticket.
511  Json::Value const resp = acct_objs(gw, jss::ticket);
512  BEAST_EXPECT(acct_objs_is_size(resp, 1));
513 
514  auto const& ticket = resp[jss::result][jss::account_objects][0u];
515  BEAST_EXPECT(ticket[sfAccount.jsonName] == gw.human());
516  BEAST_EXPECT(ticket[sfLedgerEntryType.jsonName] == jss::Ticket);
517  BEAST_EXPECT(ticket[sfSequence.jsonName].asUInt() == 11);
518  }
519  {
520  // See how "deletion_blockers_only" handles gw's directory.
521  Json::Value params;
522  params[jss::account] = gw.human();
523  params[jss::deletion_blockers_only] = true;
524  auto resp = env.rpc("json", "account_objects", to_string(params));
525 
526  std::vector<std::string> const expectedLedgerTypes = [] {
528  jss::Escrow.c_str(),
529  jss::Check.c_str(),
530  jss::RippleState.c_str(),
531  jss::PayChannel.c_str()};
532  std::sort(v.begin(), v.end());
533  return v;
534  }();
535 
536  std::uint32_t const expectedAccountObjects{
537  static_cast<std::uint32_t>(std::size(expectedLedgerTypes))};
538 
539  if (BEAST_EXPECT(acct_objs_is_size(resp, expectedAccountObjects)))
540  {
541  auto const& aobjs = resp[jss::result][jss::account_objects];
542  std::vector<std::string> gotLedgerTypes;
543  gotLedgerTypes.reserve(expectedAccountObjects);
544  for (std::uint32_t i = 0; i < expectedAccountObjects; ++i)
545  {
546  gotLedgerTypes.push_back(
547  aobjs[i]["LedgerEntryType"].asString());
548  }
549  std::sort(gotLedgerTypes.begin(), gotLedgerTypes.end());
550  BEAST_EXPECT(gotLedgerTypes == expectedLedgerTypes);
551  }
552  }
553  {
554  // See how "deletion_blockers_only" with `type` handles gw's
555  // directory.
556  Json::Value params;
557  params[jss::account] = gw.human();
558  params[jss::deletion_blockers_only] = true;
559  params[jss::type] = jss::escrow;
560  auto resp = env.rpc("json", "account_objects", to_string(params));
561 
562  if (BEAST_EXPECT(acct_objs_is_size(resp, 1u)))
563  {
564  auto const& aobjs = resp[jss::result][jss::account_objects];
565  BEAST_EXPECT(aobjs[0u]["LedgerEntryType"] == jss::Escrow);
566  }
567  }
568 
569  // Run up the number of directory entries so gw has two
570  // directory nodes.
571  for (int d = 1'000'032; d >= 1'000'000; --d)
572  {
573  env(offer(gw, USD(1), drops(d)));
574  env.close();
575  }
576 
577  // Verify that the non-returning types still don't return anything.
578  BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::account), 0));
579  BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::amendments), 0));
580  BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::directory), 0));
581  BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::fee), 0));
582  BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::hashes), 0));
583  }
584 
585  void
586  run() override
587  {
588  testErrors();
590  testObjectTypes();
591  }
592 };
593 
594 BEAST_DEFINE_TESTSUITE(AccountObjects, app, ripple);
595 
596 } // namespace test
597 } // namespace ripple
ripple::test::AccountObjects_test::testObjectTypes
void testObjectTypes()
Definition: AccountObjects_test.cpp:340
ripple::test::jtx::XRP
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:105
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountDelete, app, ripple)
std::string
STL class.
ripple::test::jtx::drops
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Definition: amount.h:241
ripple::sfLedgerEntryType
const SF_U16 sfLedgerEntryType(access, STI_UINT16, 1, "LedgerEntryType", SField::sMD_Never)
Definition: SField.h:346
std::vector::reserve
T reserve(T... args)
ripple::sfSignerQuorum
const SF_U32 sfSignerQuorum(access, STI_UINT32, 35, "SignerQuorum")
Definition: SField.h:388
ripple::test::AccountObjects_test
Definition: AccountObjects_test.cpp:111
std::vector< std::string >
std::size
T size(T... args)
ripple::sfSequence
const SF_U32 sfSequence(access, STI_UINT32, 4, "Sequence")
Definition: SField.h:356
ripple::tfPassive
const std::uint32_t tfPassive
Definition: TxFlags.h:76
ripple::sfAccount
const SF_Account sfAccount(access, STI_ACCOUNT, 1, "Account")
Definition: SField.h:480
ripple::sfTakerPays
const SF_Amount sfTakerPays(access, STI_AMOUNT, 4, "TakerPays")
Definition: SField.h:443
ripple::test::jtx::Account::human
std::string const & human() const
Returns the human readable public key.
Definition: Account.h:109
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:42
Json::Reader
Unserialize a JSON document into a Value.
Definition: json_reader.h:36
ripple::sfAmount
const SF_Amount sfAmount(access, STI_AMOUNT, 1, "Amount")
Definition: SField.h:440
ripple::sfSignerEntries
const SField sfSignerEntries(access, STI_ARRAY, 4, "SignerEntries")
Definition: SField.h:517
ripple::SField::jsonName
const Json::StaticString jsonName
Definition: SField.h:133
ripple::sfHighLimit
const SF_Amount sfHighLimit(access, STI_AMOUNT, 7, "HighLimit")
Definition: SField.h:446
ripple::sfFinishAfter
const SF_U32 sfFinishAfter(access, STI_UINT32, 37, "FinishAfter")
Definition: SField.h:390
std::sort
T sort(T... args)
ripple::test::jtx::Env::trust
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
Definition: Env.cpp:250
algorithm
ripple::test::AccountObjects_test::testUnsteppedThenStepped
void testUnsteppedThenStepped()
Definition: AccountObjects_test.cpp:248
std::vector::push_back
T push_back(T... args)
ripple::test::AccountObjects_test::testErrors
void testErrors()
Definition: AccountObjects_test.cpp:115
std::cout
std::chrono::time_point::time_since_epoch
T time_since_epoch(T... args)
ripple::sfSendMax
const SF_Amount sfSendMax(access, STI_AMOUNT, 9, "SendMax")
Definition: SField.h:448
ripple::JsonOptions::none
@ none
ripple::set
bool set(T &target, std::string const &name, Section const &section)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
Definition: BasicConfig.h:276
ripple::test::jtx::txflags
Set the flags on a JTx.
Definition: txflags.h:30
Json::Value::size
UInt size() const
Number of values in array or object.
Definition: json_value.cpp:706
ripple::sfSignerEntry
const SField sfSignerEntry(access, STI_OBJECT, 11, "SignerEntry")
Definition: SField.h:508
ripple::test::jtx::supported_amendments
FeatureBitset supported_amendments()
Definition: Env.h:70
std::uint32_t
ripple::featureTickets
const uint256 featureTickets
Definition: Feature.cpp:163
ripple::tfUniversal
const std::uint32_t tfUniversal
Definition: TxFlags.h:49
Json::Value::isArray
bool isArray() const
Definition: json_value.cpp:1015
ripple::sfPublicKey
const SF_Blob sfPublicKey(access, STI_VL, 1, "PublicKey")
Definition: SField.h:457
ripple::sfSignerWeight
const SF_U16 sfSignerWeight(access, STI_UINT16, 3, "SignerWeight")
Definition: SField.h:348
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
std::endl
T endl(T... args)
ripple::sfBalance
const SF_Amount sfBalance(access, STI_AMOUNT, 2, "Balance")
Definition: SField.h:441
ripple::test::jtx::pay
Json::Value pay(Account const &account, Account const &to, AnyAmount amount)
Create a payment.
Definition: pay.cpp:29
ripple::test::jtx::Env::now
NetClock::time_point now()
Returns the current Ripple Network Time.
Definition: Env.h:263
ripple::test::jtx::Env::close
bool close(NetClock::time_point closeTime, boost::optional< std::chrono::milliseconds > consensusDelay=boost::none)
Close and advance the ledger.
Definition: Env.cpp:121
std::vector::begin
T begin(T... args)
ripple::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:219
Json::Reader::parse
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
Definition: json_reader.cpp:73
ripple::test::AccountObjects_test::run
void run() override
Definition: AccountObjects_test.cpp:586
ripple::sfSettleDelay
const SF_U32 sfSettleDelay(access, STI_UINT32, 39, "SettleDelay")
Definition: SField.h:392
ripple::sfTakerGets
const SF_Amount sfTakerGets(access, STI_AMOUNT, 5, "TakerGets")
Definition: SField.h:444
ripple::sfDestination
const SF_Account sfDestination(access, STI_ACCOUNT, 3, "Destination")
Definition: SField.h:482
ripple::test::jtx::Account
Immutable cryptographic account descriptor.
Definition: Account.h:37
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:67
std::vector::end
T end(T... args)
ripple::sfAuthorize
const SF_Account sfAuthorize(access, STI_ACCOUNT, 5, "Authorize")
Definition: SField.h:484
ripple::test::bobs_account_objects
static char const * bobs_account_objects[]
Definition: AccountObjects_test.cpp:33
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:115
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:684
Json::Value
Represents a JSON value.
Definition: json_value.h:145