rippled
STObject_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 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/beast/unit_test.h>
21 #include <ripple/json/json_reader.h>
22 #include <ripple/json/to_string.h>
23 #include <ripple/protocol/SecretKey.h>
24 #include <ripple/protocol/jss.h>
25 #include <ripple/protocol/st.h>
26 #include <test/jtx.h>
27 
28 #include <array>
29 #include <memory>
30 #include <type_traits>
31 
32 namespace ripple {
33 
34 class STObject_test : public beast::unit_test::suite
35 {
36 public:
37  bool
39  {
40  Json::Reader reader;
41  return reader.parse(json, to) && to.isObject();
42  }
43 
44  void
46  {
47  testcase("parse json array invalid children");
48  try
49  {
50  /*
51 
52  STArray/STObject constructs don't really map perfectly to json
53  arrays/objects.
54 
55  STObject is an associative container, mapping fields to value, but
56  an STObject may also have a Field as its name, stored outside the
57  associative structure. The name is important, so to maintain
58  fidelity, it will take TWO json objects to represent them.
59 
60  */
61  std::string faulty(
62  "{\"Template\":[{"
63  "\"ModifiedNode\":{\"Sequence\":1}, "
64  "\"DeletedNode\":{\"Sequence\":1}"
65  "}]}");
66 
68  Json::Value faultyJson;
69  bool parsedOK(parseJSONString(faulty, faultyJson));
70  unexpected(!parsedOK, "failed to parse");
71  STParsedJSONObject parsed("test", faultyJson);
72  BEAST_EXPECT(!parsed.object);
73  }
74  catch (std::runtime_error& e)
75  {
76  std::string what(e.what());
77  unexpected(what.find("First level children of `Template`") != 0);
78  }
79  }
80 
81  void
83  {
84  testcase("parse json array");
85  std::string const json(
86  "{\"Template\":[{\"ModifiedNode\":{\"Sequence\":1}}]}");
87 
88  Json::Value jsonObject;
89  bool parsedOK(parseJSONString(json, jsonObject));
90  if (parsedOK)
91  {
92  STParsedJSONObject parsed("test", jsonObject);
93  BEAST_EXPECT(parsed.object);
94  std::string const& serialized(
95  to_string(parsed.object->getJson(JsonOptions::none)));
96  BEAST_EXPECT(serialized == json);
97  }
98  else
99  {
100  fail("Couldn't parse json: " + json);
101  }
102  }
103 
104  void
106  {
107  testcase("parse json object");
108 
109  {
110  std::string const goodJson(R"({"CloseResolution":19,"Method":250,)"
111  R"("TransactionResult":"tecFROZEN"})");
112 
113  Json::Value jv;
114  if (BEAST_EXPECT(parseJSONString(goodJson, jv)))
115  {
116  STParsedJSONObject parsed("test", jv);
117  if (BEAST_EXPECT(parsed.object))
118  {
119  std::string const& serialized(
120  to_string(parsed.object->getJson(JsonOptions::none)));
121  BEAST_EXPECT(serialized == goodJson);
122  }
123  }
124  }
125 
126  {
127  std::string const goodJson(
128  R"({"CloseResolution":19,"Method":"250",)"
129  R"("TransactionResult":"tecFROZEN"})");
130  std::string const expectedJson(
131  R"({"CloseResolution":19,"Method":250,)"
132  R"("TransactionResult":"tecFROZEN"})");
133 
134  Json::Value jv;
135  if (BEAST_EXPECT(parseJSONString(goodJson, jv)))
136  {
137  // Integer values are always parsed as int,
138  // unless they're too big. We want a small uint.
139  jv["CloseResolution"] = Json::UInt(19);
140  STParsedJSONObject parsed("test", jv);
141  if (BEAST_EXPECT(parsed.object))
142  {
143  std::string const& serialized(
144  to_string(parsed.object->getJson(JsonOptions::none)));
145  BEAST_EXPECT(serialized == expectedJson);
146  }
147  }
148  }
149 
150  {
151  std::string const json(R"({"CloseResolution":19,"Method":250,)"
152  R"("TransactionResult":"terQUEUED"})");
153 
154  Json::Value jv;
155  if (BEAST_EXPECT(parseJSONString(json, jv)))
156  {
157  STParsedJSONObject parsed("test", jv);
158  BEAST_EXPECT(!parsed.object);
159  BEAST_EXPECT(parsed.error);
160  BEAST_EXPECT(parsed.error[jss::error] == "invalidParams");
161  BEAST_EXPECT(
162  parsed.error[jss::error_message] ==
163  "Field 'test.TransactionResult' is out of range.");
164  }
165  }
166 
167  {
168  std::string const json(R"({"CloseResolution":19,"Method":"pony",)"
169  R"("TransactionResult":"tesSUCCESS"})");
170 
171  Json::Value jv;
172  if (BEAST_EXPECT(parseJSONString(json, jv)))
173  {
174  STParsedJSONObject parsed("test", jv);
175  BEAST_EXPECT(!parsed.object);
176  BEAST_EXPECT(parsed.error);
177  BEAST_EXPECT(parsed.error[jss::error] == "invalidParams");
178  BEAST_EXPECT(
179  parsed.error[jss::error_message] ==
180  "Field 'test.Method' has bad type.");
181  }
182  }
183 
184  {
185  std::string const json(
186  R"({"CloseResolution":19,"Method":3294967296,)"
187  R"("TransactionResult":"tesSUCCESS"})");
188 
189  Json::Value jv;
190  if (BEAST_EXPECT(parseJSONString(json, jv)))
191  {
192  STParsedJSONObject parsed("test", jv);
193  BEAST_EXPECT(!parsed.object);
194  BEAST_EXPECT(parsed.error);
195  BEAST_EXPECT(parsed.error[jss::error] == "invalidParams");
196  BEAST_EXPECT(
197  parsed.error[jss::error_message] ==
198  "Field 'test.Method' is out of range.");
199  }
200  }
201 
202  {
203  std::string const json(R"({"CloseResolution":-10,"Method":42,)"
204  R"("TransactionResult":"tesSUCCESS"})");
205 
206  Json::Value jv;
207  if (BEAST_EXPECT(parseJSONString(json, jv)))
208  {
209  STParsedJSONObject parsed("test", jv);
210  BEAST_EXPECT(!parsed.object);
211  BEAST_EXPECT(parsed.error);
212  BEAST_EXPECT(parsed.error[jss::error] == "invalidParams");
213  BEAST_EXPECT(
214  parsed.error[jss::error_message] ==
215  "Field 'test.CloseResolution' is out of range.");
216  }
217  }
218 
219  {
220  std::string const json(
221  R"({"CloseResolution":19,"Method":3.141592653,)"
222  R"("TransactionResult":"tesSUCCESS"})");
223 
224  Json::Value jv;
225  if (BEAST_EXPECT(parseJSONString(json, jv)))
226  {
227  STParsedJSONObject parsed("test", jv);
228  BEAST_EXPECT(!parsed.object);
229  BEAST_EXPECT(parsed.error);
230  BEAST_EXPECT(parsed.error[jss::error] == "invalidParams");
231  BEAST_EXPECT(
232  parsed.error[jss::error_message] ==
233  "Field 'test.Method' has bad type.");
234  }
235  }
236  }
237 
238  void
240  {
241  testcase("serialization");
242 
243  unexpected(sfGeneric.isUseful(), "sfGeneric must not be useful");
244  {
245  // Try to put sfGeneric in an SOTemplate.
246  except<std::runtime_error>([&]() {
247  SOTemplate elements{{sfGeneric, soeREQUIRED}};
248  });
249  }
250 
251  unexpected(sfInvalid.isUseful(), "sfInvalid must not be useful");
252  {
253  // Test return of sfInvalid.
254  auto testInvalid = [this](SerializedTypeID tid, int fv) {
255  SField const& shouldBeInvalid{SField::getField(tid, fv)};
256  BEAST_EXPECT(shouldBeInvalid == sfInvalid);
257  };
258  testInvalid(STI_VL, 255);
259  testInvalid(STI_UINT256, 255);
260  testInvalid(STI_UINT32, 255);
261  testInvalid(STI_VECTOR256, 255);
262  testInvalid(STI_OBJECT, 255);
263  }
264  {
265  // Try to put sfInvalid in an SOTemplate.
266  except<std::runtime_error>([&]() {
267  SOTemplate elements{{sfInvalid, soeREQUIRED}};
268  });
269  }
270  {
271  // Try to put the same SField into an SOTemplate twice.
272  except<std::runtime_error>([&]() {
273  SOTemplate elements{
276  };
277  });
278  }
279 
280  // Put a variety of SFields of different types in an SOTemplate.
281  SField const& sfTestVL = sfMasterSignature;
282  SField const& sfTestH256 = sfCheckID;
283  SField const& sfTestU32 = sfSettleDelay;
284  SField const& sfTestV256 = sfAmendments;
285  SField const& sfTestObject = sfMajority;
286 
287  SOTemplate const elements{
288  {sfFlags, soeREQUIRED},
289  {sfTestVL, soeREQUIRED},
290  {sfTestH256, soeOPTIONAL},
291  {sfTestU32, soeREQUIRED},
292  {sfTestV256, soeOPTIONAL},
293  };
294 
295  STObject object1(elements, sfTestObject);
296  STObject object2(object1);
297 
298  unexpected(
299  object1.getSerializer() != object2.getSerializer(),
300  "STObject error 1");
301 
302  unexpected(
303  object1.isFieldPresent(sfTestH256) ||
304  !object1.isFieldPresent(sfTestVL),
305  "STObject error");
306 
307  object1.makeFieldPresent(sfTestH256);
308 
309  unexpected(!object1.isFieldPresent(sfTestH256), "STObject Error 2");
310 
311  unexpected(
312  object1.getFieldH256(sfTestH256) != uint256(), "STObject error 3");
313 
314  if (object1.getSerializer() == object2.getSerializer())
315  {
316  log << "O1: " << object1.getJson(JsonOptions::none) << '\n'
317  << "O2: " << object2.getJson(JsonOptions::none) << std::endl;
318  fail("STObject error 4");
319  }
320  else
321  {
322  pass();
323  }
324 
325  object1.makeFieldAbsent(sfTestH256);
326 
327  unexpected(object1.isFieldPresent(sfTestH256), "STObject error 5");
328 
329  unexpected(object1.getFlags() != 0, "STObject error 6");
330 
331  unexpected(
332  object1.getSerializer() != object2.getSerializer(),
333  "STObject error 7");
334 
335  STObject copy(object1);
336 
337  unexpected(object1.isFieldPresent(sfTestH256), "STObject error 8");
338 
339  unexpected(copy.isFieldPresent(sfTestH256), "STObject error 9");
340 
341  unexpected(
342  object1.getSerializer() != copy.getSerializer(),
343  "STObject error 10");
344 
345  copy.setFieldU32(sfTestU32, 1);
346 
347  unexpected(
348  object1.getSerializer() == copy.getSerializer(),
349  "STObject error 11");
350 
351  for (int i = 0; i < 1000; i++)
352  {
353  Blob j(i, 2);
354 
355  object1.setFieldVL(sfTestVL, j);
356 
357  Serializer s;
358  object1.add(s);
359  SerialIter it(s.slice());
360 
361  STObject object3(elements, it, sfTestObject);
362 
363  unexpected(object1.getFieldVL(sfTestVL) != j, "STObject error");
364 
365  unexpected(object3.getFieldVL(sfTestVL) != j, "STObject error");
366  }
367 
368  {
369  std::vector<uint256> uints;
370  uints.reserve(5);
371  for (int i = 0; i < uints.capacity(); ++i)
372  {
373  uints.emplace_back(i);
374  }
375  object1.setFieldV256(sfTestV256, STVector256(uints));
376 
377  Serializer s;
378  object1.add(s);
379  SerialIter it(s.slice());
380 
381  STObject object3(elements, it, sfTestObject);
382 
383  auto const& uints1 = object1.getFieldV256(sfTestV256);
384  auto const& uints3 = object3.getFieldV256(sfTestV256);
385 
386  BEAST_EXPECT(uints1 == uints3);
387  }
388  }
389 
390  // Exercise field accessors
391  void
393  {
394  testcase("fields");
395 
396  auto const& sf1Outer = sfSequence;
397  auto const& sf2Outer = sfExpiration;
398  auto const& sf3Outer = sfQualityIn;
399  auto const& sf4 = sfSignature;
400  auto const& sf5 = sfPublicKey;
401 
402  // read free object
403 
404  {
405  auto const st = [&]() {
406  STObject s(sfGeneric);
407  s.setFieldU32(sf1Outer, 1);
408  s.setFieldU32(sf2Outer, 2);
409  return s;
410  }();
411 
412  BEAST_EXPECT(st[sf1Outer] == 1);
413  BEAST_EXPECT(st[sf2Outer] == 2);
414  except<STObject::FieldErr>([&]() { st[sf3Outer]; });
415  BEAST_EXPECT(*st[~sf1Outer] == 1);
416  BEAST_EXPECT(*st[~sf2Outer] == 2);
417  BEAST_EXPECT(st[~sf3Outer] == std::nullopt);
418  BEAST_EXPECT(!!st[~sf1Outer]);
419  BEAST_EXPECT(!!st[~sf2Outer]);
420  BEAST_EXPECT(!st[~sf3Outer]);
421  BEAST_EXPECT(st[sf1Outer] != st[sf2Outer]);
422  BEAST_EXPECT(st[~sf1Outer] != st[~sf2Outer]);
423  }
424 
425  // read templated object
426  SOTemplate const sotOuter{
427  {sf1Outer, soeREQUIRED},
428  {sf2Outer, soeOPTIONAL},
429  {sf3Outer, soeDEFAULT},
430  {sf4, soeOPTIONAL},
431  {sf5, soeDEFAULT},
432  };
433 
434  {
435  auto const st = [&]() {
436  STObject s(sotOuter, sfGeneric);
437  s.setFieldU32(sf1Outer, 1);
438  s.setFieldU32(sf2Outer, 2);
439  return s;
440  }();
441 
442  BEAST_EXPECT(st[sf1Outer] == 1);
443  BEAST_EXPECT(st[sf2Outer] == 2);
444  BEAST_EXPECT(st[sf3Outer] == 0);
445  BEAST_EXPECT(*st[~sf1Outer] == 1);
446  BEAST_EXPECT(*st[~sf2Outer] == 2);
447  BEAST_EXPECT(*st[~sf3Outer] == 0);
448  BEAST_EXPECT(!!st[~sf1Outer]);
449  BEAST_EXPECT(!!st[~sf2Outer]);
450  BEAST_EXPECT(!!st[~sf3Outer]);
451  }
452 
453  // write free object
454 
455  {
456  STObject st(sfGeneric);
457  unexcept([&]() { st[sf1Outer]; });
458  except([&]() { return st[sf1Outer] == 0; });
459  BEAST_EXPECT(st[~sf1Outer] == std::nullopt);
460  BEAST_EXPECT(st[~sf1Outer] == std::optional<std::uint32_t>{});
461  BEAST_EXPECT(st[~sf1Outer] != std::optional<std::uint32_t>(1));
462  BEAST_EXPECT(!st[~sf1Outer]);
463  st[sf1Outer] = 2;
464  BEAST_EXPECT(st[sf1Outer] == 2);
465  BEAST_EXPECT(st[~sf1Outer] != std::nullopt);
466  BEAST_EXPECT(st[~sf1Outer] == std::optional<std::uint32_t>(2));
467  BEAST_EXPECT(!!st[~sf1Outer]);
468  st[sf1Outer] = 1;
469  BEAST_EXPECT(st[sf1Outer] == 1);
470  BEAST_EXPECT(!!st[sf1Outer]);
471  BEAST_EXPECT(!!st[~sf1Outer]);
472  st[sf1Outer] = 0;
473  BEAST_EXPECT(!st[sf1Outer]);
474  BEAST_EXPECT(!!st[~sf1Outer]);
475  st[~sf1Outer] = std::nullopt;
476  BEAST_EXPECT(!st[~sf1Outer]);
477  BEAST_EXPECT(st[~sf1Outer] == std::nullopt);
478  BEAST_EXPECT(st[~sf1Outer] == std::optional<std::uint32_t>{});
479  st[~sf1Outer] = std::nullopt;
480  BEAST_EXPECT(!st[~sf1Outer]);
481  except([&]() { return st[sf1Outer] == 0; });
482  except([&]() { return *st[~sf1Outer]; });
483  st[sf1Outer] = 1;
484  BEAST_EXPECT(st[sf1Outer] == 1);
485  BEAST_EXPECT(!!st[sf1Outer]);
486  BEAST_EXPECT(!!st[~sf1Outer]);
487  st[sf1Outer] = 3;
488  st[sf2Outer] = st[sf1Outer];
489  BEAST_EXPECT(st[sf1Outer] == 3);
490  BEAST_EXPECT(st[sf2Outer] == 3);
491  BEAST_EXPECT(st[sf2Outer] == st[sf1Outer]);
492  st[sf1Outer] = 4;
493  st[sf2Outer] = st[sf1Outer];
494  BEAST_EXPECT(st[sf1Outer] == 4);
495  BEAST_EXPECT(st[sf2Outer] == 4);
496  BEAST_EXPECT(st[sf2Outer] == st[sf1Outer]);
497  }
498 
499  // Write templated object
500 
501  {
502  STObject st(sotOuter, sfGeneric);
503  BEAST_EXPECT(!!st[~sf1Outer]);
504  BEAST_EXPECT(st[~sf1Outer] != std::nullopt);
505  BEAST_EXPECT(st[sf1Outer] == 0);
506  BEAST_EXPECT(*st[~sf1Outer] == 0);
507  BEAST_EXPECT(!st[~sf2Outer]);
508  BEAST_EXPECT(st[~sf2Outer] == std::nullopt);
509  except([&]() { return st[sf2Outer] == 0; });
510  BEAST_EXPECT(!!st[~sf3Outer]);
511  BEAST_EXPECT(st[~sf3Outer] != std::nullopt);
512  BEAST_EXPECT(st[sf3Outer] == 0);
513  except([&]() { st[~sf1Outer] = std::nullopt; });
514  st[sf1Outer] = 1;
515  BEAST_EXPECT(st[sf1Outer] == 1);
516  BEAST_EXPECT(*st[~sf1Outer] == 1);
517  BEAST_EXPECT(!!st[~sf1Outer]);
518  st[sf1Outer] = 0;
519  BEAST_EXPECT(st[sf1Outer] == 0);
520  BEAST_EXPECT(*st[~sf1Outer] == 0);
521  BEAST_EXPECT(!!st[~sf1Outer]);
522  st[sf2Outer] = 2;
523  BEAST_EXPECT(st[sf2Outer] == 2);
524  BEAST_EXPECT(*st[~sf2Outer] == 2);
525  BEAST_EXPECT(!!st[~sf2Outer]);
526  st[~sf2Outer] = std::nullopt;
527  except([&]() { return *st[~sf2Outer]; });
528  BEAST_EXPECT(!st[~sf2Outer]);
529  st[sf3Outer] = 3;
530  BEAST_EXPECT(st[sf3Outer] == 3);
531  BEAST_EXPECT(*st[~sf3Outer] == 3);
532  BEAST_EXPECT(!!st[~sf3Outer]);
533  st[sf3Outer] = 2;
534  BEAST_EXPECT(st[sf3Outer] == 2);
535  BEAST_EXPECT(*st[~sf3Outer] == 2);
536  BEAST_EXPECT(!!st[~sf3Outer]);
537  st[sf3Outer] = 0;
538  BEAST_EXPECT(st[sf3Outer] == 0);
539  BEAST_EXPECT(*st[~sf3Outer] == 0);
540  BEAST_EXPECT(!!st[~sf3Outer]);
541  except([&]() { st[~sf3Outer] = std::nullopt; });
542  BEAST_EXPECT(st[sf3Outer] == 0);
543  BEAST_EXPECT(*st[~sf3Outer] == 0);
544  BEAST_EXPECT(!!st[~sf3Outer]);
545  }
546 
547  // coercion operator to std::optional
548 
549  {
550  STObject st(sfGeneric);
551  auto const v = ~st[~sf1Outer];
552  static_assert(
553  std::is_same<
554  std::decay_t<decltype(v)>,
556  "");
557  }
558 
559  // UDT scalar fields
560 
561  {
562  STObject st(sfGeneric);
563  st[sfAmount] = STAmount{};
564  st[sfAccount] = AccountID{};
565  st[sfDigest] = uint256{};
566  [&](STAmount) {}(st[sfAmount]);
567  [&](AccountID) {}(st[sfAccount]);
568  [&](uint256) {}(st[sfDigest]);
569  }
570 
571  // STBlob and slice
572 
573  {{STObject st(sfGeneric);
574  Buffer b(1);
575  BEAST_EXPECT(!b.empty());
576  st[sf4] = std::move(b);
577  BEAST_EXPECT(b.empty());
578  BEAST_EXPECT(Slice(st[sf4]).size() == 1);
579  st[~sf4] = std::nullopt;
580  BEAST_EXPECT(!~st[~sf4]);
581  b = Buffer{2};
582  st[sf4] = Slice(b);
583  BEAST_EXPECT(b.size() == 2);
584  BEAST_EXPECT(Slice(st[sf4]).size() == 2);
585  st[sf5] = st[sf4];
586  BEAST_EXPECT(Slice(st[sf4]).size() == 2);
587  BEAST_EXPECT(Slice(st[sf5]).size() == 2);
588  }
589  {
590  STObject st(sotOuter, sfGeneric);
591  BEAST_EXPECT(st[sf5] == Slice{});
592  BEAST_EXPECT(!!st[~sf5]);
593  BEAST_EXPECT(!!~st[~sf5]);
594  Buffer b(1);
595  st[sf5] = std::move(b);
596  BEAST_EXPECT(b.empty());
597  BEAST_EXPECT(Slice(st[sf5]).size() == 1);
598  st[~sf4] = std::nullopt;
599  BEAST_EXPECT(!~st[~sf4]);
600  }
601 }
602 
603 // UDT blobs
604 
605 {
606  STObject st(sfGeneric);
607  BEAST_EXPECT(!st[~sf5]);
608  auto const kp =
609  generateKeyPair(KeyType::secp256k1, generateSeed("masterpassphrase"));
610  st[sf5] = kp.first;
611  st[~sf5] = std::nullopt;
612 }
613 
614 // By reference fields
615 
616 {
617  auto const& sf = sfIndexes;
618  STObject st(sfGeneric);
620  v.emplace_back(1);
621  v.emplace_back(2);
622  st[sf] = v;
623  st[sf] = std::move(v);
624  auto const& cst = st;
625  BEAST_EXPECT(cst[sf].size() == 2);
626  BEAST_EXPECT(cst[~sf]->size() == 2);
627  BEAST_EXPECT(cst[sf][0] == 1);
628  BEAST_EXPECT(cst[sf][1] == 2);
629  static_assert(
630  std::is_same<decltype(cst[sfIndexes]), std::vector<uint256> const&>::
631  value,
632  "");
633 }
634 
635 // Default by reference field
636 
637 {
638  auto const& sf1 = sfIndexes;
639  auto const& sf2 = sfHashes;
640  auto const& sf3 = sfAmendments;
641  SOTemplate const sot{
642  {sf1, soeREQUIRED},
643  {sf2, soeOPTIONAL},
644  {sf3, soeDEFAULT},
645  };
646 
647  STObject st(sot, sfGeneric);
648  auto const& cst(st);
649  BEAST_EXPECT(cst[sf1].size() == 0);
650  BEAST_EXPECT(!cst[~sf2]);
651  BEAST_EXPECT(cst[sf3].size() == 0);
653  v.emplace_back(1);
654  st[sf1] = v;
655  BEAST_EXPECT(cst[sf1].size() == 1);
656  BEAST_EXPECT(cst[sf1][0] == uint256{1});
657  st[sf2] = v;
658  BEAST_EXPECT(cst[sf2].size() == 1);
659  BEAST_EXPECT(cst[sf2][0] == uint256{1});
660  st[~sf2] = std::nullopt;
661  BEAST_EXPECT(!st[~sf2]);
662  st[sf3] = v;
663  BEAST_EXPECT(cst[sf3].size() == 1);
664  BEAST_EXPECT(cst[sf3][0] == uint256{1});
665  st[sf3] = std::vector<uint256>{};
666  BEAST_EXPECT(cst[sf3].size() == 0);
667 }
668 } // namespace ripple
669 
670 void
672 {
673  testcase("Malformed serialized forms");
674 
675  try
676  {
677  std::array<std::uint8_t, 7> const payload{
678  {0xe9, 0x12, 0xab, 0xcd, 0x12, 0xfe, 0xdc}};
679  SerialIter sit{makeSlice(payload)};
680  auto obj = std::make_shared<STArray>(sit, sfMetadata);
681  BEAST_EXPECT(!obj);
682  }
683  catch (std::exception const& e)
684  {
685  BEAST_EXPECT(strcmp(e.what(), "Duplicate field detected") == 0);
686  }
687 
688  try
689  {
690  std::array<std::uint8_t, 3> const payload{{0xe2, 0xe1, 0xe2}};
691  SerialIter sit{makeSlice(payload)};
692  auto obj = std::make_shared<STObject>(sit, sfMetadata);
693  BEAST_EXPECT(!obj);
694  }
695  catch (std::exception const& e)
696  {
697  BEAST_EXPECT(strcmp(e.what(), "Duplicate field detected") == 0);
698  }
699 }
700 
701 void
702 run() override
703 {
704  // Instantiate a jtx::Env so debugLog writes are exercised.
705  test::jtx::Env env(*this);
706 
707  testFields();
712  testMalformed();
713 }
714 }
715 ;
716 
718 
719 } // ripple
ripple::STObject_test::testParseJSONArrayWithInvalidChildrenObjects
void testParseJSONArrayWithInvalidChildrenObjects()
Definition: STObject_test.cpp:45
std::is_same
ripple::makeSlice
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition: Slice.h:241
ripple::STObject::makeFieldAbsent
void makeFieldAbsent(SField const &field)
Definition: STObject.cpp:530
ripple::sfMetadata
const SField sfMetadata
Json::Value::isObject
bool isObject() const
Definition: json_value.cpp:1027
std::string
STL class.
ripple::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple)
std::exception
STL class.
ripple::sfGeneric
const SField sfGeneric(access, 0)
Definition: SField.h:359
ripple::STObject::setFieldV256
void setFieldV256(SField const &field, STVector256 const &v)
Definition: STObject.cpp:712
ripple::sfAmount
const SF_AMOUNT sfAmount
ripple::sfCheckID
const SF_UINT256 sfCheckID
ripple::Slice
An immutable linear range of bytes.
Definition: Slice.h:44
ripple::STObject::getFieldV256
const STVector256 & getFieldV256(SField const &field) const
Definition: STObject.cpp:633
std::vector::reserve
T reserve(T... args)
ripple::sfSequence
const SF_UINT32 sfSequence
Json::UInt
unsigned int UInt
Definition: json_forwards.h:27
std::vector< unsigned char >
std::string::find
T find(T... args)
ripple::SerializedTypeID
SerializedTypeID
Definition: SField.h:106
ripple::SField::isUseful
bool isUseful() const
Definition: SField.h:228
ripple::STObject_test::run
void run() override
Definition: STObject_test.cpp:702
ripple::STObject_test::testMalformed
void testMalformed()
Definition: STObject_test.cpp:671
ripple::STObject::getSerializer
Serializer getSerializer() const
Definition: STObject.h:911
ripple::sfQualityIn
const SF_UINT32 sfQualityIn
ripple::Buffer::empty
bool empty() const noexcept
Definition: Buffer.h:132
ripple::soeREQUIRED
@ soeREQUIRED
Definition: SOTemplate.h:35
ripple::Buffer
Like std::vector<char> but better.
Definition: Buffer.h:35
ripple::STParsedJSONObject
Holds the serialized result of parsing an input JSON object.
Definition: STParsedJSON.h:31
ripple::SField::getField
static const SField & getField(int fieldCode)
Definition: SField.cpp:464
ripple::STObject::setFieldVL
void setFieldVL(SField const &field, Blob const &)
Definition: STObject.cpp:724
ripple::STObject::getFieldVL
Blob getFieldVL(SField const &field) const
Definition: STObject.cpp:611
Json::Reader
Unserialize a JSON document into a Value.
Definition: json_reader.h:36
ripple::STParsedJSONObject::object
std::optional< STObject > object
The STObject if the parse was successful.
Definition: STParsedJSON.h:50
ripple::sfInvalid
const SField sfInvalid(access, -1)
Definition: SField.h:358
ripple::generateKeyPair
std::pair< PublicKey, SecretKey > generateKeyPair(KeyType type, Seed const &seed)
Generate a key pair deterministically.
Definition: SecretKey.cpp:351
ripple::STParsedJSONObject::error
Json::Value error
On failure, an appropriate set of error values.
Definition: STParsedJSON.h:53
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:550
ripple::sfExpiration
const SF_UINT32 sfExpiration
ripple::sfIndexes
const SF_VECTOR256 sfIndexes
ripple::base_uint< 256 >
std::vector::capacity
T capacity(T... args)
ripple::sfSettleDelay
const SF_UINT32 sfSettleDelay
ripple::SOTemplate
Defines the fields and their attributes within a STObject.
Definition: SOTemplate.h:84
ripple::sfMasterSignature
const SF_VL sfMasterSignature
ripple::soeOPTIONAL
@ soeOPTIONAL
Definition: SOTemplate.h:36
ripple::STObject_test::testSerialization
void testSerialization()
Definition: STObject_test.cpp:239
ripple::sfDigest
const SF_UINT256 sfDigest
array
ripple::STAmount
Definition: STAmount.h:46
ripple::Serializer::slice
Slice slice() const noexcept
Definition: Serializer.h:64
ripple::Buffer::size
std::size_t size() const noexcept
Returns the number of bytes in the buffer.
Definition: Buffer.h:126
ripple::STObject::getFlags
std::uint32_t getFlags() const
Definition: STObject.cpp:497
ripple::sfMajority
const SField sfMajority
ripple::STObject_test::parseJSONString
bool parseJSONString(std::string const &json, Json::Value &to)
Definition: STObject_test.cpp:38
std::runtime_error
STL class.
ripple::SerialIter
Definition: Serializer.h:311
ripple::STObject_test::testParseJSONArray
void testParseJSONArray()
Definition: STObject_test.cpp:82
ripple::STObject_test::testFields
void testFields()
Definition: STObject_test.cpp:392
memory
ripple::KeyType::secp256k1
@ secp256k1
std::decay_t
ripple::Serializer
Definition: Serializer.h:40
ripple::STObject::makeFieldPresent
STBase * makeFieldPresent(SField const &field)
Definition: STObject.cpp:508
ripple::sfHashes
const SF_VECTOR256 sfHashes
ripple::generateSeed
Seed generateSeed(std::string const &passPhrase)
Generate a seed deterministically.
Definition: Seed.cpp:69
ripple::STObject::add
void add(Serializer &s) const override
Definition: STObject.cpp:101
ripple::STObject
Definition: STObject.h:55
std::vector::emplace_back
T emplace_back(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::STObject_test
Definition: STObject_test.cpp:34
ripple::JsonOptions::none
@ none
Definition: STBase.h:42
std::endl
T endl(T... args)
protocol
Definition: ValidatorList.h:38
ripple::STObject_test::testParseJSONEdgeCases
void testParseJSONEdgeCases()
Definition: STObject_test.cpp:105
ripple::SField
Identifies fields.
Definition: SField.h:141
ripple::sfFlags
const SF_UINT32 sfFlags
ripple::STObject::isFieldPresent
bool isFieldPresent(SField const &field) const
Definition: STObject.cpp:444
Json::Reader::parse
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
Definition: json_reader.cpp:73
ripple::sfSignature
const SF_VL sfSignature
ripple::STVector256
Definition: STVector256.h:30
std::optional< std::uint32_t >
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:38
ripple::sfAccount
const SF_ACCOUNT sfAccount
ripple::STObject::getJson
Json::Value getJson(JsonOptions options) const override
Definition: STObject.cpp:766
std::unique_ptr
STL class.
ripple::STObject::setFieldU32
void setFieldU32(SField const &field, std::uint32_t)
Definition: STObject.cpp:688
ripple::sfPublicKey
const SF_VL sfPublicKey
type_traits
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:116
ripple::soeDEFAULT
@ soeDEFAULT
Definition: SOTemplate.h:37
ripple::AccountID
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition: AccountID.h:49
std::runtime_error::what
T what(T... args)
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::sfAmendments
const SF_VECTOR256 sfAmendments
ripple::STObject::getFieldH256
uint256 getFieldH256(SField const &field) const
Definition: STObject.cpp:599