GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: test/zserio/BitBufferTest.cpp Lines: 281 281 100.0 %
Date: 2023-12-13 14:51:09 Branches: 610 1832 33.3 %

Line Branch Exec Source
1
#include <utility>
2
#include <vector>
3
#include <array>
4
5
#include "gtest/gtest.h"
6
7
#include "zserio/CppRuntimeException.h"
8
#include "zserio/BitBuffer.h"
9
10
#include "TrackingAllocator.h"
11
12
namespace zserio
13
{
14
15


802
TEST(BitBufferTest, emptyConstructor)
16
{
17
2
    const BitBuffer bitBuffer;
18



1
    ASSERT_EQ(0, bitBuffer.getBitSize());
19



1
    ASSERT_EQ(0, bitBuffer.getByteSize());
20
}
21
22


802
TEST(BitBufferTest, allocatorConstructor)
23
{
24
2
    const std::allocator<uint8_t> allocator;
25
2
    const BitBuffer bitBuffer(allocator);
26



1
    ASSERT_EQ(0, bitBuffer.getBitSize());
27



1
    ASSERT_EQ(0, bitBuffer.getByteSize());
28
}
29
30


802
TEST(BitBufferTest, bitSizeConstructor)
31
{
32
1
    const size_t bitSize = 11;
33
2
    const BitBuffer bitBuffer(bitSize);
34



1
    ASSERT_EQ(bitSize, bitBuffer.getBitSize());
35
}
36
37


802
TEST(BitBufferTest, spanConstructor)
38
{
39
    // vector
40
2
    std::vector<uint8_t> buffer1(2);
41

2
    const BitBuffer bitBuffer1(buffer1);
42



1
    ASSERT_EQ(8 * buffer1.size(), bitBuffer1.getBitSize());
43
44
1
    const size_t emptyBitSize = 0;
45
2
    const std::vector<uint8_t> emptyBuffer;
46

2
    const BitBuffer emptyBitBuffer(emptyBuffer);
47



1
    ASSERT_EQ(emptyBitSize, emptyBitBuffer.getBitSize());
48
49
    // const vector
50

2
    const std::vector<uint8_t> buffer2(2);
51

2
    const BitBuffer bitBuffer2(buffer2);
52



1
    ASSERT_EQ(8 * buffer2.size(), bitBuffer2.getBitSize());
53
54
    // array
55
1
    std::array<uint8_t, 2> buffer3{};
56

2
    const BitBuffer bitBuffer3(buffer3);
57



1
    ASSERT_EQ(8 * buffer3.size(), bitBuffer3.getBitSize());
58
59
    // const array
60
1
    const std::array<uint8_t, 2> buffer4{};
61

2
    const BitBuffer bitBuffer4(buffer4);
62



1
    ASSERT_EQ(8 * buffer4.size(), bitBuffer4.getBitSize());
63
64
    // span
65
1
    std::array<uint8_t, 2> arrayBuffer5{};
66
1
    Span<uint8_t> buffer5(arrayBuffer5);
67

2
    const BitBuffer bitBuffer5(buffer5);
68



1
    ASSERT_EQ(8 * buffer5.size(), bitBuffer5.getBitSize());
69
70
    // const span
71
1
    const std::array<uint8_t, 2> arrayBuffer6{};
72
1
    Span<const uint8_t> buffer6(arrayBuffer6);
73

2
    const BitBuffer bitBuffer6(buffer6);
74



1
    ASSERT_EQ(8 * buffer6.size(), bitBuffer6.getBitSize());
75
}
76
77


802
TEST(BitBufferTest, spanBitSizeConstructor)
78
{
79
    // vector
80
1
    const size_t bitSize = 11;
81
2
    std::vector<uint8_t> buffer1((bitSize + 7) / 8);
82

2
    const BitBuffer bitBuffer1(buffer1, bitSize);
83



1
    ASSERT_EQ(bitSize, bitBuffer1.getBitSize());
84
85
1
    const size_t emptyBitSize = 0;
86
2
    const std::vector<uint8_t> emptyBuffer;
87

2
    const BitBuffer emptyBitBuffer(emptyBuffer, emptyBitSize);
88



1
    ASSERT_EQ(emptyBitSize, emptyBitBuffer.getBitSize());
89
90
1
    const size_t outOfRangeBitSize = 9;
91

2
    const std::vector<uint8_t> outOfRangeBuffer(1);
92










2
    ASSERT_THROW(BitBuffer(outOfRangeBuffer, outOfRangeBitSize), CppRuntimeException);
93
94
    // const vector
95

2
    const std::vector<uint8_t> buffer2((bitSize + 7) / 8);
96

2
    const BitBuffer bitBuffer2(buffer2, bitSize);
97



1
    ASSERT_EQ(bitSize, bitBuffer2.getBitSize());
98
99
    // array
100
1
    std::array<uint8_t, 2> buffer3{};
101

2
    const BitBuffer bitBuffer3(buffer3, bitSize);
102



1
    ASSERT_EQ(bitSize, bitBuffer3.getBitSize());
103
104
    // const array
105
1
    const std::array<uint8_t, 2> buffer4{};
106

2
    const BitBuffer bitBuffer4(buffer4, bitSize);
107



1
    ASSERT_EQ(bitSize, bitBuffer4.getBitSize());
108
109
    // span
110
1
    std::array<uint8_t, 2> arrayBuffer5{};
111
1
    Span<uint8_t> buffer5(arrayBuffer5);
112

2
    const BitBuffer bitBuffer5(buffer5, bitSize);
113



1
    ASSERT_EQ(bitSize, bitBuffer5.getBitSize());
114
115
    // const span
116
1
    const std::array<uint8_t, 2> arrayBuffer6{};
117
1
    Span<const uint8_t> buffer6(arrayBuffer6);
118

2
    const BitBuffer bitBuffer6(buffer6, bitSize);
119



1
    ASSERT_EQ(bitSize, bitBuffer6.getBitSize());
120
}
121
122


802
TEST(BitBufferTest, vectorMoveConstructor)
123
{
124
1
    const size_t byteSize = 2;
125
2
    std::vector<uint8_t> buffer(byteSize);
126
1
    const uint8_t* bufferStart = buffer.data();
127
2
    const BitBuffer bitBuffer(std::move(buffer));
128



1
    ASSERT_EQ(8 * byteSize, bitBuffer.getBitSize());
129



1
    ASSERT_EQ(bufferStart, bitBuffer.getBuffer());
130
}
131
132


802
TEST(BitBufferTest, vectorBitSizeMoveConstructor)
133
{
134
1
    const size_t bitSize = 11;
135
2
    std::vector<uint8_t> buffer((bitSize + 7) / 8);
136
1
    const uint8_t* bufferStart = buffer.data();
137

2
    const BitBuffer bitBuffer(std::move(buffer), bitSize);
138



1
    ASSERT_EQ(bitSize, bitBuffer.getBitSize());
139



1
    ASSERT_EQ(bufferStart, bitBuffer.getBuffer());
140
141
1
    const size_t outOfRangeBitSize = 9;
142











2
    ASSERT_THROW(BitBuffer(std::vector<uint8_t>(1), outOfRangeBitSize), CppRuntimeException);
143
}
144
145


802
TEST(BitBufferTest, rawPointerConstructor)
146
{
147
1
    const size_t bitSize = 11;
148
2
    const std::vector<uint8_t> buffer((bitSize + 7) / 8);
149

2
    const BitBuffer bitBuffer(buffer.data(), bitSize);
150



1
    ASSERT_EQ(bitSize, bitBuffer.getBitSize());
151
152
1
    const size_t emptyBitSize = 0;
153
2
    const std::vector<uint8_t> emptyBuffer;
154

2
    const BitBuffer emptyBitBuffer(emptyBuffer.data(), emptyBitSize);
155



1
    ASSERT_EQ(emptyBitSize, emptyBitBuffer.getBitSize());
156
}
157
158


802
TEST(BitBufferTest, copyConstructor)
159
{
160
1
    const size_t bitSize = 11;
161
2
    const std::vector<uint8_t> buffer = {0xAB, 0xE0};
162

2
    const BitBuffer bitBuffer(buffer, bitSize);
163
164

2
    const BitBuffer copiedBitBuffer(bitBuffer);
165



1
    ASSERT_EQ(bitBuffer.getBitSize(), copiedBitBuffer.getBitSize());
166



1
    ASSERT_EQ(bitBuffer.getByteSize(), copiedBitBuffer.getByteSize());
167
1
    const Span<const uint8_t> copiedBuffer = copiedBitBuffer.getData();
168
1
    size_t index = 0;
169

3
    for (uint8_t element : buffer)
170
    {
171



2
        ASSERT_EQ(element, copiedBuffer[index]);
172
2
        ++index;
173
    }
174
}
175
176


802
TEST(BitBufferTest, copyConstructorWithAllocator)
177
{
178
2
    const TrackingAllocator<uint8_t> allocator;
179
1
    const size_t bitSize = 11;
180
1
    const std::array<uint8_t, 2> data = {0xAB, 0xE0};
181
1
    Span<const uint8_t> buffer(data);
182

2
    const BasicBitBuffer<TrackingAllocator<uint8_t>> bitBuffer(buffer, bitSize, allocator);
183
1
    const size_t numAllocations = allocator.numAllocs();
184
185

2
    const TrackingAllocator<uint8_t> newAllocator;
186

2
    const BasicBitBuffer<TrackingAllocator<uint8_t>> copiedBitBuffer(bitBuffer, newAllocator);
187



1
    ASSERT_EQ(bitBuffer.getBitSize(), copiedBitBuffer.getBitSize());
188



1
    ASSERT_EQ(bitBuffer.getByteSize(), copiedBitBuffer.getByteSize());
189
1
    const Span<const uint8_t> copiedBuffer = copiedBitBuffer.getData();
190
1
    size_t index = 0;
191
3
    for (uint8_t element : buffer)
192
    {
193



2
        ASSERT_EQ(element, copiedBuffer[index]);
194
2
        ++index;
195
    }
196



1
    ASSERT_EQ(numAllocations, allocator.numAllocs());
197



1
    ASSERT_NE(0, newAllocator.numAllocs());
198
}
199
200


802
TEST(BitBufferTest, assignmentOperator)
201
{
202
1
    const size_t bitSize = 11;
203
2
    const std::vector<uint8_t> buffer = {0xAB, 0xE0};
204

2
    const BitBuffer bitBuffer(buffer, bitSize);
205
206
2
    BitBuffer copiedBitBuffer;
207
1
    copiedBitBuffer = bitBuffer;
208



1
    ASSERT_EQ(bitBuffer.getBitSize(), copiedBitBuffer.getBitSize());
209



1
    ASSERT_EQ(bitBuffer.getByteSize(), copiedBitBuffer.getByteSize());
210
1
    const Span<const uint8_t> copiedBuffer = copiedBitBuffer.getData();
211
1
    size_t index = 0;
212
3
    for (uint8_t element : buffer)
213
    {
214



2
        ASSERT_EQ(element, copiedBuffer[index]);
215
2
        ++index;
216
    }
217
218
2
    BitBuffer anotherBitBuffer;
219
1
    const void* origDataAddress = &copiedBitBuffer.getData()[0];
220
1
    anotherBitBuffer = std::move(copiedBitBuffer);
221



1
    ASSERT_EQ(bitBuffer.getBitSize(), anotherBitBuffer.getBitSize());
222



1
    ASSERT_EQ(bitBuffer.getByteSize(), anotherBitBuffer.getByteSize());
223



1
    ASSERT_EQ(origDataAddress, &anotherBitBuffer.getData()[0]);
224
}
225
226


802
TEST(BitBufferTest, moveConstructor)
227
{
228
1
    const size_t bitSize = 11;
229
2
    const std::vector<uint8_t> buffer = {0xAB, 0xE0};
230
1
    const size_t byteSize = buffer.size();
231

2
    BitBuffer bitBuffer(buffer, bitSize);
232
1
    const uint8_t* bufferStart = &bitBuffer.getData()[0];
233
234
2
    const BitBuffer movedBitBuffer(std::move(bitBuffer));
235



1
    ASSERT_EQ(bitSize, movedBitBuffer.getBitSize());
236



1
    ASSERT_EQ(byteSize, movedBitBuffer.getByteSize());
237



1
    ASSERT_EQ(bufferStart, movedBitBuffer.getBuffer());
238
}
239
240


802
TEST(BitBufferTest, moveConstructorWithAllocator)
241
{
242
2
    const TrackingAllocator<uint8_t> allocator;
243
1
    const size_t bitSize = 11;
244
1
    const std::array<uint8_t, 2> data = {0xAB, 0xE0};
245
1
    Span<const uint8_t> buffer(data);
246
1
    const size_t byteSize = buffer.size();
247

2
    BasicBitBuffer<TrackingAllocator<uint8_t>> bitBuffer(buffer, bitSize, allocator);
248
1
    const size_t numAllocations = allocator.numAllocs();
249
250

2
    const TrackingAllocator<uint8_t> newAllocator;
251

2
    const BasicBitBuffer<TrackingAllocator<uint8_t>> movedBitBuffer(std::move(bitBuffer), newAllocator);
252



1
    ASSERT_EQ(bitSize, movedBitBuffer.getBitSize());
253



1
    ASSERT_EQ(byteSize, movedBitBuffer.getByteSize());
254



1
    ASSERT_EQ(numAllocations, allocator.numAllocs());
255



1
    ASSERT_NE(0, newAllocator.numAllocs());
256
}
257
258


802
TEST(BitBufferTest, moveAssignmentOperator)
259
{
260
1
    const size_t bitSize = 11;
261
2
    const std::vector<uint8_t> buffer = {0xAB, 0xE0};
262
1
    const size_t byteSize = buffer.size();
263

2
    BitBuffer bitBuffer(buffer, bitSize);
264
1
    const uint8_t* bufferStart = bitBuffer.getBuffer();
265
266
2
    const BitBuffer movedBitBuffer = std::move(bitBuffer);
267



1
    ASSERT_EQ(bitSize, movedBitBuffer.getBitSize());
268



1
    ASSERT_EQ(byteSize, movedBitBuffer.getByteSize());
269



1
    ASSERT_EQ(bufferStart, movedBitBuffer.getBuffer());
270
}
271
272


802
TEST(BitBufferTest, operatorEquality)
273
{
274
1
    const size_t bitSize = 11;
275

2
    const BitBuffer bitBuffer1(std::vector<uint8_t>({0xAB, 0xE0}), bitSize);
276

2
    const BitBuffer bitBuffer2(std::vector<uint8_t>({0xAB, 0xF0}), bitSize);
277



1
    ASSERT_TRUE(bitBuffer1 == bitBuffer2);
278
279

2
    const BitBuffer bitBuffer3(std::vector<uint8_t>({0xAB, 0xFF}), bitSize);
280



1
    ASSERT_TRUE(bitBuffer1 == bitBuffer3);
281
282

2
    const BitBuffer bitBuffer4(std::vector<uint8_t>({0xAB, 0xC0}), bitSize);
283



1
    ASSERT_FALSE(bitBuffer1 == bitBuffer4);
284
285

2
    const BitBuffer bitBuffer5(std::vector<uint8_t>({0xBA, 0xE0}), bitSize);
286



1
    ASSERT_FALSE(bitBuffer1 == bitBuffer5);
287
288

2
    const BitBuffer bitBuffer6(std::vector<uint8_t>({0xAB}));
289



1
    ASSERT_FALSE(bitBuffer1 == bitBuffer6);
290
291
2
    const BitBuffer bitBuffer7;
292




1
    ASSERT_FALSE(bitBuffer1 == bitBuffer7);
293
}
294
295


802
TEST(BitBufferTest, operatorLessThan)
296
{
297
2
    const BitBuffer bitBufferEmpty1;
298
2
    const BitBuffer bitBufferEmpty2;
299



1
    ASSERT_FALSE(bitBufferEmpty1 < bitBufferEmpty2);
300



1
    ASSERT_FALSE(bitBufferEmpty2 < bitBufferEmpty1);
301
302

2
    const BitBuffer bitBufferByte1(std::vector<uint8_t>({0xAB}), 8);
303

2
    const BitBuffer bitBufferByte2(std::vector<uint8_t>({0xAC}), 8);
304



1
    ASSERT_TRUE(bitBufferByte1 < bitBufferByte2);
305



1
    ASSERT_FALSE(bitBufferByte2 < bitBufferByte1);
306
307

2
    const BitBuffer bitBuffer1(std::vector<uint8_t>({0xAB, 0xE0}), 11);
308



1
    ASSERT_TRUE(bitBufferEmpty1 < bitBuffer1);
309



1
    ASSERT_TRUE(bitBufferByte1 < bitBuffer1);
310



1
    ASSERT_FALSE(bitBuffer1 < bitBufferEmpty1);
311



1
    ASSERT_FALSE(bitBuffer1 < bitBufferByte1);
312
313

2
    const BitBuffer bitBuffer1Copy(bitBuffer1);
314



1
    ASSERT_FALSE(bitBuffer1 < bitBuffer1Copy);
315



1
    ASSERT_FALSE(bitBuffer1Copy < bitBuffer1);
316
317

2
    const BitBuffer bitBuffer2(std::vector<uint8_t>({0xAB, 0xF0}), 11);
318



1
    ASSERT_FALSE(bitBuffer1 < bitBuffer2);
319



1
    ASSERT_FALSE(bitBuffer2 < bitBuffer1);
320
321

2
    const BitBuffer bitBuffer3(std::vector<uint8_t>({0xAB, 0x00}), 11);
322



1
    ASSERT_TRUE(bitBuffer3 < bitBuffer1);
323



1
    ASSERT_FALSE(bitBuffer1 < bitBuffer3);
324
325

2
    const BitBuffer bitBuffer4(std::vector<uint8_t>({0x00, 0x00}), 11);
326



1
    ASSERT_TRUE(bitBuffer4 < bitBuffer1);
327



1
    ASSERT_FALSE(bitBuffer1 < bitBuffer4);
328
329

2
    const BitBuffer bitBuffer5(std::vector<uint8_t>({0xAB, 0xE0, 0x00}), 20);
330



1
    ASSERT_TRUE(bitBuffer1 < bitBuffer5);
331




1
    ASSERT_FALSE(bitBuffer5 < bitBuffer1);
332
}
333
334


802
TEST(BitBufferTest, hashCode)
335
{
336
1
    const size_t bitSize = 11;
337

2
    const BitBuffer bitBuffer1(std::vector<uint8_t>({0xAB, 0xE0}), bitSize);
338

2
    const BitBuffer bitBuffer2(std::vector<uint8_t>({0xAB, 0xF0}), bitSize);
339




1
    ASSERT_EQ(bitBuffer1.hashCode(), bitBuffer2.hashCode());
340
341

2
    const BitBuffer bitBuffer3(std::vector<uint8_t>({0xAB, 0xFF}), bitSize);
342




1
    ASSERT_EQ(bitBuffer1.hashCode(), bitBuffer3.hashCode());
343
344

2
    const BitBuffer bitBuffer4(std::vector<uint8_t>({0xAB, 0xC0}), bitSize);
345




1
    ASSERT_NE(bitBuffer1.hashCode(), bitBuffer4.hashCode());
346
347

2
    const BitBuffer bitBuffer5(std::vector<uint8_t>({0xBA, 0xE0}), bitSize);
348




1
    ASSERT_NE(bitBuffer1.hashCode(), bitBuffer5.hashCode());
349
350

2
    const BitBuffer bitBuffer6(std::vector<uint8_t>({0xAB}));
351




1
    ASSERT_NE(bitBuffer1.hashCode(), bitBuffer6.hashCode());
352
353
2
    const BitBuffer bitBuffer7;
354




1
    ASSERT_NE(bitBuffer1.hashCode(), bitBuffer7.hashCode());
355
}
356
357


802
TEST(BitBufferTest, constGetBuffer)
358
{
359
1
    const size_t bitSize = 11;
360
2
    const std::vector<uint8_t> buffer = {0xAB, 0xC0};
361

2
    const BitBuffer bitBuffer(buffer, bitSize);
362
363
1
    const uint8_t* readBuffer = bitBuffer.getBuffer();
364

3
    for (uint8_t element : buffer)
365
    {
366



2
        ASSERT_EQ(element, *readBuffer);
367
2
        readBuffer++;
368
    }
369
}
370
371


802
TEST(BitBufferTest, getBuffer)
372
{
373
1
    const size_t bitSize = 11;
374
2
    const std::vector<uint8_t> buffer = {0xAB, 0xC0};
375

2
    BitBuffer bitBuffer(buffer, bitSize);
376
377
1
    uint8_t* readBuffer = bitBuffer.getBuffer();
378

3
    for (uint8_t element : buffer)
379
    {
380



2
        ASSERT_EQ(element, *readBuffer);
381
2
        readBuffer++;
382
    }
383
}
384
385


802
TEST(BitBufferTest, getBitSize)
386
{
387
1
    const size_t bitSize = 11;
388
2
    const std::vector<uint8_t> buffer = {0xAB, 0xC0};
389

2
    const BitBuffer bitBuffer(buffer, bitSize);
390



1
    ASSERT_EQ(bitSize, bitBuffer.getBitSize());
391
}
392
393


802
TEST(BitBufferTest, getByteSize)
394
{
395
1
    const size_t bitSize = 11;
396
2
    const std::vector<uint8_t> buffer = {0xAB, 0xC0};
397
1
    const size_t byteSize = buffer.size();
398

2
    const BitBuffer bitBuffer(buffer, bitSize);
399



1
    ASSERT_EQ(byteSize, bitBuffer.getByteSize());
400
}
401
402


802
TEST(BitBufferTest, getBytes)
403
{
404
1
    const size_t bitSize = 11;
405
2
    const std::vector<uint8_t> buffer = {0xAB, 0xC0};
406

2
    const BitBuffer bitBuffer(buffer, bitSize);
407
408
1
    const std::vector<uint8_t>& bytes = bitBuffer.getBytes();
409



1
    ASSERT_EQ(buffer.size(), bytes.size());
410

3
    for (size_t i = 0; i < buffer.size(); ++i)
411
    {
412



2
        ASSERT_EQ(buffer[i], bytes[i]);
413
    }
414
}
415
416


802
TEST(BitBufferTest, getData)
417
{
418
1
    const size_t bitSize = 11;
419
2
    const std::vector<uint8_t> buffer = {0xAB, 0xC0};
420

2
    const BitBuffer bitBuffer(buffer, bitSize);
421
422
1
    const Span<const uint8_t> bytes = bitBuffer.getData();
423



1
    ASSERT_EQ(buffer.size(), bytes.size());
424

3
    for (size_t i = 0; i < buffer.size(); ++i)
425
    {
426



2
        ASSERT_EQ(buffer[i], bytes[i]);
427
    }
428
}
429
430


802
TEST(BitBufferTest, cppRuntimeExceptionOperator)
431
{
432

2
    CppRuntimeException exception = CppRuntimeException() << BitBuffer();
433



1
    ASSERT_STREQ("BitBuffer([...], 0)", exception.what());
434
}
435
436

2394
} // namespace zserio