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