rippled
Loading...
Searching...
No Matches
STObject_test.cpp
1#include <test/jtx.h>
2
3namespace xrpl {
4
6{
7public:
8 void
10 {
11 testcase("serialization");
12
13 unexpected(sfGeneric.isUseful(), "sfGeneric must not be useful");
14 {
15 // Try to put sfGeneric in an SOTemplate.
16 except<std::runtime_error>(
17 [&]() { SOTemplate const elements{{sfGeneric, soeREQUIRED}}; });
18 }
19
20 unexpected(sfInvalid.isUseful(), "sfInvalid must not be useful");
21 {
22 // Test return of sfInvalid.
23 auto testInvalid = [this](SerializedTypeID tid, int fv) {
24 SField const& shouldBeInvalid{SField::getField(tid, fv)};
25 BEAST_EXPECT(shouldBeInvalid == sfInvalid);
26 };
27 testInvalid(STI_VL, 255);
28 testInvalid(STI_UINT256, 255);
29 testInvalid(STI_UINT32, 255);
30 testInvalid(STI_VECTOR256, 255);
31 testInvalid(STI_OBJECT, 255);
32 }
33 {
34 // Try to put sfInvalid in an SOTemplate.
35 except<std::runtime_error>(
36 [&]() { SOTemplate const elements{{sfInvalid, soeREQUIRED}}; });
37 }
38 {
39 // Try to put the same SField into an SOTemplate twice.
40 except<std::runtime_error>([&]() {
41 SOTemplate const elements{
42 {sfAccount, soeREQUIRED},
43 {sfAccount, soeREQUIRED},
44 };
45 });
46 }
47
48 // Put a variety of SFields of different types in an SOTemplate.
49 SField const& sfTestVL = sfMasterSignature;
50 SField const& sfTestH256 = sfCheckID;
51 SField const& sfTestU32 = sfSettleDelay;
52 SField const& sfTestV256 = sfAmendments;
53 SField const& sfTestObject = sfMajority;
54
55 SOTemplate const elements{
56 {sfFlags, soeREQUIRED},
57 {sfTestVL, soeREQUIRED},
58 {sfTestH256, soeOPTIONAL},
59 {sfTestU32, soeREQUIRED},
60 {sfTestV256, soeOPTIONAL},
61 };
62
63 STObject object1(elements, sfTestObject);
64 STObject const object2(object1);
65
66 unexpected(object1.getSerializer() != object2.getSerializer(), "STObject error 1");
67
69 object1.isFieldPresent(sfTestH256) || !object1.isFieldPresent(sfTestVL),
70 "STObject error");
71
72 object1.makeFieldPresent(sfTestH256);
73
74 unexpected(!object1.isFieldPresent(sfTestH256), "STObject Error 2");
75
76 unexpected(object1.getFieldH256(sfTestH256) != uint256(), "STObject error 3");
77
78 if (object1.getSerializer() == object2.getSerializer())
79 {
80 log << "O1: " << object1.getJson(JsonOptions::none) << '\n'
81 << "O2: " << object2.getJson(JsonOptions::none) << std::endl;
82 fail("STObject error 4");
83 }
84 else
85 {
86 pass();
87 }
88
89 object1.makeFieldAbsent(sfTestH256);
90
91 unexpected(object1.isFieldPresent(sfTestH256), "STObject error 5");
92
93 unexpected(object1.getFlags() != 0, "STObject error 6");
94
95 unexpected(object1.getSerializer() != object2.getSerializer(), "STObject error 7");
96
97 STObject copy(object1);
98
99 unexpected(object1.isFieldPresent(sfTestH256), "STObject error 8");
100
101 unexpected(copy.isFieldPresent(sfTestH256), "STObject error 9");
102
103 unexpected(object1.getSerializer() != copy.getSerializer(), "STObject error 10");
104
105 copy.setFieldU32(sfTestU32, 1);
106
107 unexpected(object1.getSerializer() == copy.getSerializer(), "STObject error 11");
108
109 for (int i = 0; i < 1000; i++)
110 {
111 Blob const j(i, 2);
112
113 object1.setFieldVL(sfTestVL, j);
114
115 Serializer s;
116 object1.add(s);
117 SerialIter it(s.slice());
118
119 STObject const object3(elements, it, sfTestObject);
120
121 unexpected(object1.getFieldVL(sfTestVL) != j, "STObject error");
122
123 unexpected(object3.getFieldVL(sfTestVL) != j, "STObject error");
124 }
125
126 {
128 uints.reserve(5);
129 for (int i = 0; i < uints.capacity(); ++i)
130 {
131 uints.emplace_back(i);
132 }
133 object1.setFieldV256(sfTestV256, STVector256(uints));
134
135 Serializer s;
136 object1.add(s);
137 SerialIter it(s.slice());
138
139 STObject const object3(elements, it, sfTestObject);
140
141 auto const& uints1 = object1.getFieldV256(sfTestV256);
142 auto const& uints3 = object3.getFieldV256(sfTestV256);
143
144 BEAST_EXPECT(uints1 == uints3);
145 }
146 }
147
148 // Exercise field accessors
149 void
151 {
152 testcase("fields");
153
154 auto const& sf1Outer = sfSequence;
155 auto const& sf2Outer = sfExpiration;
156 auto const& sf3Outer = sfQualityIn;
157 auto const& sf4Outer = sfAmount;
158 auto const& sf4 = sfSignature;
159 auto const& sf5 = sfPublicKey;
160
161 // read free object
162
163 {
164 auto const st = [&]() {
166 s.setFieldU32(sf1Outer, 1);
167 s.setFieldU32(sf2Outer, 2);
168 return s;
169 }();
170
171 BEAST_EXPECT(st[sf1Outer] == 1);
172 BEAST_EXPECT(st[sf2Outer] == 2);
173 except<STObject::FieldErr>([&]() { st[sf3Outer]; });
174 BEAST_EXPECT(*st[~sf1Outer] == 1); // NOLINT(bugprone-unchecked-optional-access)
175 BEAST_EXPECT(*st[~sf2Outer] == 2); // NOLINT(bugprone-unchecked-optional-access)
176 BEAST_EXPECT(st[~sf3Outer] == std::nullopt);
177 BEAST_EXPECT(!!st[~sf1Outer]);
178 BEAST_EXPECT(!!st[~sf2Outer]);
179 BEAST_EXPECT(!st[~sf3Outer]);
180 BEAST_EXPECT(st[sf1Outer] != st[sf2Outer]);
181 BEAST_EXPECT(st[~sf1Outer] != st[~sf2Outer]);
182 }
183
184 // read templated object
185 SOTemplate const sotOuter{
186 {sf1Outer, soeREQUIRED},
187 {sf2Outer, soeOPTIONAL},
188 {sf3Outer, soeDEFAULT},
189 {sf4Outer, soeOPTIONAL},
190 {sf4, soeOPTIONAL},
191 {sf5, soeDEFAULT},
192 };
193
194 {
195 auto const st = [&]() {
196 STObject s(sotOuter, sfGeneric);
197 s.setFieldU32(sf1Outer, 1);
198 s.setFieldU32(sf2Outer, 2);
199 return s;
200 }();
201
202 BEAST_EXPECT(st[sf1Outer] == 1);
203 BEAST_EXPECT(st[sf2Outer] == 2);
204 BEAST_EXPECT(st[sf3Outer] == 0);
205 BEAST_EXPECT(*st[~sf1Outer] == 1); // NOLINT(bugprone-unchecked-optional-access)
206 BEAST_EXPECT(*st[~sf2Outer] == 2); // NOLINT(bugprone-unchecked-optional-access)
207 BEAST_EXPECT(*st[~sf3Outer] == 0); // NOLINT(bugprone-unchecked-optional-access)
208 BEAST_EXPECT(!!st[~sf1Outer]);
209 BEAST_EXPECT(!!st[~sf2Outer]);
210 BEAST_EXPECT(!!st[~sf3Outer]);
211 }
212
213 // write free object
214
215 {
217 unexcept([&]() { st[sf1Outer]; });
218 except([&]() { return st[sf1Outer] == 0; });
219 BEAST_EXPECT(st[~sf1Outer] == std::nullopt);
220 BEAST_EXPECT(st[~sf1Outer] == std::optional<std::uint32_t>{});
221 BEAST_EXPECT(st[~sf1Outer] != std::optional<std::uint32_t>(1));
222 BEAST_EXPECT(!st[~sf1Outer]);
223 st[sf1Outer] = 2;
224 BEAST_EXPECT(st[sf1Outer] == 2);
225 BEAST_EXPECT(st[~sf1Outer] != std::nullopt);
226 BEAST_EXPECT(st[~sf1Outer] == std::optional<std::uint32_t>(2));
227 BEAST_EXPECT(!!st[~sf1Outer]);
228 st[sf1Outer] = 1;
229 BEAST_EXPECT(st[sf1Outer] == 1);
230 BEAST_EXPECT(!!st[sf1Outer]);
231 BEAST_EXPECT(!!st[~sf1Outer]);
232 st[sf1Outer] = 0;
233 BEAST_EXPECT(!st[sf1Outer]);
234 BEAST_EXPECT(!!st[~sf1Outer]);
235 st[~sf1Outer] = std::nullopt;
236 BEAST_EXPECT(!st[~sf1Outer]);
237 BEAST_EXPECT(st[~sf1Outer] == std::nullopt);
238 BEAST_EXPECT(st[~sf1Outer] == std::optional<std::uint32_t>{});
239 st[~sf1Outer] = std::nullopt;
240 BEAST_EXPECT(!st[~sf1Outer]);
241 except([&]() { return st[sf1Outer] == 0; });
242 except([&]() { return *st[~sf1Outer]; });
243 st[sf1Outer] = 1;
244 BEAST_EXPECT(st[sf1Outer] == 1);
245 BEAST_EXPECT(!!st[sf1Outer]);
246 BEAST_EXPECT(!!st[~sf1Outer]);
247 st[sf1Outer] = 3;
248 st[sf2Outer] = st[sf1Outer];
249 BEAST_EXPECT(st[sf1Outer] == 3);
250 BEAST_EXPECT(st[sf2Outer] == 3);
251 BEAST_EXPECT(st[sf2Outer] == st[sf1Outer]);
252 st[sf1Outer] = 4;
253 st[sf2Outer] = st[sf1Outer];
254 BEAST_EXPECT(st[sf1Outer] == 4);
255 BEAST_EXPECT(st[sf2Outer] == 4);
256 BEAST_EXPECT(st[sf2Outer] == st[sf1Outer]);
257 st[sf1Outer] += 1;
258 BEAST_EXPECT(st[sf1Outer] == 5);
259 st[sf4Outer] = STAmount{1};
260 BEAST_EXPECT(st[sf4Outer] == STAmount{1});
261 st[sf4Outer] += STAmount{1};
262 BEAST_EXPECT(st[sf4Outer] == STAmount{2});
263 st[sf1Outer] -= 1;
264 BEAST_EXPECT(st[sf1Outer] == 4);
265 st[sf4Outer] -= STAmount{1};
266 BEAST_EXPECT(st[sf4Outer] == STAmount{1});
267 }
268
269 // Write templated object
270
271 {
272 STObject st(sotOuter, sfGeneric);
273 BEAST_EXPECT(!!st[~sf1Outer]);
274 BEAST_EXPECT(st[~sf1Outer] != std::nullopt);
275 BEAST_EXPECT(st[sf1Outer] == 0);
276 BEAST_EXPECT(*st[~sf1Outer] == 0);
277 BEAST_EXPECT(!st[~sf2Outer]);
278 BEAST_EXPECT(st[~sf2Outer] == std::nullopt);
279 except([&]() { return st[sf2Outer] == 0; });
280 BEAST_EXPECT(!!st[~sf3Outer]);
281 BEAST_EXPECT(st[~sf3Outer] != std::nullopt);
282 BEAST_EXPECT(st[sf3Outer] == 0);
283 except([&]() { st[~sf1Outer] = std::nullopt; });
284 st[sf1Outer] = 1;
285 BEAST_EXPECT(st[sf1Outer] == 1);
286 BEAST_EXPECT(*st[~sf1Outer] == 1);
287 BEAST_EXPECT(!!st[~sf1Outer]);
288 st[sf1Outer] = 0;
289 BEAST_EXPECT(st[sf1Outer] == 0);
290 BEAST_EXPECT(*st[~sf1Outer] == 0);
291 BEAST_EXPECT(!!st[~sf1Outer]);
292 st[sf2Outer] = 2;
293 BEAST_EXPECT(st[sf2Outer] == 2);
294 BEAST_EXPECT(*st[~sf2Outer] == 2);
295 BEAST_EXPECT(!!st[~sf2Outer]);
296 st[~sf2Outer] = std::nullopt;
297 except([&]() { return *st[~sf2Outer]; });
298 BEAST_EXPECT(!st[~sf2Outer]);
299 st[sf3Outer] = 3;
300 BEAST_EXPECT(st[sf3Outer] == 3);
301 BEAST_EXPECT(*st[~sf3Outer] == 3);
302 BEAST_EXPECT(!!st[~sf3Outer]);
303 st[sf3Outer] = 2;
304 BEAST_EXPECT(st[sf3Outer] == 2);
305 BEAST_EXPECT(*st[~sf3Outer] == 2);
306 BEAST_EXPECT(!!st[~sf3Outer]);
307 st[sf3Outer] = 0;
308 BEAST_EXPECT(st[sf3Outer] == 0);
309 BEAST_EXPECT(*st[~sf3Outer] == 0);
310 BEAST_EXPECT(!!st[~sf3Outer]);
311 except([&]() { st[~sf3Outer] = std::nullopt; });
312 BEAST_EXPECT(st[sf3Outer] == 0);
313 BEAST_EXPECT(*st[~sf3Outer] == 0);
314 BEAST_EXPECT(!!st[~sf3Outer]);
315 st[sf1Outer] += 1;
316 BEAST_EXPECT(st[sf1Outer] == 1);
317 st[sf4Outer] = STAmount{1};
318 BEAST_EXPECT(st[sf4Outer] == STAmount{1});
319 st[sf4Outer] += STAmount{1};
320 BEAST_EXPECT(st[sf4Outer] == STAmount{2});
321 st[sf1Outer] -= 1;
322 BEAST_EXPECT(st[sf1Outer] == 0);
323 st[sf4Outer] -= STAmount{1};
324 BEAST_EXPECT(st[sf4Outer] == STAmount{1});
325 }
326
327 // coercion operator to std::optional
328
329 {
331 auto const v = ~st[~sf1Outer];
332 static_assert(
333 std::is_same<std::decay_t<decltype(v)>, std::optional<std::uint32_t>>::value, "");
334 }
335
336 // UDT scalar fields
337
338 {
340 st[sfAmount] = STAmount{};
341 st[sfAccount] = AccountID{};
342 st[sfDigest] = uint256{};
343 [&](STAmount) {}(st[sfAmount]);
344 [&](AccountID) {}(st[sfAccount]);
345 [&](uint256) {}(st[sfDigest]);
346 }
347
348 // STBlob and slice
349
350 {
351 {
353 Buffer b(1);
354 BEAST_EXPECT(!b.empty());
355 st[sf4] = std::move(b);
356 BEAST_EXPECT(b.empty()); // NOLINT(bugprone-use-after-move)
357 BEAST_EXPECT(Slice(st[sf4]).size() == 1);
358 st[~sf4] = std::nullopt;
359 BEAST_EXPECT(!~st[~sf4]);
360 b = Buffer{2};
361 st[sf4] = Slice(b);
362 BEAST_EXPECT(b.size() == 2);
363 BEAST_EXPECT(Slice(st[sf4]).size() == 2);
364 st[sf5] = st[sf4];
365 BEAST_EXPECT(Slice(st[sf4]).size() == 2);
366 BEAST_EXPECT(Slice(st[sf5]).size() == 2);
367 }
368 {
369 STObject st(sotOuter, sfGeneric);
370 BEAST_EXPECT(st[sf5] == Slice{});
371 BEAST_EXPECT(!!st[~sf5]);
372 BEAST_EXPECT(!!~st[~sf5]);
373 Buffer b(1);
374 st[sf5] = std::move(b);
375 BEAST_EXPECT(b.empty()); // NOLINT(bugprone-use-after-move)
376 BEAST_EXPECT(Slice(st[sf5]).size() == 1);
377 st[~sf4] = std::nullopt;
378 BEAST_EXPECT(!~st[~sf4]);
379 }
380 }
381
382 // UDT blobs
383
384 {
386 BEAST_EXPECT(!st[~sf5]);
387 auto const kp = generateKeyPair(KeyType::secp256k1, generateSeed("masterpassphrase"));
388 st[sf5] = kp.first;
389 st[~sf5] = std::nullopt;
390 }
391
392 // By reference fields
393
394 {
395 auto const& sf = sfIndexes;
398 v.emplace_back(1);
399 v.emplace_back(2);
400 st[sf] = v;
401 st[sf] = std::move(v);
402 auto const& cst = st;
403 BEAST_EXPECT(cst[sf].size() == 2);
404 BEAST_EXPECT(cst[~sf]->size() == 2); // NOLINT(bugprone-unchecked-optional-access)
405 BEAST_EXPECT(cst[sf][0] == 1);
406 BEAST_EXPECT(cst[sf][1] == 2);
407 static_assert(
408 std::is_same<decltype(cst[sfIndexes]), std::vector<uint256> const&>::value, "");
409 }
410
411 // Default by reference field
412
413 {
414 auto const& sf1 = sfIndexes;
415 auto const& sf2 = sfHashes;
416 auto const& sf3 = sfAmendments;
417 SOTemplate const sot{
418 {sf1, soeREQUIRED},
419 {sf2, soeOPTIONAL},
420 {sf3, soeDEFAULT},
421 };
422
423 STObject st(sot, sfGeneric);
424 auto const& cst(st);
425 BEAST_EXPECT(cst[sf1].empty());
426 BEAST_EXPECT(!cst[~sf2]);
427 BEAST_EXPECT(cst[sf3].empty());
429 v.emplace_back(1);
430 st[sf1] = v;
431 BEAST_EXPECT(cst[sf1].size() == 1);
432 BEAST_EXPECT(cst[sf1][0] == uint256{1});
433 st[sf2] = v;
434 BEAST_EXPECT(cst[sf2].size() == 1);
435 BEAST_EXPECT(cst[sf2][0] == uint256{1});
436 st[~sf2] = std::nullopt;
437 BEAST_EXPECT(!st[~sf2]);
438 st[sf3] = v;
439 BEAST_EXPECT(cst[sf3].size() == 1);
440 BEAST_EXPECT(cst[sf3][0] == uint256{1});
441 st[sf3] = std::vector<uint256>{};
442 BEAST_EXPECT(cst[sf3].empty());
443 }
444 } // namespace xrpl
445
446 void
448 {
449 testcase("Malformed serialized forms");
450
451 try
452 {
453 std::array<std::uint8_t, 7> const payload{{0xe9, 0x12, 0xab, 0xcd, 0x12, 0xfe, 0xdc}};
454 SerialIter sit{makeSlice(payload)};
455 auto obj = std::make_shared<STArray>(sit, sfMetadata);
456 BEAST_EXPECT(!obj);
457 }
458 catch (std::exception const& e)
459 {
460 BEAST_EXPECT(strcmp(e.what(), "Duplicate field detected") == 0);
461 }
462
463 try
464 {
465 std::array<std::uint8_t, 3> const payload{{0xe2, 0xe1, 0xe2}};
466 SerialIter sit{makeSlice(payload)};
467 auto obj = std::make_shared<STObject>(sit, sfMetadata);
468 BEAST_EXPECT(!obj);
469 }
470 catch (std::exception const& e)
471 {
472 BEAST_EXPECT(strcmp(e.what(), "Duplicate field detected") == 0);
473 }
474 }
475
476 void
477 run() override
478 {
479 // Instantiate a jtx::Env so debugLog writes are exercised.
480 test::jtx::Env const env(*this);
481
482 testFields();
485 }
486};
487
488BEAST_DEFINE_TESTSUITE(STObject, protocol, xrpl);
489
490} // namespace xrpl
T capacity(T... args)
A testsuite class.
Definition suite.h:51
log_os< char > log
Logging output stream.
Definition suite.h:147
void pass()
Record a successful test condition.
Definition suite.h:497
bool unexpected(Condition shouldBeFalse, String const &reason)
Definition suite.h:485
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:150
bool unexcept(F &&f, String const &reason)
Definition suite.h:468
bool except(F &&f, String const &reason)
Definition suite.h:434
void fail(String const &reason, char const *file, int line)
Record a failure.
Definition suite.h:519
Like std::vector<char> but better.
Definition Buffer.h:16
bool empty() const noexcept
Definition Buffer.h:110
std::size_t size() const noexcept
Returns the number of bytes in the buffer.
Definition Buffer.h:104
Identifies fields.
Definition SField.h:126
bool isUseful() const
Definition SField.h:222
static SField const & getField(int fieldCode)
Definition SField.cpp:114
Defines the fields and their attributes within a STObject.
Definition SOTemplate.h:92
void run() override
Runs the suite.
Json::Value getJson(JsonOptions=JsonOptions::none) const override
Definition STObject.cpp:831
Blob getFieldVL(SField const &field) const
Definition STObject.cpp:641
void setFieldV256(SField const &field, STVector256 const &v)
Definition STObject.cpp:765
void setFieldVL(SField const &field, Blob const &)
Definition STObject.cpp:777
void setFieldU32(SField const &field, std::uint32_t)
Definition STObject.cpp:735
void add(Serializer &s) const override
Definition STObject.cpp:119
Serializer getSerializer() const
Definition STObject.h:980
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:456
uint256 getFieldH256(SField const &field) const
Definition STObject.cpp:623
STBase * makeFieldPresent(SField const &field)
Definition STObject.cpp:520
STVector256 const & getFieldV256(SField const &field) const
Definition STObject.cpp:663
void makeFieldAbsent(SField const &field)
Definition STObject.cpp:542
std::uint32_t getFlags() const
Definition STObject.cpp:509
Slice slice() const noexcept
Definition Serializer.h:44
An immutable linear range of bytes.
Definition Slice.h:26
A transaction testing environment.
Definition Env.h:122
T emplace_back(T... args)
T endl(T... args)
T is_same_v
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
@ soeOPTIONAL
Definition SOTemplate.h:17
@ soeDEFAULT
Definition SOTemplate.h:18
@ soeREQUIRED
Definition SOTemplate.h:16
SField const sfGeneric
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:28
Seed generateSeed(std::string const &passPhrase)
Generate a seed deterministically.
Definition Seed.cpp:57
std::pair< PublicKey, SecretKey > generateKeyPair(KeyType type, Seed const &seed)
Generate a key pair deterministically.
base_uint< 256 > uint256
Definition base_uint.h:531
SerializedTypeID
Definition SField.h:90
SField const sfInvalid
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:215
T reserve(T... args)
T what(T... args)