Coverage Report

Created: 2024-04-30 09:35

test/zserio/BitStreamTest.cpp
Line
Count
Source
1
#include <array>
2
#include <cstring>
3
#include <functional>
4
#include <string>
5
6
#include "gtest/gtest.h"
7
#include "zserio/BitStreamReader.h"
8
#include "zserio/BitStreamWriter.h"
9
#include "zserio/CppRuntimeException.h"
10
#include "zserio/Types.h"
11
#include "zserio/Vector.h"
12
13
namespace zserio
14
{
15
16
class BitStreamTest : public ::testing::Test
17
{
18
public:
19
    BitStreamTest() :
20
            m_byteBuffer(),
21
            m_externalWriter(m_byteBuffer.data(), m_byteBuffer.size()),
22
            m_dummyWriter(nullptr, 0)
23
23
    {
24
23
        m_byteBuffer.fill(0);
25
23
    }
26
27
protected:
28
    template <typename T, size_t N, typename U>
29
    void testImpl(const std::array<T, N>& values, std::function<void(BitStreamWriter&, U)> writerFunc,
30
            std::function<T(BitStreamReader&)> readerFunc, uint8_t maxStartBitPos)
31
16
    {
32
16
        testBitStreamValues(values, m_externalWriter, writerFunc, readerFunc, maxStartBitPos);
33
16
        testBitStreamValues(values, m_dummyWriter, writerFunc, readerFunc, maxStartBitPos);
34
16
    }
35
36
    template <typename T, size_t N, typename U>
37
    void testBitStreamValues(const std::array<T, N>& values, BitStreamWriter& writer,
38
            std::function<void(BitStreamWriter&, U)> writerFunc, std::function<T(BitStreamReader&)> readerFunc,
39
            uint8_t maxStartBitPos)
40
32
    {
41
1.04k
        for (uint8_t bitPos = 0; bitPos < maxStartBitPos; 
++bitPos1.00k
)
42
1.00k
        {
43
1.00k
            if (bitPos > 0)
44
976
                writer.writeBits64(0, bitPos);
45
19.1k
            for (size_t i = 0; i < N; 
++i18.1k
)
46
18.1k
            {
47
18.1k
                writerFunc(writer, values.at(i));
48
18.1k
            }
49
50
1.00k
            if (!writer.hasWriteBuffer())
51
504
                continue;
52
53
504
            BitStreamReader reader(writer.getWriteBuffer(), writer.getBitPosition(), BitsTag());
54
504
            if (bitPos > 0)
55
488
                reader.readBits64(bitPos);
56
9.57k
            for (size_t i = 0; i < N; 
++i9.07k
)
57
9.07k
            {
58
18.1k
                ASSERT_EQ(readerFunc(reader), values.at(i)) << "[bitPos=" << bitPos << "]";
59
9.07k
            }
60
61
504
            writer.setBitPosition(0);
62
504
            m_byteBuffer.fill(0);
63
504
        }
64
32
    }
65
66
    void testReadBits(BitStreamWriter& writer)
67
2
    {
68
2
        writer.writeBits(1, 1);
69
2
        writer.writeBits(2, 2);
70
2
        writer.writeBits(42, 12);
71
2
        writer.writeBits(15999999, 24);
72
2
        writer.writeBits(7, 3);
73
74
2
        if (!writer.hasWriteBuffer())
75
1
            return;
76
77
1
        BitStreamReader reader(writer.getWriteBuffer(), writer.getBitPosition(), BitsTag());
78
1
        ASSERT_EQ(1, reader.readBits(1));
79
1
        ASSERT_EQ(2, reader.readBits(2));
80
1
        ASSERT_EQ(42, reader.readBits(12));
81
1
        ASSERT_EQ(15999999, reader.readBits(24));
82
1
        ASSERT_EQ(7, reader.readBits(3));
83
1
    }
84
85
    void testReadBits64(BitStreamWriter& writer)
86
2
    {
87
2
        writer.writeBits(1, 1);
88
2
        writer.writeBits64(UINT64_C(42424242424242), 48);
89
2
        writer.writeBits64(UINT64_C(0xFFFFFFFFFFFFFFFE), 64);
90
91
2
        if (!writer.hasWriteBuffer())
92
1
            return;
93
94
1
        BitStreamReader reader(writer.getWriteBuffer(), writer.getBitPosition(), BitsTag());
95
1
        ASSERT_EQ(1, reader.readBits(1));
96
1
        ASSERT_EQ(UINT64_C(42424242424242), reader.readBits64(48));
97
1
        ASSERT_EQ(UINT64_C(0xFFFFFFFFFFFFFFFE), reader.readBits64(64));
98
1
    }
99
100
    void testReadSignedBits(BitStreamWriter& writer)
101
2
    {
102
2
        writer.writeSignedBits(-1, 5);
103
2
        writer.writeSignedBits(3, 12);
104
2
        writer.writeSignedBits(-142, 9);
105
106
2
        if (!writer.hasWriteBuffer())
107
1
            return;
108
109
1
        BitStreamReader reader(writer.getWriteBuffer(), writer.getBitPosition(), BitsTag());
110
1
        ASSERT_EQ(-1, reader.readSignedBits(5));
111
1
        ASSERT_EQ(3, reader.readSignedBits(12));
112
1
        ASSERT_EQ(-142, reader.readSignedBits(9));
113
1
    }
114
115
    void testReadSignedBits64(BitStreamWriter& writer)
116
2
    {
117
2
        writer.writeSignedBits64(INT64_C(1), 4);
118
2
        writer.writeSignedBits64(INT64_C(-1), 48);
119
2
        writer.writeSignedBits64(INT64_C(-42424242), 61);
120
2
        writer.writeSignedBits64(INT64_C(-820816), 32);
121
122
2
        if (!writer.hasWriteBuffer())
123
1
            return;
124
125
1
        BitStreamReader reader(writer.getWriteBuffer(), writer.getBitPosition(), BitsTag());
126
1
        ASSERT_EQ(INT64_C(1), reader.readSignedBits(4));
127
1
        ASSERT_EQ(INT64_C(-1), reader.readSignedBits64(48));
128
1
        ASSERT_EQ(INT64_C(-42424242), reader.readSignedBits64(61));
129
1
        ASSERT_EQ(INT64_C(-820816), reader.readSignedBits64(32));
130
1
    }
131
132
    void testAlignedBytes(BitStreamWriter& writer)
133
2
    {
134
        // reads aligned data directly from buffer, bit cache should remain empty
135
2
        writer.writeBits(UINT8_C(0xCA), 8);
136
2
        writer.writeBits(UINT16_C(0xCAFE), 16);
137
2
        writer.writeBits(UINT32_C(0xCAFEC0), 24);
138
2
        writer.writeBits(UINT32_C(0xCAFEC0DE), 32);
139
2
        writer.writeBits64(UINT64_C(0xCAFEC0DEDE), 40);
140
2
        writer.writeBits64(UINT64_C(0xCAFEC0DEDEAD), 48);
141
2
        writer.writeBits64(UINT64_C(0xCAFEC0DEDEADFA), 56);
142
2
        writer.writeBits64(UINT64_C(0xCAFEC0DEDEADFACE), 64);
143
144
2
        if (!writer.hasWriteBuffer())
145
1
            return;
146
147
1
        BitStreamReader reader(writer.getWriteBuffer(), writer.getBitPosition(), BitsTag());
148
1
        ASSERT_EQ(UINT8_C(0xCA), reader.readBits(8));
149
1
        ASSERT_EQ(UINT16_C(0xCAFE), reader.readBits(16));
150
1
        ASSERT_EQ(UINT32_C(0xCAFEC0), reader.readBits(24));
151
1
        ASSERT_EQ(UINT32_C(0xCAFEC0DE), reader.readBits(32));
152
1
        ASSERT_EQ(UINT64_C(0xCAFEC0DEDE), reader.readBits64(40));
153
1
        ASSERT_EQ(UINT64_C(0xCAFEC0DEDEAD), reader.readBits64(48));
154
1
        ASSERT_EQ(UINT64_C(0xCAFEC0DEDEADFA), reader.readBits64(56));
155
1
        ASSERT_EQ(UINT64_C(0xCAFEC0DEDEADFACE), reader.readBits64(64));
156
1
    }
157
158
    void testSetBitPosition(BitStreamWriter& writer)
159
2
    {
160
2
        ASSERT_EQ(0, writer.getBitPosition());
161
2
        writer.writeBits(1, 1);
162
2
        ASSERT_EQ(1, writer.getBitPosition());
163
2
        writer.alignTo(4);
164
2
        ASSERT_EQ(4, writer.getBitPosition());
165
2
        writer.writeBits(5, 5);
166
2
        ASSERT_EQ(9, writer.getBitPosition());
167
2
        if (writer.hasWriteBuffer())
168
1
        {
169
1
            ASSERT_THROW(writer.setBitPosition(m_byteBuffer.size() * 8 + 1), CppRuntimeException);
170
1
        }
171
1
        else
172
1
        {
173
            // dummy buffer
174
1
            writer.setBitPosition(m_byteBuffer.size() * 8 + 1);
175
1
            ASSERT_EQ(m_byteBuffer.size() * 8 + 1, writer.getBitPosition());
176
1
        }
177
2
        writer.setBitPosition(4);
178
2
        ASSERT_EQ(4, writer.getBitPosition());
179
2
        writer.writeBits(3, 3);
180
2
        ASSERT_EQ(7, writer.getBitPosition());
181
182
2
        if (!writer.hasWriteBuffer())
183
1
            return;
184
185
1
        BitStreamReader reader(writer.getWriteBuffer(), writer.getBitPosition(), BitsTag());
186
1
        ASSERT_EQ(0, reader.getBitPosition());
187
1
        ASSERT_EQ(1, reader.readBits(1));
188
1
        ASSERT_EQ(1, reader.getBitPosition());
189
1
        reader.alignTo(4);
190
1
        ASSERT_EQ(4, reader.getBitPosition());
191
1
        ASSERT_EQ(3, reader.readBits(3));
192
1
        ASSERT_EQ(7, reader.getBitPosition());
193
1
        ASSERT_THROW(reader.setBitPosition(writer.getBitPosition() + 1), CppRuntimeException);
194
195
1
        reader.setBitPosition(4);
196
1
        ASSERT_EQ(4, reader.getBitPosition());
197
1
        ASSERT_EQ(3, reader.readBits(3));
198
1
        ASSERT_EQ(7, reader.getBitPosition());
199
1
    }
200
201
    void testAlignTo(BitStreamWriter& writer)
202
2
    {
203
2
        writer.writeBits(1, 1);
204
2
        writer.alignTo(4);
205
2
        ASSERT_EQ(4, writer.getBitPosition());
206
2
        writer.writeBits(1, 1);
207
2
        writer.alignTo(4);
208
2
        ASSERT_EQ(8, writer.getBitPosition());
209
2
        writer.writeBits(37, 11);
210
2
        writer.alignTo(8);
211
2
        ASSERT_EQ(24, writer.getBitPosition());
212
2
        writer.writeBits(1, 1);
213
2
        writer.alignTo(16);
214
2
        ASSERT_EQ(32, writer.getBitPosition());
215
2
        writer.writeBits(13, 13);
216
2
        writer.alignTo(32);
217
2
        ASSERT_EQ(64, writer.getBitPosition());
218
2
        writer.writeBits(42, 15);
219
2
        writer.alignTo(64);
220
2
        ASSERT_EQ(128, writer.getBitPosition());
221
2
        writer.writeBits(99, 9);
222
2
        ASSERT_EQ(137, writer.getBitPosition());
223
224
2
        if (!writer.hasWriteBuffer())
225
1
            return;
226
227
1
        BitStreamReader reader(writer.getWriteBuffer(), writer.getBitPosition(), BitsTag());
228
1
        ASSERT_EQ(1, reader.readBits(1));
229
1
        reader.alignTo(4);
230
1
        ASSERT_EQ(1, reader.readBits(1));
231
1
        reader.alignTo(4);
232
1
        ASSERT_EQ(37, reader.readBits(11));
233
1
        reader.alignTo(8);
234
1
        ASSERT_EQ(1, reader.readBits(1));
235
1
        reader.alignTo(16);
236
1
        ASSERT_EQ(13, reader.readBits(13));
237
1
        reader.alignTo(32);
238
1
        ASSERT_EQ(42, reader.readBits(15));
239
1
        reader.alignTo(64);
240
1
        ASSERT_EQ(99, reader.readBits(9));
241
1
        ASSERT_EQ(137, reader.getBitPosition());
242
1
    }
243
244
    std::array<uint8_t, 256> m_byteBuffer;
245
    BitStreamWriter m_externalWriter;
246
    BitStreamWriter m_dummyWriter;
247
};
248
249
TEST_F(BitStreamTest, readBits)
250
1
{
251
1
    testReadBits(m_externalWriter);
252
1
    testReadBits(m_dummyWriter);
253
1
}
254
255
TEST_F(BitStreamTest, readBits64)
256
1
{
257
1
    testReadBits64(m_externalWriter);
258
1
    testReadBits64(m_dummyWriter);
259
1
}
260
261
TEST_F(BitStreamTest, readSignedBits)
262
1
{
263
1
    testReadSignedBits(m_externalWriter);
264
1
    testReadSignedBits(m_dummyWriter);
265
1
}
266
267
TEST_F(BitStreamTest, readSignedBits64)
268
1
{
269
1
    testReadSignedBits64(m_externalWriter);
270
1
    testReadSignedBits64(m_dummyWriter);
271
1
}
272
273
TEST_F(BitStreamTest, alignedBytes)
274
1
{
275
1
    testAlignedBytes(m_externalWriter);
276
1
    testAlignedBytes(m_dummyWriter);
277
1
}
278
279
TEST_F(BitStreamTest, readVarInt64)
280
1
{
281
1
    const std::array<int64_t, 33> values = {
282
1
            INT64_C(0),
283
1
            INT64_C(-32),
284
1
            INT64_C(32),
285
1
            INT64_C(-4096),
286
1
            INT64_C(4096),
287
1
            INT64_C(-524288),
288
1
            INT64_C(524288),
289
1
            INT64_C(-67108864),
290
1
            INT64_C(67108864),
291
1
            INT64_C(-8589934592),
292
1
            INT64_C(8589934592),
293
1
            INT64_C(-1099511627776),
294
1
            INT64_C(1099511627776),
295
1
            INT64_C(-140737488355328),
296
1
            INT64_C(140737488355328),
297
1
            INT64_C(-18014398509481984),
298
1
            INT64_C(18014398509481984),
299
300
1
            (INT64_C(1) << (0)),
301
1
            (INT64_C(1) << (6)) - 1,
302
303
1
            (INT64_C(1) << (6)),
304
1
            (INT64_C(1) << (6 + 7)) - 1,
305
306
1
            (INT64_C(1) << (6 + 7)),
307
1
            (INT64_C(1) << (6 + 7 + 7)) - 1,
308
309
1
            (INT64_C(1) << (6 + 7 + 7)),
310
1
            (INT64_C(1) << (6 + 7 + 7 + 7)) - 1,
311
312
1
            (INT64_C(1) << (6 + 7 + 7 + 7)),
313
1
            (INT64_C(1) << (6 + 7 + 7 + 7 + 7)) - 1,
314
315
1
            (INT64_C(1) << (6 + 7 + 7 + 7 + 7)),
316
1
            (INT64_C(1) << (6 + 7 + 7 + 7 + 7 + 7)) - 1,
317
318
1
            (INT64_C(1) << (6 + 7 + 7 + 7 + 7 + 7)),
319
1
            (INT64_C(1) << (6 + 7 + 7 + 7 + 7 + 7 + 7)) - 1,
320
321
1
            (INT64_C(1) << (6 + 7 + 7 + 7 + 7 + 7 + 7)),
322
1
            (INT64_C(1) << (6 + 7 + 7 + 7 + 7 + 7 + 7 + 8)) - 1,
323
1
    };
324
325
1
    std::function<void(BitStreamWriter&, int64_t)> writerFunc = &BitStreamWriter::writeVarInt64;
326
1
    std::function<int64_t(BitStreamReader&)> readerFunc = &BitStreamReader::readVarInt64;
327
328
1
    testImpl(values, writerFunc, readerFunc, 63);
329
1
}
330
331
TEST_F(BitStreamTest, readVarInt32)
332
1
{
333
1
    const std::array<int32_t, 17> values = {
334
1
            static_cast<int32_t>(0),
335
1
            static_cast<int32_t>(-32),
336
1
            static_cast<int32_t>(32),
337
1
            static_cast<int32_t>(-4096),
338
1
            static_cast<int32_t>(4096),
339
1
            static_cast<int32_t>(-524288),
340
1
            static_cast<int32_t>(524288),
341
1
            static_cast<int32_t>(-67108864),
342
1
            static_cast<int32_t>(67108864),
343
344
1
            static_cast<int32_t>(1U << (0U)),
345
1
            static_cast<int32_t>(1U << (6U)) - 1,
346
347
1
            static_cast<int32_t>(1U << (6U)),
348
1
            static_cast<int32_t>(1U << (6U + 7)) - 1,
349
350
1
            static_cast<int32_t>(1U << (6U + 7)),
351
1
            static_cast<int32_t>(1U << (6U + 7 + 7)) - 1,
352
353
1
            static_cast<int32_t>(1U << (6U + 7 + 7)),
354
1
            static_cast<int32_t>(1U << (6U + 7 + 7 + 8)) - 1,
355
1
    };
356
357
1
    std::function<void(BitStreamWriter&, int32_t)> writerFunc = &BitStreamWriter::writeVarInt32;
358
1
    std::function<int32_t(BitStreamReader&)> readerFunc = &BitStreamReader::readVarInt32;
359
360
1
    testImpl(values, writerFunc, readerFunc, 31);
361
1
}
362
363
TEST_F(BitStreamTest, readVarInt16)
364
1
{
365
1
    const std::array<int16_t, 9> values = {
366
1
            static_cast<int16_t>(0),
367
1
            static_cast<int16_t>(-32),
368
1
            static_cast<int16_t>(32),
369
1
            static_cast<int16_t>(-4096),
370
1
            static_cast<int16_t>(4096),
371
372
1
            static_cast<int16_t>(1U << (0U)),
373
1
            static_cast<int16_t>(1U << (6U)) - 1,
374
375
1
            static_cast<int16_t>(1U << (6U)),
376
1
            static_cast<int16_t>(1U << (6 + 8U)) - 1,
377
1
    };
378
379
1
    std::function<void(BitStreamWriter&, int16_t)> writerFunc = &BitStreamWriter::writeVarInt16;
380
1
    std::function<int16_t(BitStreamReader&)> readerFunc = &BitStreamReader::readVarInt16;
381
382
1
    testImpl(values, writerFunc, readerFunc, 15);
383
1
}
384
385
TEST_F(BitStreamTest, readVarUInt64)
386
1
{
387
1
    const std::array<uint64_t, 19> values = {
388
1
            0,
389
1
            262144,
390
1
            524288,
391
392
1
            (UINT64_C(1) << (0U)),
393
1
            (UINT64_C(1) << (7U)) - 1,
394
395
1
            (UINT64_C(1) << (7U)),
396
1
            (UINT64_C(1) << (7U + 7)) - 1,
397
398
1
            (UINT64_C(1) << (7U + 7)),
399
1
            (UINT64_C(1) << (7U + 7 + 7)) - 1,
400
401
1
            (UINT64_C(1) << (7U + 7 + 7)),
402
1
            (UINT64_C(1) << (7U + 7 + 7 + 7)) - 1,
403
404
1
            (UINT64_C(1) << (7U + 7 + 7 + 7)),
405
1
            (UINT64_C(1) << (7U + 7 + 7 + 7 + 7)) - 1,
406
407
1
            (UINT64_C(1) << (7U + 7 + 7 + 7 + 7)),
408
1
            (UINT64_C(1) << (7U + 7 + 7 + 7 + 7 + 7)) - 1,
409
410
1
            (UINT64_C(1) << (7U + 7 + 7 + 7 + 7 + 7)),
411
1
            (UINT64_C(1) << (7U + 7 + 7 + 7 + 7 + 7 + 7)) - 1,
412
413
1
            (UINT64_C(1) << (7U + 7 + 7 + 7 + 7 + 7 + 7)),
414
1
            (UINT64_C(1) << (7U + 7 + 7 + 7 + 7 + 7 + 7 + 8)) - 1,
415
1
    };
416
417
1
    std::function<void(BitStreamWriter&, uint64_t)> writerFunc = &BitStreamWriter::writeVarUInt64;
418
1
    std::function<uint64_t(BitStreamReader&)> readerFunc = &BitStreamReader::readVarUInt64;
419
420
1
    testImpl(values, writerFunc, readerFunc, 63);
421
1
}
422
423
TEST_F(BitStreamTest, readVarUInt32)
424
1
{
425
1
    const std::array<uint32_t, 11> values = {
426
1
            0,
427
1
            65536,
428
1
            131072,
429
430
1
            (1U << (0U)),
431
1
            (1U << (7U)) - 1,
432
433
1
            (1U << (7U)),
434
1
            (1U << (7U + 7)) - 1,
435
436
1
            (1U << (7U + 7)),
437
1
            (1U << (7U + 7 + 7)) - 1,
438
439
1
            (1U << (7U + 7 + 7)),
440
1
            (1U << (7U + 7 + 7 + 8)) - 1,
441
1
    };
442
443
1
    std::function<void(BitStreamWriter&, uint32_t)> writerFunc = &BitStreamWriter::writeVarUInt32;
444
1
    std::function<uint32_t(BitStreamReader&)> readerFunc = &BitStreamReader::readVarUInt32;
445
446
1
    testImpl(values, writerFunc, readerFunc, 31);
447
1
}
448
449
TEST_F(BitStreamTest, readVarUInt16)
450
1
{
451
1
    const std::array<uint16_t, 7> values = {
452
1
            0,
453
1
            8192,
454
1
            16384,
455
456
1
            (1U << (0U)),
457
1
            (1U << (6U)) - 1,
458
459
1
            (1U << (6U)),
460
1
            (1U << (6U + 8)) - 1,
461
1
    };
462
463
1
    std::function<void(BitStreamWriter&, uint16_t)> writerFunc = &BitStreamWriter::writeVarUInt16;
464
1
    std::function<uint16_t(BitStreamReader&)> readerFunc = &BitStreamReader::readVarUInt16;
465
466
1
    testImpl(values, writerFunc, readerFunc, 15);
467
1
}
468
469
TEST_F(BitStreamTest, readVarInt)
470
1
{
471
1
    const std::array<int64_t, 38> values = {
472
            // 1 byte
473
1
            0,
474
1
            -1,
475
1
            1,
476
1
            -static_cast<int64_t>(UINT64_C(1) << 6U) + 1,
477
1
            static_cast<int64_t>(UINT64_C(1) << 6U) - 1,
478
            // 2 bytes
479
1
            -static_cast<int64_t>(UINT64_C(1) << 6U),
480
1
            static_cast<int64_t>(UINT64_C(1) << 6U),
481
1
            -static_cast<int64_t>(UINT64_C(1) << 13U) + 1,
482
1
            static_cast<int64_t>(UINT64_C(1) << 13U) - 1,
483
            // 3 bytes
484
1
            -static_cast<int64_t>(UINT64_C(1) << 13U),
485
1
            static_cast<int64_t>(UINT64_C(1) << 13U),
486
1
            -static_cast<int64_t>(UINT64_C(1) << 20U) + 1,
487
1
            static_cast<int64_t>(UINT64_C(1) << 20U) - 1,
488
            // 4 bytes
489
1
            -static_cast<int64_t>(UINT64_C(1) << 20U),
490
1
            static_cast<int64_t>(UINT64_C(1) << 20U),
491
1
            -static_cast<int64_t>(UINT64_C(1) << 27U) + 1,
492
1
            static_cast<int64_t>(UINT64_C(1) << 27U) - 1,
493
            // 5 bytes
494
1
            -static_cast<int64_t>(UINT64_C(1) << 27U),
495
1
            static_cast<int64_t>(UINT64_C(1) << 27U),
496
1
            -static_cast<int64_t>(UINT64_C(1) << 34U) + 1,
497
1
            static_cast<int64_t>(UINT64_C(1) << 34U) - 1,
498
            // 6 bytes
499
1
            -static_cast<int64_t>(UINT64_C(1) << 34U),
500
1
            static_cast<int64_t>(UINT64_C(1) << 34U),
501
1
            -static_cast<int64_t>(UINT64_C(1) << 41U) + 1,
502
1
            static_cast<int64_t>(UINT64_C(1) << 41U) - 1,
503
            // 7 bytes
504
1
            -static_cast<int64_t>(UINT64_C(1) << 41U),
505
1
            static_cast<int64_t>(UINT64_C(1) << 41U),
506
1
            -static_cast<int64_t>(UINT64_C(1) << 48U) + 1,
507
1
            static_cast<int64_t>(UINT64_C(1) << 48U) - 1,
508
            // 8 bytes
509
1
            -static_cast<int64_t>(UINT64_C(1) << 48U),
510
1
            static_cast<int64_t>(UINT64_C(1) << 48U),
511
1
            -static_cast<int64_t>(UINT64_C(1) << 55U) + 1,
512
1
            static_cast<int64_t>(UINT64_C(1) << 55U) - 1,
513
            // 9 bytes
514
1
            -static_cast<int64_t>(UINT64_C(1) << 55U),
515
1
            static_cast<int64_t>(UINT64_C(1) << 55U),
516
1
            INT64_MIN + 1,
517
1
            INT64_MAX,
518
519
            // special case - stored as -0 (1 byte)
520
1
            INT64_MIN,
521
1
    };
522
523
1
    std::function<void(BitStreamWriter&, int64_t)> writerFunc = &BitStreamWriter::writeVarInt;
524
1
    std::function<int64_t(BitStreamReader&)> readerFunc = &BitStreamReader::readVarInt;
525
526
1
    testImpl(values, writerFunc, readerFunc, 63);
527
1
}
528
529
TEST_F(BitStreamTest, readVarUInt)
530
1
{
531
1
    const std::array<uint64_t, 19> values = {
532
            // 1 byte
533
1
            0,
534
1
            1,
535
1
            (UINT64_C(1) << 7U) - 1,
536
            // 2 bytes
537
1
            (UINT64_C(1) << 7U),
538
1
            (UINT64_C(1) << 14U) - 1,
539
            // 3 bytes
540
1
            (UINT64_C(1) << 14U),
541
1
            (UINT64_C(1) << 21U) - 1,
542
            // 4 bytes
543
1
            (UINT64_C(1) << 21U),
544
1
            (UINT64_C(1) << 28U) - 1,
545
            // 5 bytes
546
1
            (UINT64_C(1) << 28U),
547
1
            (UINT64_C(1) << 35U) - 1,
548
            // 6 bytes
549
1
            (UINT64_C(1) << 35U),
550
1
            (UINT64_C(1) << 42U) - 1,
551
            // 7 bytes
552
1
            (UINT64_C(1) << 42U),
553
1
            (UINT64_C(1) << 49U) - 1,
554
            // 8 bytes
555
1
            (UINT64_C(1) << 49U),
556
1
            (UINT64_C(1) << 56U) - 1,
557
            // 9 bytes
558
1
            (UINT64_C(1) << 56U),
559
1
            UINT64_MAX,
560
1
    };
561
562
1
    std::function<void(BitStreamWriter&, uint64_t)> writerFunc = &BitStreamWriter::writeVarUInt;
563
1
    std::function<uint64_t(BitStreamReader&)> readerFunc = &BitStreamReader::readVarUInt;
564
565
1
    testImpl(values, writerFunc, readerFunc, 63);
566
1
}
567
568
TEST_F(BitStreamTest, readVarSize)
569
1
{
570
1
    const std::array<uint32_t, 13> values = {
571
1
            0,
572
1
            65536,
573
1
            131072,
574
575
1
            (1U << (0U)),
576
1
            (1U << (7U)) - 1,
577
578
1
            (1U << (7U)),
579
1
            (1U << (7U + 7)) - 1,
580
581
1
            (1U << (7U + 7)),
582
1
            (1U << (7U + 7 + 7)) - 1,
583
584
1
            (1U << (7U + 7 + 7)),
585
1
            (1U << (7U + 7 + 7 + 7)) - 1,
586
587
1
            (1U << (7U + 7 + 7 + 7)),
588
1
            (1U << (7U + 7 + 7 + 7 + 3)) - 1,
589
1
    };
590
591
1
    std::function<void(BitStreamWriter&, uint32_t)> writerFunc = &BitStreamWriter::writeVarSize;
592
1
    std::function<uint32_t(BitStreamReader&)> readerFunc = &BitStreamReader::readVarSize;
593
594
1
    testImpl(values, writerFunc, readerFunc, 31);
595
1
}
596
597
TEST_F(BitStreamTest, readFloat16)
598
1
{
599
1
    const std::array<float, 6> values = {2.0, -2.0, 0.6171875, 0.875, 9.875, 42.5};
600
601
1
    std::function<void(BitStreamWriter&, float)> writerFunc = &BitStreamWriter::writeFloat16;
602
1
    std::function<float(BitStreamReader&)> readerFunc = &BitStreamReader::readFloat16;
603
604
1
    testImpl(values, writerFunc, readerFunc, 15);
605
1
}
606
607
TEST_F(BitStreamTest, readFloat32)
608
1
{
609
1
    const std::array<float, 6> values = {2.0, -2.0, 0.6171875, 0.875, 9.875, 42.5};
610
611
1
    std::function<void(BitStreamWriter&, float)> writerFunc = &BitStreamWriter::writeFloat32;
612
1
    std::function<float(BitStreamReader&)> readerFunc = &BitStreamReader::readFloat32;
613
614
1
    testImpl(values, writerFunc, readerFunc, 31);
615
1
}
616
617
TEST_F(BitStreamTest, readFloat64)
618
1
{
619
1
    const std::array<double, 6> values = {2.0, -2.0, 0.6171875, 0.875, 9.875, 42.5};
620
621
1
    std::function<void(BitStreamWriter&, double)> writerFunc = &BitStreamWriter::writeFloat64;
622
1
    std::function<double(BitStreamReader&)> readerFunc = &BitStreamReader::readFloat64;
623
624
1
    testImpl(values, writerFunc, readerFunc, 61);
625
1
}
626
627
TEST_F(BitStreamTest, readString)
628
1
{
629
1
    const std::array<std::string, 3> values = {
630
1
            "Hello World", "\n\t%^@(*aAzZ01234569$%^!?<>[]](){}-=+~:;/|\\\"\'Hello World2\0nonWrittenPart",
631
1
            "Price: \xE2\x82\xAC 3 what's this? -> \xC2\xA2" /* '€' '¢' */
632
1
    };
633
634
1
    std::function<void(BitStreamWriter&, const std::string&)> writerFunc = &BitStreamWriter::writeString;
635
1
    std::function<std::string(BitStreamReader&)> readerFunc = std::bind(
636
1
            &BitStreamReader::readString<std::allocator<char>>, std::placeholders::_1, std::allocator<char>());
637
638
1
    testImpl(values, writerFunc, readerFunc, 7);
639
1
}
640
641
TEST_F(BitStreamTest, readBool)
642
1
{
643
1
    const std::array<bool, 2> values = {true, false};
644
645
1
    std::function<void(BitStreamWriter&, bool)> writerFunc = &BitStreamWriter::writeBool;
646
1
    std::function<bool(BitStreamReader&)> readerFunc = &BitStreamReader::readBool;
647
648
1
    testImpl(values, writerFunc, readerFunc, 1);
649
1
}
650
651
TEST_F(BitStreamTest, readBitBuffer)
652
1
{
653
1
    const std::array<BitBuffer, 2> values = {BitBuffer(std::vector<uint8_t>({0xAB, 0xE0}), 11),
654
1
            BitBuffer(std::vector<uint8_t>({0xAB, 0xCD, 0xFE}), 23)};
655
656
1
    std::function<void(BitStreamWriter&, const BitBuffer&)> writerFunc =
657
1
            &BitStreamWriter::writeBitBuffer<std::allocator<uint8_t>>;
658
1
    std::function<BitBuffer(BitStreamReader&)> readerFunc = std::bind(
659
1
            &BitStreamReader::readBitBuffer<std::allocator<uint8_t>>, std::placeholders::_1,
660
1
            std::allocator<uint8_t>());
661
662
1
    testImpl(values, writerFunc, readerFunc, 7);
663
1
}
664
665
TEST_F(BitStreamTest, readBytes)
666
1
{
667
1
    const std::array<vector<uint8_t>, 2> values = {
668
1
            vector<uint8_t>{{0, 255}},
669
1
            vector<uint8_t>{{1, 127, 128, 254}},
670
1
    };
671
672
1
    std::function<void(BitStreamWriter&, const vector<uint8_t>&)> writerFunc = &BitStreamWriter::writeBytes;
673
1
    std::function<vector<uint8_t>(BitStreamReader&)> readerFunc = std::bind(
674
1
            &BitStreamReader::readBytes<std::allocator<uint8_t>>, std::placeholders::_1,
675
1
            std::allocator<uint8_t>());
676
677
1
    testImpl(values, writerFunc, readerFunc, 7);
678
1
}
679
680
TEST_F(BitStreamTest, setBitPosition)
681
1
{
682
1
    testSetBitPosition(m_externalWriter);
683
1
    testSetBitPosition(m_dummyWriter);
684
1
}
685
686
TEST_F(BitStreamTest, alignTo)
687
1
{
688
1
    testAlignTo(m_externalWriter);
689
1
    testAlignTo(m_dummyWriter);
690
1
}
691
692
} // namespace zserio