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