xrpld
Toggle main menu visibility
Loading...
Searching...
No Matches
tests
libxrpl
basics
Buffer.cpp
1
#include <xrpl/basics/Buffer.h>
2
3
#include <xrpl/basics/Slice.h>
4
5
#include <gtest/gtest.h>
6
7
#include <
array
>
8
#include <
cstddef
>
9
#include <
cstdint
>
10
#include <
cstring
>
11
#include <
type_traits
>
12
#include <
utility
>
13
14
namespace
xrpl::test
{
15
16
static_assert
(
std::is_nothrow_move_constructible_v<Buffer>
);
17
static_assert
(
std::is_nothrow_move_assignable_v<Buffer>
);
18
19
struct
BufferTest
:
public
::testing::Test
20
{
21
static
constexpr
auto
kRandomData
= std::to_array<std::uint8_t>(
22
{0xa8, 0xa1, 0x38, 0x45, 0x23, 0xec, 0xe4, 0x23, 0x71, 0x6d, 0x2a,
23
0x18, 0xb4, 0x70, 0xcb, 0xf5, 0xac, 0x2d, 0x89, 0x4d, 0x19, 0x9c,
24
0xf0, 0x2c, 0x15, 0xd1, 0xf9, 0x9b, 0x66, 0xd2, 0x30, 0xd3});
25
26
static
constexpr
std::size_t
kHalf
=
kRandomData
.size() / 2;
27
28
static
bool
29
sane
(
Buffer
const
& b)
30
{
31
if
(b.
empty
())
32
return
b.
data
() ==
nullptr
;
33
34
return
b.
data
() !=
nullptr
;
35
}
36
49
static
void
50
checkEmptyAfterMove
(
Buffer
const
& buf)
51
{
52
EXPECT_TRUE(
sane
(buf));
53
EXPECT_TRUE(buf.
empty
());
54
}
55
56
Buffer
const
emptyBuffer
;
57
Buffer
const
firstHalf
{
kRandomData
.data(),
kHalf
};
58
Buffer
const
secondHalf
{
kRandomData
.data() +
kHalf
,
kHalf
};
59
Buffer
const
whole
{
kRandomData
.data(),
kRandomData
.size()};
60
};
61
62
TEST_F
(
BufferTest
, default_constructed_is_empty)
63
{
64
Buffer
const
b;
65
66
EXPECT_TRUE(sane(b));
67
EXPECT_TRUE(b.
empty
());
68
EXPECT_EQ(b.
data
(),
nullptr
);
69
}
70
71
TEST_F
(
BufferTest
, zero_sized_construction_is_empty)
72
{
73
Buffer
const
b{0};
74
75
EXPECT_TRUE(sane(b));
76
EXPECT_TRUE(b.
empty
());
77
}
78
79
TEST_F
(
BufferTest
, alloc_grows_an_empty_buffer)
80
{
81
Buffer
b{0};
82
std::memcpy
(b.
alloc
(kHalf), kRandomData.data(), kHalf);
83
84
EXPECT_TRUE(sane(b));
85
EXPECT_FALSE(b.
empty
());
86
EXPECT_EQ(b.
size
(), kHalf);
87
EXPECT_EQ(b, firstHalf);
88
}
89
90
TEST_F
(
BufferTest
, sized_construction_reserves_without_filling)
91
{
92
Buffer
b{kHalf};
93
94
EXPECT_TRUE(sane(b));
95
EXPECT_FALSE(b.
empty
());
96
EXPECT_EQ(b.
size
(), kHalf);
97
98
std::memcpy
(b.
data
(), kRandomData.data() + kHalf, kHalf);
99
EXPECT_EQ(b, secondHalf);
100
}
101
102
TEST_F
(
BufferTest
, construction_copies_raw_memory)
103
{
104
Buffer
const
b{kRandomData.data(), kRandomData.size()};
105
106
EXPECT_TRUE(sane(b));
107
EXPECT_FALSE(b.
empty
());
108
EXPECT_EQ(b.
size
(), kRandomData.size());
109
EXPECT_EQ(
std::memcmp
(b.
data
(), kRandomData.data(), b.
size
()), 0);
110
}
111
112
TEST_F
(
BufferTest
, equality_compares_contents)
113
{
114
// Uses EXPECT_TRUE rather than EXPECT_EQ/EXPECT_NE because the operators are what is under test
115
// here.
116
EXPECT_TRUE(emptyBuffer == emptyBuffer);
117
EXPECT_TRUE(firstHalf == firstHalf);
118
119
EXPECT_TRUE(emptyBuffer != firstHalf);
120
EXPECT_TRUE(firstHalf != secondHalf);
121
EXPECT_TRUE(secondHalf != whole);
122
}
123
124
TEST_F
(
BufferTest
, copy_construction)
125
{
126
Buffer
const
fromEmpty{emptyBuffer};
127
EXPECT_TRUE(sane(fromEmpty));
128
EXPECT_EQ(fromEmpty, emptyBuffer);
129
130
Buffer
const
fromNonEmpty{firstHalf};
131
EXPECT_TRUE(sane(fromNonEmpty));
132
EXPECT_EQ(fromNonEmpty, firstHalf);
133
}
134
135
TEST_F
(
BufferTest
, copy_assignment)
136
{
137
Buffer
b{emptyBuffer};
138
139
// empty <- non-empty
140
b = secondHalf;
141
EXPECT_TRUE(sane(b));
142
EXPECT_EQ(b, secondHalf);
143
144
// non-empty <- non-empty of a different size
145
b = whole;
146
EXPECT_TRUE(sane(b));
147
EXPECT_EQ(b, whole);
148
149
// non-empty <- empty
150
b = emptyBuffer;
151
EXPECT_TRUE(sane(b));
152
EXPECT_EQ(b, emptyBuffer);
153
}
154
155
TEST_F
(
BufferTest
, self_assignment_preserves_contents)
156
{
157
#ifdef __clang__
158
#pragma clang diagnostic push
159
#pragma clang diagnostic ignored "-Wself-assign-overloaded"
160
#endif
161
162
Buffer
emptyCopy{emptyBuffer};
163
emptyCopy = emptyCopy;
164
EXPECT_TRUE(sane(emptyCopy));
165
EXPECT_EQ(emptyCopy, emptyBuffer);
166
167
Buffer
wholeCopy{whole};
168
wholeCopy = wholeCopy;
169
EXPECT_TRUE(sane(wholeCopy));
170
EXPECT_EQ(wholeCopy, whole);
171
172
#ifdef __clang__
173
#pragma clang diagnostic pop
174
#endif
175
}
176
177
TEST_F
(
BufferTest
, move_construct_from_empty)
178
{
179
Buffer
source;
180
Buffer
const
moved{std::move(source)};
181
182
checkEmptyAfterMove(source);
// NOLINT(bugprone-use-after-move)
183
EXPECT_TRUE(sane(moved));
184
EXPECT_TRUE(moved.
empty
());
185
}
186
187
TEST_F
(
BufferTest
, move_construct_from_non_empty)
188
{
189
Buffer
source{firstHalf};
190
Buffer
const
moved{std::move(source)};
191
192
checkEmptyAfterMove(source);
// NOLINT(bugprone-use-after-move)
193
EXPECT_TRUE(sane(moved));
194
EXPECT_EQ(moved, firstHalf);
195
}
196
197
TEST_F
(
BufferTest
, move_assign_empty_to_empty)
198
{
199
Buffer
target;
200
Buffer
source;
201
202
target = std::move(source);
203
204
EXPECT_TRUE(sane(target));
205
EXPECT_TRUE(target.
empty
());
206
checkEmptyAfterMove(source);
// NOLINT(bugprone-use-after-move)
207
}
208
209
TEST_F
(
BufferTest
, move_assign_non_empty_to_empty)
210
{
211
Buffer
target;
212
Buffer
source{firstHalf};
213
214
target = std::move(source);
215
216
EXPECT_TRUE(sane(target));
217
EXPECT_EQ(target, firstHalf);
218
checkEmptyAfterMove(source);
// NOLINT(bugprone-use-after-move)
219
}
220
221
TEST_F
(
BufferTest
, move_assign_empty_to_non_empty)
222
{
223
Buffer
target{firstHalf};
224
Buffer
source;
225
226
target = std::move(source);
227
228
EXPECT_TRUE(sane(target));
229
EXPECT_TRUE(target.
empty
());
230
checkEmptyAfterMove(source);
// NOLINT(bugprone-use-after-move)
231
}
232
233
TEST_F
(
BufferTest
, move_assign_non_empty_to_non_empty)
234
{
235
Buffer
target{firstHalf};
236
Buffer
sameSize{secondHalf};
237
Buffer
largerSize{whole};
238
239
target = std::move(sameSize);
240
EXPECT_TRUE(sane(target));
241
EXPECT_EQ(target, secondHalf);
242
checkEmptyAfterMove(sameSize);
// NOLINT(bugprone-use-after-move)
243
244
target = std::move(largerSize);
245
EXPECT_TRUE(sane(target));
246
EXPECT_EQ(target, whole);
247
checkEmptyAfterMove(largerSize);
// NOLINT(bugprone-use-after-move)
248
}
249
250
TEST_F
(
BufferTest
, construction_from_slice)
251
{
252
Buffer
const
fromEmpty{
static_cast<
Slice
>
(emptyBuffer)};
253
EXPECT_TRUE(sane(fromEmpty));
254
EXPECT_EQ(fromEmpty, emptyBuffer);
255
256
Buffer
const
fromNonEmpty{
static_cast<
Slice
>
(whole)};
257
EXPECT_TRUE(sane(fromNonEmpty));
258
EXPECT_EQ(fromNonEmpty, whole);
259
}
260
261
TEST_F
(
BufferTest
, assignment_from_slice)
262
{
263
Buffer
b;
264
265
// empty <- empty slice
266
b =
static_cast<
Slice
>
(emptyBuffer);
267
EXPECT_TRUE(sane(b));
268
EXPECT_EQ(b, emptyBuffer);
269
270
// empty <- non-empty slice
271
b =
static_cast<
Slice
>
(firstHalf);
272
EXPECT_TRUE(sane(b));
273
EXPECT_EQ(b, firstHalf);
274
275
// non-empty <- non-empty slice
276
b =
static_cast<
Slice
>
(secondHalf);
277
EXPECT_TRUE(sane(b));
278
EXPECT_EQ(b, secondHalf);
279
280
// non-empty <- empty slice
281
b =
static_cast<
Slice
>
(emptyBuffer);
282
EXPECT_TRUE(sane(b));
283
EXPECT_EQ(b, emptyBuffer);
284
}
285
286
TEST_F
(
BufferTest
, resize_allocates_and_clear_releases)
287
{
288
auto
check
= [](
Buffer
const
& original,
std::size_t
size) {
289
SCOPED_TRACE(::testing::Message() <<
"size: "
<< size);
290
291
Buffer
b{original};
292
293
// Resizing to zero is equivalent to clearing.
294
b(size);
295
EXPECT_TRUE(sane(b));
296
EXPECT_EQ(b.
size
(), size);
297
EXPECT_EQ(b.
data
() ==
nullptr
, size == 0);
298
299
b(size + 1);
300
EXPECT_TRUE(sane(b));
301
EXPECT_EQ(b.
size
(), size + 1);
302
EXPECT_NE(b.
data
(),
nullptr
);
303
304
b.
clear
();
305
EXPECT_TRUE(sane(b));
306
EXPECT_TRUE(b.
empty
());
307
EXPECT_EQ(b.
data
(),
nullptr
);
308
309
// clear() is idempotent.
310
b.
clear
();
311
EXPECT_TRUE(sane(b));
312
EXPECT_TRUE(b.
empty
());
313
EXPECT_EQ(b.
data
(),
nullptr
);
314
};
315
316
for
(
auto
size = 0uz; size < kHalf; ++size)
317
{
318
check
(emptyBuffer, size);
319
check
(firstHalf, size);
320
}
321
}
322
323
TEST_F
(
BufferTest
, fill_sets_every_byte)
324
{
325
Buffer
b{4};
326
b.
fill
(0xab);
327
328
EXPECT_EQ(b.
size
(), 4);
329
for
(
auto
const
byte
:
Slice
{b})
330
EXPECT_EQ(
byte
, 0xab);
331
}
332
333
TEST_F
(
BufferTest
, fill_overwrites_and_keeps_size)
334
{
335
Buffer
b{4};
336
b.
fill
(0xab);
337
b.
fill
(0x00);
338
339
EXPECT_EQ(b.
size
(), 4);
340
for
(
auto
const
byte
:
Slice
{b})
341
EXPECT_EQ(
byte
, 0x00);
342
}
343
344
TEST_F
(
BufferTest
, fill_on_empty_buffer_is_a_noop)
345
{
346
Buffer
empty;
347
empty.fill(0xff);
348
349
EXPECT_TRUE(empty.empty());
350
EXPECT_EQ(empty.data(),
nullptr
);
351
}
352
353
}
// namespace xrpl::test
array
xrpl::Buffer
Like std::vector<char> but better.
Definition
Buffer.h:19
xrpl::Buffer::empty
bool empty() const noexcept
Definition
Buffer.h:129
xrpl::Buffer::alloc
std::uint8_t * alloc(std::size_t n)
Reallocate the storage.
Definition
Buffer.h:189
xrpl::Buffer::size
std::size_t size() const noexcept
Returns the number of bytes in the buffer.
Definition
Buffer.h:123
xrpl::Buffer::data
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
Definition
Buffer.h:148
xrpl::Buffer::clear
void clear() noexcept
Reset the buffer.
Definition
Buffer.h:178
xrpl::Buffer::fill
void fill(std::uint8_t value) noexcept
Set every byte in the buffer to the given value.
Definition
Buffer.h:168
xrpl::Slice
An immutable linear range of bytes.
Definition
Slice.h:28
cstddef
cstdint
cstring
std::is_nothrow_move_assignable_v
T is_nothrow_move_assignable_v
std::is_nothrow_move_constructible_v
T is_nothrow_move_constructible_v
std::memcmp
T memcmp(T... args)
std::memcpy
T memcpy(T... args)
xrpl::test::jtx::check
Check operations.
Definition
check.h:18
xrpl::test
Definition
STLedgerEntry.h:21
xrpl::test::TEST_F
TEST_F(BaseUintDeathTest, from_raw_size_mismatch)
Definition
base_uint.cpp:131
std::size_t
xrpl::test::BufferTest
Definition
Buffer.cpp:20
xrpl::test::BufferTest::sane
static bool sane(Buffer const &b)
Definition
Buffer.cpp:29
xrpl::test::BufferTest::firstHalf
Buffer const firstHalf
Definition
Buffer.cpp:57
xrpl::test::BufferTest::checkEmptyAfterMove
static void checkEmptyAfterMove(Buffer const &buf)
Check the state Buffer documents for a moved-from buffer: "the other buffer is reset",...
Definition
Buffer.cpp:50
xrpl::test::BufferTest::whole
Buffer const whole
Definition
Buffer.cpp:59
xrpl::test::BufferTest::emptyBuffer
Buffer const emptyBuffer
Definition
Buffer.cpp:56
xrpl::test::BufferTest::kHalf
static constexpr std::size_t kHalf
Definition
Buffer.cpp:26
xrpl::test::BufferTest::secondHalf
Buffer const secondHalf
Definition
Buffer.cpp:58
xrpl::test::BufferTest::kRandomData
static constexpr auto kRandomData
Definition
Buffer.cpp:21
type_traits
utility
Generated by
1.17.0