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