xrpld
Loading...
Searching...
No Matches
Buffer_test.cpp
1#include <xrpl/basics/Buffer.h>
2#include <xrpl/basics/Slice.h>
3#include <xrpl/beast/unit_test/suite.h>
4
5#include <cstddef>
6#include <cstdint>
7#include <cstring>
8#include <type_traits>
9#include <utility>
10
11namespace xrpl::test {
12
14{
15 static bool
16 sane(Buffer const& b)
17 {
18 if (b.empty())
19 return b.data() == nullptr;
20
21 return b.data() != nullptr;
22 }
23
24 void
25 run() override
26 {
27 std::uint8_t const data[] = {0xa8, 0xa1, 0x38, 0x45, 0x23, 0xec, 0xe4, 0x23,
28 0x71, 0x6d, 0x2a, 0x18, 0xb4, 0x70, 0xcb, 0xf5,
29 0xac, 0x2d, 0x89, 0x4d, 0x19, 0x9c, 0xf0, 0x2c,
30 0x15, 0xd1, 0xf9, 0x9b, 0x66, 0xd2, 0x30, 0xd3};
31
32 Buffer const b0;
33 BEAST_EXPECT(sane(b0));
34 BEAST_EXPECT(b0.empty());
35
36 Buffer b1{0};
37 BEAST_EXPECT(sane(b1));
38 BEAST_EXPECT(b1.empty());
39 std::memcpy(b1.alloc(16), data, 16);
40 BEAST_EXPECT(sane(b1));
41 BEAST_EXPECT(!b1.empty());
42 BEAST_EXPECT(b1.size() == 16);
43
44 Buffer b2{b1.size()};
45 BEAST_EXPECT(sane(b2));
46 BEAST_EXPECT(!b2.empty());
47 BEAST_EXPECT(b2.size() == b1.size());
48 std::memcpy(b2.data(), data + 16, 16);
49
50 Buffer b3{data, sizeof(data)};
51 BEAST_EXPECT(sane(b3));
52 BEAST_EXPECT(!b3.empty());
53 BEAST_EXPECT(b3.size() == sizeof(data));
54 BEAST_EXPECT(std::memcmp(b3.data(), data, b3.size()) == 0);
55
56 // Check equality and inequality comparisons
57 BEAST_EXPECT(b0 == b0);
58 BEAST_EXPECT(b0 != b1);
59 BEAST_EXPECT(b1 == b1);
60 BEAST_EXPECT(b1 != b2);
61 BEAST_EXPECT(b2 != b3);
62
63 // Check copy constructors and copy assignments:
64 {
65 testcase("Copy Construction / Assignment");
66
67 Buffer x{b0};
68 BEAST_EXPECT(x == b0);
69 BEAST_EXPECT(sane(x));
70 Buffer y{b1};
71 BEAST_EXPECT(y == b1);
72 BEAST_EXPECT(sane(y));
73 x = b2;
74 BEAST_EXPECT(x == b2);
75 BEAST_EXPECT(sane(x));
76 x = y;
77 BEAST_EXPECT(x == y);
78 BEAST_EXPECT(sane(x));
79 y = b3;
80 BEAST_EXPECT(y == b3);
81 BEAST_EXPECT(sane(y));
82 x = b0;
83 BEAST_EXPECT(x == b0);
84 BEAST_EXPECT(sane(x));
85#if defined(__clang__)
86#pragma clang diagnostic push
87#pragma clang diagnostic ignored "-Wself-assign-overloaded"
88#endif
89
90 x = x;
91 BEAST_EXPECT(x == b0);
92 BEAST_EXPECT(sane(x));
93 y = y;
94 BEAST_EXPECT(y == b3);
95 BEAST_EXPECT(sane(y));
96
97#if defined(__clang__)
98#pragma clang diagnostic pop
99#endif
100 }
101
102 // Check move constructor & move assignments:
103 {
104 testcase("Move Construction / Assignment");
105
108
109 { // Move-construct from empty buf
110 Buffer x;
111 Buffer const y{std::move(x)};
112 BEAST_EXPECT(sane(x)); // NOLINT(bugprone-use-after-move)
113 BEAST_EXPECT(x.empty()); // NOLINT(bugprone-use-after-move)
114 BEAST_EXPECT(sane(y));
115 BEAST_EXPECT(y.empty());
116 BEAST_EXPECT(x == y); // NOLINT(bugprone-use-after-move)
117 }
118
119 { // Move-construct from non-empty buf
120 Buffer x{b1};
121 Buffer const y{std::move(x)};
122 BEAST_EXPECT(sane(x)); // NOLINT(bugprone-use-after-move)
123 BEAST_EXPECT(x.empty()); // NOLINT(bugprone-use-after-move)
124 BEAST_EXPECT(sane(y));
125 BEAST_EXPECT(y == b1);
126 }
127
128 { // Move assign empty buf to empty buf
129 Buffer x;
130 Buffer y;
131
132 x = std::move(y);
133 BEAST_EXPECT(sane(x));
134 BEAST_EXPECT(x.empty());
135 BEAST_EXPECT(sane(y)); // NOLINT(bugprone-use-after-move)
136 BEAST_EXPECT(y.empty()); // NOLINT(bugprone-use-after-move)
137 }
138
139 { // Move assign non-empty buf to empty buf
140 Buffer x;
141 Buffer y{b1};
142
143 x = std::move(y);
144 BEAST_EXPECT(sane(x));
145 BEAST_EXPECT(x == b1);
146 BEAST_EXPECT(sane(y)); // NOLINT(bugprone-use-after-move)
147 BEAST_EXPECT(y.empty()); // NOLINT(bugprone-use-after-move)
148 }
149
150 { // Move assign empty buf to non-empty buf
151 Buffer x{b1};
152 Buffer y;
153
154 x = std::move(y);
155 BEAST_EXPECT(sane(x));
156 BEAST_EXPECT(x.empty());
157 BEAST_EXPECT(sane(y)); // NOLINT(bugprone-use-after-move)
158 BEAST_EXPECT(y.empty()); // NOLINT(bugprone-use-after-move)
159 }
160
161 { // Move assign non-empty buf to non-empty buf
162 Buffer x{b1};
163 Buffer y{b2};
164 Buffer z{b3};
165
166 x = std::move(y);
167 BEAST_EXPECT(sane(x));
168 BEAST_EXPECT(!x.empty());
169 BEAST_EXPECT(sane(y)); // NOLINT(bugprone-use-after-move)
170 BEAST_EXPECT(y.empty()); // NOLINT(bugprone-use-after-move)
171
172 x = std::move(z);
173 BEAST_EXPECT(sane(x));
174 BEAST_EXPECT(!x.empty());
175 BEAST_EXPECT(sane(z)); // NOLINT(bugprone-use-after-move)
176 BEAST_EXPECT(z.empty()); // NOLINT(bugprone-use-after-move)
177 }
178 }
179
180 {
181 testcase("Slice Conversion / Construction / Assignment");
182
183 Buffer w{static_cast<Slice>(b0)};
184 BEAST_EXPECT(sane(w));
185 BEAST_EXPECT(w == b0);
186
187 Buffer x{static_cast<Slice>(b1)};
188 BEAST_EXPECT(sane(x));
189 BEAST_EXPECT(x == b1);
190
191 Buffer y{static_cast<Slice>(b2)};
192 BEAST_EXPECT(sane(y));
193 BEAST_EXPECT(y == b2);
194
195 Buffer z{static_cast<Slice>(b3)};
196 BEAST_EXPECT(sane(z));
197 BEAST_EXPECT(z == b3);
198
199 // Assign empty slice to empty buffer
200 w = static_cast<Slice>(b0);
201 BEAST_EXPECT(sane(w));
202 BEAST_EXPECT(w == b0);
203
204 // Assign non-empty slice to empty buffer
205 w = static_cast<Slice>(b1);
206 BEAST_EXPECT(sane(w));
207 BEAST_EXPECT(w == b1);
208
209 // Assign non-empty slice to non-empty buffer
210 x = static_cast<Slice>(b2);
211 BEAST_EXPECT(sane(x));
212 BEAST_EXPECT(x == b2);
213
214 // Assign non-empty slice to non-empty buffer
215 y = static_cast<Slice>(z);
216 BEAST_EXPECT(sane(y));
217 BEAST_EXPECT(y == z);
218
219 // Assign empty slice to non-empty buffer:
220 z = static_cast<Slice>(b0);
221 BEAST_EXPECT(sane(z));
222 BEAST_EXPECT(z == b0);
223 }
224
225 {
226 testcase("Allocation, Deallocation and Clearing");
227
228 auto test = [this](Buffer const& b, std::size_t i) {
229 Buffer x{b};
230
231 // Try to allocate some number of bytes, possibly
232 // zero (which means clear) and sanity check
233 x(i);
234 BEAST_EXPECT(sane(x));
235 BEAST_EXPECT(x.size() == i);
236 BEAST_EXPECT((x.data() == nullptr) == (i == 0));
237
238 // Try to allocate some more data (always non-zero)
239 x(i + 1);
240 BEAST_EXPECT(sane(x));
241 BEAST_EXPECT(x.size() == i + 1);
242 BEAST_EXPECT(x.data() != nullptr);
243
244 // Try to clear:
245 x.clear();
246 BEAST_EXPECT(sane(x));
247 BEAST_EXPECT(x.empty());
248 BEAST_EXPECT(x.data() == nullptr);
249
250 // Try to clear again:
251 x.clear();
252 BEAST_EXPECT(sane(x));
253 BEAST_EXPECT(x.empty());
254 BEAST_EXPECT(x.data() == nullptr);
255 };
256
257 for (std::size_t i = 0; i < 16; ++i)
258 {
259 test(b0, i);
260 test(b1, i);
261 }
262 }
263 }
264};
265
267
268} // namespace xrpl::test
A testsuite class.
Definition suite.h:50
TestcaseT testcase
Memberspace for declaring test cases.
Definition suite.h:149
Like std::vector<char> but better.
Definition Buffer.h:16
bool empty() const noexcept
Definition Buffer.h:111
std::uint8_t * alloc(std::size_t n)
Reallocate the storage.
Definition Buffer.h:155
std::size_t size() const noexcept
Returns the number of bytes in the buffer.
Definition Buffer.h:105
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
Definition Buffer.h:129
void clear() noexcept
Reset the buffer.
Definition Buffer.h:145
An immutable linear range of bytes.
Definition Slice.h:26
T is_nothrow_move_assignable_v
T is_nothrow_move_constructible_v
T memcmp(T... args)
T memcpy(T... args)
BEAST_DEFINE_TESTSUITE(AMMClawback, app, xrpl)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
static bool sane(Buffer const &b)
void run() override
Runs the suite.