Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/common-tests/binary_reader_writer_tests.cpp
7197 views
1
// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin <[email protected]>
2
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
3
4
#include "common/binary_reader_writer.h"
5
#include "common/small_string.h"
6
7
#include <array>
8
#include <cstring>
9
#include <gtest/gtest.h>
10
#include <optional>
11
#include <string>
12
#include <string_view>
13
14
using namespace std::string_view_literals;
15
16
//////////////////////////////////////////////////////////////////////////
17
// Global test data
18
//////////////////////////////////////////////////////////////////////////
19
20
// Buffer with various primitive types
21
alignas(8) static constexpr std::array<u8, 32> g_primitive_buffer = {{
22
0x01, // u8: 1
23
0xFE, // s8: -2
24
0x34, 0x12, // u16: 0x1234 (little endian)
25
0xCD, 0xAB, // s16: -0x5433 (little endian)
26
0x78, 0x56, 0x34, 0x12, // u32: 0x12345678
27
0x88, 0xA9, 0xCB, 0xED, // s32: -0x12345678
28
0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01, // u64: 0x0123456789ABCDEF
29
0x00, 0x00, 0x80, 0x3F, // float: 1.0f
30
0x00, 0x00, 0x00, 0x00 // padding
31
}};
32
33
// Buffer with C-strings (null-terminated)
34
static constexpr std::array<u8, 16> g_cstring_buffer = {{
35
'H', 'e', 'l', 'l', 'o', '\0', // "Hello"
36
'W', 'o', 'r', 'l', 'd', '\0', // "World"
37
'\0', // empty string
38
'A', 'B', 'C' // "ABC" without null terminator (truncated)
39
}};
40
41
// Buffer with size-prefixed strings (u32 length + data)
42
static constexpr std::array<u8, 25> g_size_prefixed_buffer = {
43
0x05, 0x00, 0x00, 0x00, // length: 5
44
'H', 'e', 'l', 'l', 'o', // "Hello"
45
0x00, 0x00, 0x00, 0x00, // length: 0 (empty string)
46
0x04, 0x00, 0x00, 0x00, // length: 4
47
'T', 'e', 's', 't', // "Test"
48
0xFF, 0xFF, 0xFF, 0xFF // invalid length (overflow)
49
};
50
51
//////////////////////////////////////////////////////////////////////////
52
// BinarySpanReader Tests
53
//////////////////////////////////////////////////////////////////////////
54
55
TEST(BinarySpanReader, DefaultConstructor)
56
{
57
BinarySpanReader reader;
58
EXPECT_FALSE(reader.IsValid());
59
EXPECT_EQ(reader.GetBufferRemaining(), 0u);
60
EXPECT_EQ(reader.GetBufferConsumed(), 0u);
61
}
62
63
TEST(BinarySpanReader, SpanConstructor)
64
{
65
BinarySpanReader reader(g_primitive_buffer);
66
EXPECT_TRUE(reader.IsValid());
67
EXPECT_EQ(reader.GetBufferRemaining(), g_primitive_buffer.size());
68
EXPECT_EQ(reader.GetBufferConsumed(), 0u);
69
}
70
71
TEST(BinarySpanReader, MoveConstructor)
72
{
73
BinarySpanReader original(g_primitive_buffer);
74
original.ReadU8();
75
original.ReadU8();
76
77
BinarySpanReader moved(std::move(original));
78
EXPECT_TRUE(moved.IsValid());
79
EXPECT_EQ(moved.GetBufferConsumed(), 2u);
80
EXPECT_EQ(original.GetBufferConsumed(), 0u);
81
}
82
83
TEST(BinarySpanReader, MoveAssignment)
84
{
85
BinarySpanReader original(g_primitive_buffer);
86
original.ReadU8();
87
88
BinarySpanReader moved;
89
moved = std::move(original);
90
EXPECT_TRUE(moved.IsValid());
91
EXPECT_EQ(moved.GetBufferConsumed(), 1u);
92
EXPECT_EQ(original.GetBufferConsumed(), 0u);
93
}
94
95
TEST(BinarySpanReader, GetSpan)
96
{
97
BinarySpanReader reader(g_primitive_buffer);
98
auto span = reader.GetSpan();
99
EXPECT_EQ(span.size(), g_primitive_buffer.size());
100
EXPECT_EQ(span.data(), g_primitive_buffer.data());
101
}
102
103
TEST(BinarySpanReader, CheckRemaining)
104
{
105
BinarySpanReader reader(g_primitive_buffer);
106
EXPECT_TRUE(reader.CheckRemaining(g_primitive_buffer.size()));
107
EXPECT_TRUE(reader.CheckRemaining(1));
108
EXPECT_FALSE(reader.CheckRemaining(g_primitive_buffer.size() + 1));
109
}
110
111
TEST(BinarySpanReader, ReadU8)
112
{
113
BinarySpanReader reader(g_primitive_buffer);
114
u8 val;
115
EXPECT_TRUE(reader.ReadU8(&val));
116
EXPECT_EQ(val, 0x01u);
117
EXPECT_EQ(reader.GetBufferConsumed(), 1u);
118
}
119
120
TEST(BinarySpanReader, ReadS8)
121
{
122
BinarySpanReader reader(g_primitive_buffer);
123
reader.IncrementPosition(1);
124
s8 val;
125
EXPECT_TRUE(reader.ReadS8(&val));
126
EXPECT_EQ(val, static_cast<s8>(0xFE));
127
EXPECT_EQ(reader.GetBufferConsumed(), 2u);
128
}
129
130
TEST(BinarySpanReader, ReadU16)
131
{
132
BinarySpanReader reader(g_primitive_buffer);
133
reader.IncrementPosition(2);
134
u16 val;
135
EXPECT_TRUE(reader.ReadU16(&val));
136
EXPECT_EQ(val, 0x1234u);
137
}
138
139
TEST(BinarySpanReader, ReadS16)
140
{
141
BinarySpanReader reader(g_primitive_buffer);
142
reader.IncrementPosition(4);
143
s16 val;
144
EXPECT_TRUE(reader.ReadS16(&val));
145
EXPECT_EQ(val, static_cast<s16>(0xABCD));
146
}
147
148
TEST(BinarySpanReader, ReadU32)
149
{
150
BinarySpanReader reader(g_primitive_buffer);
151
reader.IncrementPosition(6);
152
u32 val;
153
EXPECT_TRUE(reader.ReadU32(&val));
154
EXPECT_EQ(val, 0x12345678u);
155
}
156
157
TEST(BinarySpanReader, ReadS32)
158
{
159
BinarySpanReader reader(g_primitive_buffer);
160
reader.IncrementPosition(10);
161
s32 val;
162
EXPECT_TRUE(reader.ReadS32(&val));
163
EXPECT_EQ(val, static_cast<s32>(0xEDCBA988));
164
}
165
166
TEST(BinarySpanReader, ReadU64)
167
{
168
BinarySpanReader reader(g_primitive_buffer);
169
reader.IncrementPosition(14);
170
u64 val;
171
EXPECT_TRUE(reader.ReadU64(&val));
172
EXPECT_EQ(val, 0x0123456789ABCDEFull);
173
}
174
175
TEST(BinarySpanReader, ReadFloat)
176
{
177
BinarySpanReader reader(g_primitive_buffer);
178
reader.IncrementPosition(22);
179
float val;
180
EXPECT_TRUE(reader.ReadFloat(&val));
181
EXPECT_FLOAT_EQ(val, 1.0f);
182
}
183
184
TEST(BinarySpanReader, ReadBool)
185
{
186
std::array<u8, 2> buf = {0x00, 0x01};
187
BinarySpanReader reader(buf);
188
bool val;
189
EXPECT_TRUE(reader.ReadBool(&val));
190
EXPECT_FALSE(val);
191
EXPECT_TRUE(reader.ReadBool(&val));
192
EXPECT_TRUE(val);
193
}
194
195
TEST(BinarySpanReader, ReadTReturningValue)
196
{
197
BinarySpanReader reader(g_primitive_buffer);
198
EXPECT_EQ(reader.ReadU8(), 0x01u);
199
EXPECT_EQ(reader.ReadS8(), static_cast<s8>(0xFE));
200
EXPECT_EQ(reader.ReadU16(), 0x1234u);
201
EXPECT_EQ(reader.ReadS16(), static_cast<s16>(0xABCD));
202
EXPECT_EQ(reader.ReadU32(), 0x12345678u);
203
EXPECT_EQ(reader.ReadS32(), static_cast<s32>(0xEDCBA988));
204
EXPECT_EQ(reader.ReadU64(), 0x0123456789ABCDEFull);
205
EXPECT_FLOAT_EQ(reader.ReadFloat(), 1.0f);
206
}
207
208
TEST(BinarySpanReader, ReadBoolReturningValue)
209
{
210
std::array<u8, 3> buf = {0x00, 0x01, 0xFF};
211
BinarySpanReader reader(buf);
212
EXPECT_FALSE(reader.ReadBool());
213
EXPECT_TRUE(reader.ReadBool());
214
EXPECT_TRUE(reader.ReadBool()); // any non-zero is true
215
}
216
217
TEST(BinarySpanReader, ReadCStringToString)
218
{
219
BinarySpanReader reader(g_cstring_buffer);
220
std::string val;
221
EXPECT_TRUE(reader.ReadCString(&val));
222
EXPECT_EQ(val, "Hello");
223
EXPECT_EQ(reader.GetBufferConsumed(), 6u);
224
}
225
226
TEST(BinarySpanReader, ReadCStringToStringView)
227
{
228
BinarySpanReader reader(g_cstring_buffer);
229
std::string_view val;
230
EXPECT_TRUE(reader.ReadCString(&val));
231
EXPECT_EQ(val, "Hello"sv);
232
}
233
234
TEST(BinarySpanReader, ReadCStringToSmallString)
235
{
236
BinarySpanReader reader(g_cstring_buffer);
237
SmallString val;
238
EXPECT_TRUE(reader.ReadCString(&val));
239
EXPECT_STREQ(val.c_str(), "Hello");
240
}
241
242
TEST(BinarySpanReader, ReadCStringReturningValue)
243
{
244
BinarySpanReader reader(g_cstring_buffer);
245
EXPECT_EQ(reader.ReadCString(), "Hello"sv);
246
EXPECT_EQ(reader.ReadCString(), "World"sv);
247
EXPECT_EQ(reader.ReadCString(), ""sv);
248
}
249
250
TEST(BinarySpanReader, ReadCStringWithoutNullTerminator)
251
{
252
// Buffer ending without null terminator
253
std::array<u8, 3> buf = {'A', 'B', 'C'};
254
BinarySpanReader reader(buf);
255
std::string val;
256
EXPECT_FALSE(reader.ReadCString(&val));
257
}
258
259
TEST(BinarySpanReader, ReadSizePrefixedStringToString)
260
{
261
BinarySpanReader reader(g_size_prefixed_buffer);
262
std::string val;
263
EXPECT_TRUE(reader.ReadSizePrefixedString(&val));
264
EXPECT_EQ(val, "Hello");
265
EXPECT_EQ(reader.GetBufferConsumed(), 9u);
266
}
267
268
TEST(BinarySpanReader, ReadSizePrefixedStringToStringView)
269
{
270
BinarySpanReader reader(g_size_prefixed_buffer);
271
std::string_view val;
272
EXPECT_TRUE(reader.ReadSizePrefixedString(&val));
273
EXPECT_EQ(val, "Hello"sv);
274
}
275
276
TEST(BinarySpanReader, ReadSizePrefixedStringToSmallString)
277
{
278
BinarySpanReader reader(g_size_prefixed_buffer);
279
SmallString val;
280
EXPECT_TRUE(reader.ReadSizePrefixedString(&val));
281
EXPECT_STREQ(val.c_str(), "Hello");
282
}
283
284
TEST(BinarySpanReader, ReadSizePrefixedStringReturningValue)
285
{
286
BinarySpanReader reader(g_size_prefixed_buffer);
287
EXPECT_EQ(reader.ReadSizePrefixedString(), "Hello"sv);
288
EXPECT_EQ(reader.ReadSizePrefixedString(), ""sv);
289
EXPECT_EQ(reader.ReadSizePrefixedString(), "Test"sv);
290
}
291
292
TEST(BinarySpanReader, ReadSizePrefixedStringEmpty)
293
{
294
BinarySpanReader reader(g_size_prefixed_buffer);
295
reader.IncrementPosition(9);
296
std::string val;
297
EXPECT_TRUE(reader.ReadSizePrefixedString(&val));
298
EXPECT_TRUE(val.empty());
299
}
300
301
TEST(BinarySpanReader, PeekU8)
302
{
303
BinarySpanReader reader(g_primitive_buffer);
304
u8 val;
305
EXPECT_TRUE(reader.PeekU8(&val));
306
EXPECT_EQ(val, 0x01u);
307
EXPECT_EQ(reader.GetBufferConsumed(), 0u); // position unchanged
308
}
309
310
TEST(BinarySpanReader, PeekU16)
311
{
312
BinarySpanReader reader(g_primitive_buffer);
313
reader.IncrementPosition(2);
314
u16 val;
315
EXPECT_TRUE(reader.PeekU16(&val));
316
EXPECT_EQ(val, 0x1234u);
317
EXPECT_EQ(reader.GetBufferConsumed(), 2u); // position unchanged after peek
318
}
319
320
TEST(BinarySpanReader, PeekU32)
321
{
322
BinarySpanReader reader(g_primitive_buffer);
323
reader.IncrementPosition(6);
324
u32 val;
325
EXPECT_TRUE(reader.PeekU32(&val));
326
EXPECT_EQ(val, 0x12345678u);
327
EXPECT_EQ(reader.GetBufferConsumed(), 6u);
328
}
329
330
TEST(BinarySpanReader, PeekU64)
331
{
332
BinarySpanReader reader(g_primitive_buffer);
333
reader.IncrementPosition(14);
334
u64 val;
335
EXPECT_TRUE(reader.PeekU64(&val));
336
EXPECT_EQ(val, 0x0123456789ABCDEFull);
337
EXPECT_EQ(reader.GetBufferConsumed(), 14u);
338
}
339
340
TEST(BinarySpanReader, PeekFloat)
341
{
342
BinarySpanReader reader(g_primitive_buffer);
343
reader.IncrementPosition(22);
344
float val;
345
EXPECT_TRUE(reader.PeekFloat(&val));
346
EXPECT_FLOAT_EQ(val, 1.0f);
347
EXPECT_EQ(reader.GetBufferConsumed(), 22u);
348
}
349
350
TEST(BinarySpanReader, PeekBool)
351
{
352
std::array<u8, 2> buf = {0x00, 0x01};
353
BinarySpanReader reader(buf);
354
bool val;
355
EXPECT_TRUE(reader.PeekBool(&val));
356
EXPECT_FALSE(val);
357
EXPECT_EQ(reader.GetBufferConsumed(), 0u);
358
}
359
360
TEST(BinarySpanReader, PeekCString)
361
{
362
BinarySpanReader reader(g_cstring_buffer);
363
std::string_view val;
364
EXPECT_TRUE(reader.PeekCString(&val));
365
EXPECT_EQ(val, "Hello"sv);
366
EXPECT_EQ(reader.GetBufferConsumed(), 0u); // position unchanged
367
}
368
369
TEST(BinarySpanReader, PeekSizePrefixedString)
370
{
371
BinarySpanReader reader(g_size_prefixed_buffer);
372
std::string_view val;
373
EXPECT_TRUE(reader.PeekSizePrefixedString(&val));
374
EXPECT_EQ(val, "Hello"sv);
375
EXPECT_EQ(reader.GetBufferConsumed(), 0u); // position unchanged
376
}
377
378
TEST(BinarySpanReader, StreamOperators)
379
{
380
BinarySpanReader reader(g_primitive_buffer);
381
u8 u8val;
382
s8 s8val;
383
u16 u16val;
384
s16 s16val;
385
u32 u32val;
386
s32 s32val;
387
u64 u64val;
388
float fval;
389
390
reader >> u8val >> s8val >> u16val >> s16val >> u32val >> s32val >> u64val >> fval;
391
392
EXPECT_EQ(u8val, 0x01u);
393
EXPECT_EQ(s8val, static_cast<s8>(0xFE));
394
EXPECT_EQ(u16val, 0x1234u);
395
EXPECT_EQ(s16val, static_cast<s16>(0xABCD));
396
EXPECT_EQ(u32val, 0x12345678u);
397
EXPECT_EQ(s32val, static_cast<s32>(0xEDCBA988));
398
EXPECT_EQ(u64val, 0x0123456789ABCDEFull);
399
EXPECT_FLOAT_EQ(fval, 1.0f);
400
}
401
402
TEST(BinarySpanReader, StreamOperatorCString)
403
{
404
BinarySpanReader reader(g_cstring_buffer);
405
std::string_view val;
406
reader >> val;
407
EXPECT_EQ(val, "Hello"sv);
408
}
409
410
TEST(BinarySpanReader, ReadOptionalTWithValue)
411
{
412
std::array<u8, 5> buf = {0x01, 0x78, 0x56, 0x34, 0x12}; // has_value=true, value=0x12345678
413
BinarySpanReader reader(buf);
414
std::optional<u32> val;
415
EXPECT_TRUE(reader.ReadOptionalT(&val));
416
EXPECT_TRUE(val.has_value());
417
EXPECT_EQ(val.value(), 0x12345678u);
418
}
419
420
TEST(BinarySpanReader, ReadOptionalTWithoutValue)
421
{
422
std::array<u8, 5> buf = {0x00, 0x00, 0x00, 0x00, 0x00}; // has_value=false
423
BinarySpanReader reader(buf);
424
std::optional<u32> val = 123u; // preset to non-empty
425
EXPECT_TRUE(reader.ReadOptionalT(&val));
426
EXPECT_FALSE(val.has_value());
427
}
428
429
TEST(BinarySpanReader, GetRemainingSpan)
430
{
431
BinarySpanReader reader(g_primitive_buffer);
432
reader.IncrementPosition(10);
433
auto remaining = reader.GetRemainingSpan();
434
EXPECT_EQ(remaining.size(), g_primitive_buffer.size() - 10);
435
}
436
437
TEST(BinarySpanReader, GetRemainingSpanWithSize)
438
{
439
BinarySpanReader reader(g_primitive_buffer);
440
reader.IncrementPosition(10);
441
auto remaining = reader.GetRemainingSpan(5);
442
EXPECT_EQ(remaining.size(), 5u);
443
}
444
445
TEST(BinarySpanReader, ReadBeyondBuffer)
446
{
447
std::array<u8, 2> buf = {0x01, 0x02};
448
BinarySpanReader reader(buf);
449
u32 val;
450
EXPECT_FALSE(reader.ReadU32(&val));
451
}
452
453
TEST(BinarySpanReader, PeekBeyondBuffer)
454
{
455
std::array<u8, 2> buf = {0x01, 0x02};
456
BinarySpanReader reader(buf);
457
u32 val;
458
EXPECT_FALSE(reader.PeekU32(&val));
459
}
460
461
//////////////////////////////////////////////////////////////////////////
462
// BinarySpanWriter Tests
463
//////////////////////////////////////////////////////////////////////////
464
465
TEST(BinarySpanWriter, DefaultConstructor)
466
{
467
BinarySpanWriter writer;
468
EXPECT_FALSE(writer.IsValid());
469
EXPECT_EQ(writer.GetBufferRemaining(), 0u);
470
EXPECT_EQ(writer.GetBufferWritten(), 0u);
471
}
472
473
TEST(BinarySpanWriter, SpanConstructor)
474
{
475
std::array<u8, 32> buf = {};
476
BinarySpanWriter writer(buf);
477
EXPECT_TRUE(writer.IsValid());
478
EXPECT_EQ(writer.GetBufferRemaining(), buf.size());
479
EXPECT_EQ(writer.GetBufferWritten(), 0u);
480
}
481
482
TEST(BinarySpanWriter, MoveConstructor)
483
{
484
std::array<u8, 32> buf = {};
485
BinarySpanWriter original(buf);
486
original.WriteU8(0x01);
487
original.WriteU8(0x02);
488
489
BinarySpanWriter moved(std::move(original));
490
EXPECT_TRUE(moved.IsValid());
491
EXPECT_EQ(moved.GetBufferWritten(), 2u);
492
EXPECT_EQ(original.GetBufferWritten(), 0u);
493
}
494
495
TEST(BinarySpanWriter, MoveAssignment)
496
{
497
std::array<u8, 32> buf = {};
498
BinarySpanWriter original(buf);
499
original.WriteU8(0x01);
500
501
BinarySpanWriter moved;
502
moved = std::move(original);
503
EXPECT_TRUE(moved.IsValid());
504
EXPECT_EQ(moved.GetBufferWritten(), 1u);
505
EXPECT_EQ(original.GetBufferWritten(), 0u);
506
}
507
508
TEST(BinarySpanWriter, GetSpan)
509
{
510
std::array<u8, 32> buf = {};
511
BinarySpanWriter writer(buf);
512
auto span = writer.GetSpan();
513
EXPECT_EQ(span.size(), buf.size());
514
EXPECT_EQ(span.data(), buf.data());
515
}
516
517
TEST(BinarySpanWriter, WriteU8)
518
{
519
std::array<u8, 4> buf = {};
520
BinarySpanWriter writer(buf);
521
EXPECT_TRUE(writer.WriteU8(0xAB));
522
EXPECT_EQ(buf[0], 0xABu);
523
EXPECT_EQ(writer.GetBufferWritten(), 1u);
524
}
525
526
TEST(BinarySpanWriter, WriteS8)
527
{
528
std::array<u8, 4> buf = {};
529
BinarySpanWriter writer(buf);
530
EXPECT_TRUE(writer.WriteS8(-5));
531
EXPECT_EQ(static_cast<s8>(buf[0]), -5);
532
}
533
534
TEST(BinarySpanWriter, WriteU16)
535
{
536
std::array<u8, 4> buf = {};
537
BinarySpanWriter writer(buf);
538
EXPECT_TRUE(writer.WriteU16(0x1234));
539
EXPECT_EQ(buf[0], 0x34u);
540
EXPECT_EQ(buf[1], 0x12u);
541
}
542
543
TEST(BinarySpanWriter, WriteS16)
544
{
545
std::array<u8, 4> buf = {};
546
BinarySpanWriter writer(buf);
547
EXPECT_TRUE(writer.WriteS16(-1000));
548
s16 val;
549
std::memcpy(&val, buf.data(), sizeof(val));
550
EXPECT_EQ(val, -1000);
551
}
552
553
TEST(BinarySpanWriter, WriteU32)
554
{
555
std::array<u8, 4> buf = {};
556
BinarySpanWriter writer(buf);
557
EXPECT_TRUE(writer.WriteU32(0x12345678));
558
EXPECT_EQ(buf[0], 0x78u);
559
EXPECT_EQ(buf[1], 0x56u);
560
EXPECT_EQ(buf[2], 0x34u);
561
EXPECT_EQ(buf[3], 0x12u);
562
}
563
564
TEST(BinarySpanWriter, WriteS32)
565
{
566
std::array<u8, 4> buf = {};
567
BinarySpanWriter writer(buf);
568
EXPECT_TRUE(writer.WriteS32(-123456789));
569
s32 val;
570
std::memcpy(&val, buf.data(), sizeof(val));
571
EXPECT_EQ(val, -123456789);
572
}
573
574
TEST(BinarySpanWriter, WriteU64)
575
{
576
std::array<u8, 8> buf = {};
577
BinarySpanWriter writer(buf);
578
EXPECT_TRUE(writer.WriteU64(0x0123456789ABCDEFull));
579
EXPECT_EQ(buf[0], 0xEFu);
580
EXPECT_EQ(buf[7], 0x01u);
581
}
582
583
TEST(BinarySpanWriter, WriteS64)
584
{
585
std::array<u8, 8> buf = {};
586
BinarySpanWriter writer(buf);
587
EXPECT_TRUE(writer.WriteS64(-1234567890123456789ll));
588
s64 val;
589
std::memcpy(&val, buf.data(), sizeof(val));
590
EXPECT_EQ(val, -1234567890123456789ll);
591
}
592
593
TEST(BinarySpanWriter, WriteFloat)
594
{
595
std::array<u8, 4> buf = {};
596
BinarySpanWriter writer(buf);
597
EXPECT_TRUE(writer.WriteFloat(1.0f));
598
float val;
599
std::memcpy(&val, buf.data(), sizeof(val));
600
EXPECT_FLOAT_EQ(val, 1.0f);
601
}
602
603
TEST(BinarySpanWriter, WriteBool)
604
{
605
std::array<u8, 2> buf = {};
606
BinarySpanWriter writer(buf);
607
EXPECT_TRUE(writer.WriteBool(false));
608
EXPECT_TRUE(writer.WriteBool(true));
609
EXPECT_EQ(buf[0], 0x00u);
610
EXPECT_EQ(buf[1], 0x01u);
611
}
612
613
TEST(BinarySpanWriter, WriteCString)
614
{
615
std::array<u8, 16> buf = {};
616
BinarySpanWriter writer(buf);
617
EXPECT_TRUE(writer.WriteCString("Hello"));
618
EXPECT_EQ(buf[0], 'H');
619
EXPECT_EQ(buf[4], 'o');
620
EXPECT_EQ(buf[5], '\0');
621
EXPECT_EQ(writer.GetBufferWritten(), 6u);
622
}
623
624
TEST(BinarySpanWriter, WriteCStringEmpty)
625
{
626
std::array<u8, 16> buf = {};
627
BinarySpanWriter writer(buf);
628
EXPECT_TRUE(writer.WriteCString(""));
629
EXPECT_EQ(buf[0], '\0');
630
EXPECT_EQ(writer.GetBufferWritten(), 1u);
631
}
632
633
TEST(BinarySpanWriter, WriteSizePrefixedString)
634
{
635
std::array<u8, 16> buf = {};
636
BinarySpanWriter writer(buf);
637
EXPECT_TRUE(writer.WriteSizePrefixedString("Test"));
638
639
u32 length;
640
std::memcpy(&length, buf.data(), sizeof(length));
641
EXPECT_EQ(length, 4u);
642
EXPECT_EQ(buf[4], 'T');
643
EXPECT_EQ(buf[7], 't');
644
EXPECT_EQ(writer.GetBufferWritten(), 8u);
645
}
646
647
TEST(BinarySpanWriter, WriteSizePrefixedStringEmpty)
648
{
649
std::array<u8, 16> buf = {};
650
BinarySpanWriter writer(buf);
651
EXPECT_TRUE(writer.WriteSizePrefixedString(""));
652
653
u32 length;
654
std::memcpy(&length, buf.data(), sizeof(length));
655
EXPECT_EQ(length, 0u);
656
EXPECT_EQ(writer.GetBufferWritten(), 4u);
657
}
658
659
TEST(BinarySpanWriter, StreamOperators)
660
{
661
std::array<u8, 32> buf = {};
662
BinarySpanWriter writer(buf);
663
664
writer << static_cast<u8>(0x01) << static_cast<s8>(0xFE) << static_cast<u16>(0x1234) << static_cast<s16>(0xABCD)
665
<< static_cast<u32>(0x12345678) << static_cast<s32>(0xEDCBA988) << static_cast<u64>(0x0123456789ABCDEFull)
666
<< 1.0f;
667
668
EXPECT_EQ(writer.GetBufferWritten(), 26u);
669
670
// Verify by reading back
671
BinarySpanReader reader(std::span<const u8>(buf.data(), writer.GetBufferWritten()));
672
EXPECT_EQ(reader.ReadU8(), 0x01u);
673
EXPECT_EQ(reader.ReadS8(), static_cast<s8>(0xFE));
674
EXPECT_EQ(reader.ReadU16(), 0x1234u);
675
EXPECT_EQ(reader.ReadS16(), static_cast<s16>(0xABCD));
676
EXPECT_EQ(reader.ReadU32(), 0x12345678u);
677
EXPECT_EQ(reader.ReadS32(), static_cast<s32>(0xEDCBA988));
678
EXPECT_EQ(reader.ReadU64(), 0x0123456789ABCDEFull);
679
EXPECT_FLOAT_EQ(reader.ReadFloat(), 1.0f);
680
}
681
682
TEST(BinarySpanWriter, StreamOperatorCString)
683
{
684
std::array<u8, 16> buf = {};
685
BinarySpanWriter writer(buf);
686
writer << "Hello"sv;
687
688
BinarySpanReader reader(std::span<const u8>(buf.data(), writer.GetBufferWritten()));
689
EXPECT_EQ(reader.ReadCString(), "Hello"sv);
690
}
691
692
TEST(BinarySpanWriter, WriteOptionalTWithValue)
693
{
694
std::array<u8, 8> buf = {};
695
BinarySpanWriter writer(buf);
696
std::optional<u32> val = 0x12345678u;
697
EXPECT_TRUE(writer.WriteOptionalT(val));
698
EXPECT_EQ(writer.GetBufferWritten(), 5u);
699
700
BinarySpanReader reader(std::span<const u8>(buf.data(), writer.GetBufferWritten()));
701
EXPECT_TRUE(reader.ReadBool());
702
EXPECT_EQ(reader.ReadU32(), 0x12345678u);
703
}
704
705
TEST(BinarySpanWriter, WriteOptionalTWithoutValue)
706
{
707
std::array<u8, 8> buf = {};
708
BinarySpanWriter writer(buf);
709
std::optional<u32> val;
710
EXPECT_TRUE(writer.WriteOptionalT(val));
711
EXPECT_EQ(writer.GetBufferWritten(), 1u);
712
713
BinarySpanReader reader(std::span<const u8>(buf.data(), writer.GetBufferWritten()));
714
EXPECT_FALSE(reader.ReadBool());
715
}
716
717
TEST(BinarySpanWriter, GetRemainingSpan)
718
{
719
std::array<u8, 32> buf = {};
720
BinarySpanWriter writer(buf);
721
writer.IncrementPosition(10);
722
auto remaining = writer.GetRemainingSpan();
723
EXPECT_EQ(remaining.size(), buf.size() - 10);
724
}
725
726
TEST(BinarySpanWriter, GetRemainingSpanWithSize)
727
{
728
std::array<u8, 32> buf = {};
729
BinarySpanWriter writer(buf);
730
writer.IncrementPosition(10);
731
auto remaining = writer.GetRemainingSpan(5);
732
EXPECT_EQ(remaining.size(), 5u);
733
}
734
735
TEST(BinarySpanWriter, WriteBeyondBuffer)
736
{
737
std::array<u8, 2> buf = {};
738
BinarySpanWriter writer(buf);
739
EXPECT_FALSE(writer.WriteU32(0x12345678));
740
}
741
742
TEST(BinarySpanWriter, WriteCStringBeyondBuffer)
743
{
744
std::array<u8, 4> buf = {};
745
BinarySpanWriter writer(buf);
746
EXPECT_FALSE(writer.WriteCString("Hello")); // needs 6 bytes
747
}
748
749
TEST(BinarySpanWriter, WriteSizePrefixedStringBeyondBuffer)
750
{
751
std::array<u8, 4> buf = {};
752
BinarySpanWriter writer(buf);
753
EXPECT_FALSE(writer.WriteSizePrefixedString("Test")); // needs 8 bytes
754
}
755
756
//////////////////////////////////////////////////////////////////////////
757
// Round-trip Tests (Writer -> Reader)
758
//////////////////////////////////////////////////////////////////////////
759
760
TEST(BinarySpanRoundTrip, AllPrimitiveTypes)
761
{
762
std::array<u8, 64> buf = {};
763
BinarySpanWriter writer(buf);
764
765
writer.WriteU8(0xAB);
766
writer.WriteS8(-42);
767
writer.WriteU16(0x1234);
768
writer.WriteS16(-1000);
769
writer.WriteU32(0xDEADBEEF);
770
writer.WriteS32(-123456789);
771
writer.WriteU64(0xFEDCBA9876543210ull);
772
writer.WriteS64(-876543210123456789ll);
773
writer.WriteFloat(3.14159f);
774
writer.WriteBool(true);
775
776
BinarySpanReader reader(std::span<const u8>(buf.data(), writer.GetBufferWritten()));
777
EXPECT_EQ(reader.ReadU8(), 0xABu);
778
EXPECT_EQ(reader.ReadS8(), -42);
779
EXPECT_EQ(reader.ReadU16(), 0x1234u);
780
EXPECT_EQ(reader.ReadS16(), -1000);
781
EXPECT_EQ(reader.ReadU32(), 0xDEADBEEFu);
782
EXPECT_EQ(reader.ReadS32(), -123456789);
783
EXPECT_EQ(reader.ReadU64(), 0xFEDCBA9876543210ull);
784
EXPECT_EQ(reader.ReadS64(), -876543210123456789ll);
785
EXPECT_FLOAT_EQ(reader.ReadFloat(), 3.14159f);
786
EXPECT_TRUE(reader.ReadBool());
787
}
788
789
TEST(BinarySpanRoundTrip, CStrings)
790
{
791
std::array<u8, 64> buf = {};
792
BinarySpanWriter writer(buf);
793
794
writer.WriteCString("Hello");
795
writer.WriteCString("");
796
writer.WriteCString("World!");
797
798
BinarySpanReader reader(std::span<const u8>(buf.data(), writer.GetBufferWritten()));
799
EXPECT_EQ(reader.ReadCString(), "Hello"sv);
800
EXPECT_EQ(reader.ReadCString(), ""sv);
801
EXPECT_EQ(reader.ReadCString(), "World!"sv);
802
}
803
804
TEST(BinarySpanRoundTrip, SizePrefixedStrings)
805
{
806
std::array<u8, 64> buf = {};
807
BinarySpanWriter writer(buf);
808
809
writer.WriteSizePrefixedString("Testing");
810
writer.WriteSizePrefixedString("");
811
writer.WriteSizePrefixedString("123");
812
813
BinarySpanReader reader(std::span<const u8>(buf.data(), writer.GetBufferWritten()));
814
EXPECT_EQ(reader.ReadSizePrefixedString(), "Testing"sv);
815
EXPECT_EQ(reader.ReadSizePrefixedString(), ""sv);
816
EXPECT_EQ(reader.ReadSizePrefixedString(), "123"sv);
817
}
818
819
TEST(BinarySpanRoundTrip, OptionalValues)
820
{
821
std::array<u8, 32> buf = {};
822
BinarySpanWriter writer(buf);
823
824
std::optional<u32> val1 = 12345u;
825
std::optional<u32> val2;
826
std::optional<u16> val3 = u16(9999);
827
828
writer.WriteOptionalT(val1);
829
writer.WriteOptionalT(val2);
830
writer.WriteOptionalT(val3);
831
832
BinarySpanReader reader(std::span<const u8>(buf.data(), writer.GetBufferWritten()));
833
834
std::optional<u32> read1, read2;
835
std::optional<u16> read3;
836
837
EXPECT_TRUE(reader.ReadOptionalT(&read1));
838
EXPECT_TRUE(reader.ReadOptionalT(&read2));
839
EXPECT_TRUE(reader.ReadOptionalT(&read3));
840
841
EXPECT_TRUE(read1.has_value());
842
EXPECT_EQ(read1.value(), 12345u);
843
EXPECT_FALSE(read2.has_value());
844
EXPECT_TRUE(read3.has_value());
845
EXPECT_EQ(read3.value(), 9999u);
846
}
847
848
TEST(BinarySpanRoundTrip, MixedContent)
849
{
850
std::array<u8, 128> buf = {};
851
BinarySpanWriter writer(buf);
852
853
writer.WriteU32(0x12345678);
854
writer.WriteCString("Header");
855
writer.WriteU16(100);
856
writer.WriteSizePrefixedString("Payload");
857
writer.WriteFloat(2.5f);
858
writer.WriteBool(false);
859
860
BinarySpanReader reader(std::span<const u8>(buf.data(), writer.GetBufferWritten()));
861
862
EXPECT_EQ(reader.ReadU32(), 0x12345678u);
863
EXPECT_EQ(reader.ReadCString(), "Header"sv);
864
EXPECT_EQ(reader.ReadU16(), 100u);
865
EXPECT_EQ(reader.ReadSizePrefixedString(), "Payload"sv);
866
EXPECT_FLOAT_EQ(reader.ReadFloat(), 2.5f);
867
EXPECT_FALSE(reader.ReadBool());
868
}
869