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