Coverage Report

Created: 2024-07-18 11:41

test/zserio/BitBufferTest.cpp
Line
Count
Source
1
#include <array>
2
#include <utility>
3
#include <vector>
4
5
#include "gtest/gtest.h"
6
#include "zserio/BitBuffer.h"
7
#include "zserio/CppRuntimeException.h"
8
9
#include "TrackingAllocator.h"
10
11
namespace zserio
12
{
13
14
TEST(BitBufferTest, emptyConstructor)
15
1
{
16
1
    const BitBuffer bitBuffer;
17
1
    ASSERT_EQ(0, bitBuffer.getBitSize());
18
1
    ASSERT_EQ(0, bitBuffer.getByteSize());
19
1
}
20
21
TEST(BitBufferTest, allocatorConstructor)
22
1
{
23
1
    const std::allocator<uint8_t> allocator;
24
1
    const BitBuffer bitBuffer(allocator);
25
1
    ASSERT_EQ(0, bitBuffer.getBitSize());
26
1
    ASSERT_EQ(0, bitBuffer.getByteSize());
27
1
}
28
29
TEST(BitBufferTest, bitSizeConstructor)
30
1
{
31
1
    const size_t bitSize = 11;
32
1
    const BitBuffer bitBuffer(bitSize);
33
1
    ASSERT_EQ(bitSize, bitBuffer.getBitSize());
34
1
}
35
36
TEST(BitBufferTest, spanConstructor)
37
1
{
38
    // vector
39
1
    std::vector<uint8_t> buffer1(2);
40
1
    const BitBuffer bitBuffer1(buffer1);
41
1
    ASSERT_EQ(8 * buffer1.size(), bitBuffer1.getBitSize());
42
43
1
    const size_t emptyBitSize = 0;
44
1
    const std::vector<uint8_t> emptyBuffer;
45
1
    const BitBuffer emptyBitBuffer(emptyBuffer);
46
1
    ASSERT_EQ(emptyBitSize, emptyBitBuffer.getBitSize());
47
48
    // const vector
49
1
    const std::vector<uint8_t> buffer2(2);
50
1
    const BitBuffer bitBuffer2(buffer2);
51
1
    ASSERT_EQ(8 * buffer2.size(), bitBuffer2.getBitSize());
52
53
    // array
54
1
    std::array<uint8_t, 2> buffer3{};
55
1
    const BitBuffer bitBuffer3(buffer3);
56
1
    ASSERT_EQ(8 * buffer3.size(), bitBuffer3.getBitSize());
57
58
    // const array
59
1
    const std::array<uint8_t, 2> buffer4{};
60
1
    const BitBuffer bitBuffer4(buffer4);
61
1
    ASSERT_EQ(8 * buffer4.size(), bitBuffer4.getBitSize());
62
63
    // span
64
1
    std::array<uint8_t, 2> arrayBuffer5{};
65
1
    Span<uint8_t> buffer5(arrayBuffer5);
66
1
    const BitBuffer bitBuffer5(buffer5);
67
1
    ASSERT_EQ(8 * buffer5.size(), bitBuffer5.getBitSize());
68
69
    // const span
70
1
    const std::array<uint8_t, 2> arrayBuffer6{};
71
1
    Span<const uint8_t> buffer6(arrayBuffer6);
72
1
    const BitBuffer bitBuffer6(buffer6);
73
1
    ASSERT_EQ(8 * buffer6.size(), bitBuffer6.getBitSize());
74
1
}
75
76
TEST(BitBufferTest, spanBitSizeConstructor)
77
1
{
78
    // vector
79
1
    const size_t bitSize = 11;
80
1
    std::vector<uint8_t> buffer1((bitSize + 7) / 8);
81
1
    const BitBuffer bitBuffer1(buffer1, bitSize);
82
1
    ASSERT_EQ(bitSize, bitBuffer1.getBitSize());
83
84
1
    const size_t emptyBitSize = 0;
85
1
    const std::vector<uint8_t> emptyBuffer;
86
1
    const BitBuffer emptyBitBuffer(emptyBuffer, emptyBitSize);
87
1
    ASSERT_EQ(emptyBitSize, emptyBitBuffer.getBitSize());
88
89
1
    const size_t outOfRangeBitSize = 9;
90
1
    const std::vector<uint8_t> outOfRangeBuffer(1);
91
1
    ASSERT_THROW(BitBuffer(outOfRangeBuffer, outOfRangeBitSize), CppRuntimeException);
92
93
    // const vector
94
1
    const std::vector<uint8_t> buffer2((bitSize + 7) / 8);
95
1
    const BitBuffer bitBuffer2(buffer2, bitSize);
96
1
    ASSERT_EQ(bitSize, bitBuffer2.getBitSize());
97
98
    // array
99
1
    std::array<uint8_t, 2> buffer3{};
100
1
    const BitBuffer bitBuffer3(buffer3, bitSize);
101
1
    ASSERT_EQ(bitSize, bitBuffer3.getBitSize());
102
103
    // const array
104
1
    const std::array<uint8_t, 2> buffer4{};
105
1
    const BitBuffer bitBuffer4(buffer4, bitSize);
106
1
    ASSERT_EQ(bitSize, bitBuffer4.getBitSize());
107
108
    // span
109
1
    std::array<uint8_t, 2> arrayBuffer5{};
110
1
    Span<uint8_t> buffer5(arrayBuffer5);
111
1
    const BitBuffer bitBuffer5(buffer5, bitSize);
112
1
    ASSERT_EQ(bitSize, bitBuffer5.getBitSize());
113
114
    // const span
115
1
    const std::array<uint8_t, 2> arrayBuffer6{};
116
1
    Span<const uint8_t> buffer6(arrayBuffer6);
117
1
    const BitBuffer bitBuffer6(buffer6, bitSize);
118
1
    ASSERT_EQ(bitSize, bitBuffer6.getBitSize());
119
1
}
120
121
TEST(BitBufferTest, vectorMoveConstructor)
122
1
{
123
1
    const size_t byteSize = 2;
124
1
    std::vector<uint8_t> buffer(byteSize);
125
1
    const uint8_t* bufferStart = buffer.data();
126
1
    const BitBuffer bitBuffer(std::move(buffer));
127
1
    ASSERT_EQ(8 * byteSize, bitBuffer.getBitSize());
128
1
    ASSERT_EQ(bufferStart, bitBuffer.getBuffer());
129
1
}
130
131
TEST(BitBufferTest, vectorBitSizeMoveConstructor)
132
1
{
133
1
    const size_t bitSize = 11;
134
1
    std::vector<uint8_t> buffer((bitSize + 7) / 8);
135
1
    const uint8_t* bufferStart = buffer.data();
136
1
    const BitBuffer bitBuffer(std::move(buffer), bitSize);
137
1
    ASSERT_EQ(bitSize, bitBuffer.getBitSize());
138
1
    ASSERT_EQ(bufferStart, bitBuffer.getBuffer());
139
140
1
    const size_t outOfRangeBitSize = 9;
141
1
    ASSERT_THROW(BitBuffer(std::vector<uint8_t>(1), outOfRangeBitSize), CppRuntimeException);
142
1
}
143
144
TEST(BitBufferTest, rawPointerConstructor)
145
1
{
146
1
    const size_t bitSize = 11;
147
1
    const std::vector<uint8_t> buffer((bitSize + 7) / 8);
148
1
    const BitBuffer bitBuffer(buffer.data(), bitSize);
149
1
    ASSERT_EQ(bitSize, bitBuffer.getBitSize());
150
151
1
    const size_t emptyBitSize = 0;
152
1
    const std::vector<uint8_t> emptyBuffer;
153
1
    const BitBuffer emptyBitBuffer(emptyBuffer.data(), emptyBitSize);
154
1
    ASSERT_EQ(emptyBitSize, emptyBitBuffer.getBitSize());
155
1
}
156
157
TEST(BitBufferTest, copyConstructor)
158
1
{
159
1
    const size_t bitSize = 11;
160
1
    const std::vector<uint8_t> buffer = {0xAB, 0xE0};
161
1
    const BitBuffer bitBuffer(buffer, bitSize);
162
163
1
    const BitBuffer copiedBitBuffer(bitBuffer);
164
1
    ASSERT_EQ(bitBuffer.getBitSize(), copiedBitBuffer.getBitSize());
165
1
    ASSERT_EQ(bitBuffer.getByteSize(), copiedBitBuffer.getByteSize());
166
1
    const Span<const uint8_t> copiedBuffer = copiedBitBuffer.getData();
167
1
    size_t index = 0;
168
1
    for (uint8_t element : buffer)
169
2
    {
170
2
        ASSERT_EQ(element, copiedBuffer[index]);
171
2
        ++index;
172
2
    }
173
1
}
174
175
TEST(BitBufferTest, copyConstructorWithAllocator)
176
1
{
177
1
    const TrackingAllocator<uint8_t> allocator;
178
1
    const size_t bitSize = 11;
179
1
    const std::array<uint8_t, 2> data = {0xAB, 0xE0};
180
1
    Span<const uint8_t> buffer(data);
181
1
    const BasicBitBuffer<TrackingAllocator<uint8_t>> bitBuffer(buffer, bitSize, allocator);
182
1
    const size_t numAllocations = allocator.numAllocs();
183
184
1
    const TrackingAllocator<uint8_t> newAllocator;
185
1
    const BasicBitBuffer<TrackingAllocator<uint8_t>> copiedBitBuffer(bitBuffer, newAllocator);
186
1
    ASSERT_EQ(bitBuffer.getBitSize(), copiedBitBuffer.getBitSize());
187
1
    ASSERT_EQ(bitBuffer.getByteSize(), copiedBitBuffer.getByteSize());
188
1
    const Span<const uint8_t> copiedBuffer = copiedBitBuffer.getData();
189
1
    size_t index = 0;
190
1
    for (uint8_t element : buffer)
191
2
    {
192
2
        ASSERT_EQ(element, copiedBuffer[index]);
193
2
        ++index;
194
2
    }
195
1
    ASSERT_EQ(numAllocations, allocator.numAllocs());
196
1
    ASSERT_NE(0, newAllocator.numAllocs());
197
1
}
198
199
TEST(BitBufferTest, assignmentOperator)
200
1
{
201
1
    const size_t bitSize = 11;
202
1
    const std::vector<uint8_t> buffer = {0xAB, 0xE0};
203
1
    const BitBuffer bitBuffer(buffer, bitSize);
204
205
1
    BitBuffer copiedBitBuffer;
206
1
    copiedBitBuffer = bitBuffer;
207
1
    ASSERT_EQ(bitBuffer.getBitSize(), copiedBitBuffer.getBitSize());
208
1
    ASSERT_EQ(bitBuffer.getByteSize(), copiedBitBuffer.getByteSize());
209
1
    const Span<const uint8_t> copiedBuffer = copiedBitBuffer.getData();
210
1
    size_t index = 0;
211
1
    for (uint8_t element : buffer)
212
2
    {
213
2
        ASSERT_EQ(element, copiedBuffer[index]);
214
2
        ++index;
215
2
    }
216
217
1
    BitBuffer anotherBitBuffer;
218
1
    const void* origDataAddress = &copiedBitBuffer.getData()[0];
219
1
    anotherBitBuffer = std::move(copiedBitBuffer);
220
1
    ASSERT_EQ(bitBuffer.getBitSize(), anotherBitBuffer.getBitSize());
221
1
    ASSERT_EQ(bitBuffer.getByteSize(), anotherBitBuffer.getByteSize());
222
1
    ASSERT_EQ(origDataAddress, &anotherBitBuffer.getData()[0]);
223
1
}
224
225
TEST(BitBufferTest, moveConstructor)
226
1
{
227
1
    const size_t bitSize = 11;
228
1
    const std::vector<uint8_t> buffer = {0xAB, 0xE0};
229
1
    const size_t byteSize = buffer.size();
230
1
    BitBuffer bitBuffer(buffer, bitSize);
231
1
    const uint8_t* bufferStart = &bitBuffer.getData()[0];
232
233
1
    const BitBuffer movedBitBuffer(std::move(bitBuffer));
234
1
    ASSERT_EQ(bitSize, movedBitBuffer.getBitSize());
235
1
    ASSERT_EQ(byteSize, movedBitBuffer.getByteSize());
236
1
    ASSERT_EQ(bufferStart, movedBitBuffer.getBuffer());
237
1
}
238
239
TEST(BitBufferTest, moveConstructorWithAllocator)
240
1
{
241
1
    const TrackingAllocator<uint8_t> allocator;
242
1
    const size_t bitSize = 11;
243
1
    const std::array<uint8_t, 2> data = {0xAB, 0xE0};
244
1
    Span<const uint8_t> buffer(data);
245
1
    const size_t byteSize = buffer.size();
246
1
    BasicBitBuffer<TrackingAllocator<uint8_t>> bitBuffer(buffer, bitSize, allocator);
247
1
    const size_t numAllocations = allocator.numAllocs();
248
249
1
    const TrackingAllocator<uint8_t> newAllocator;
250
1
    const BasicBitBuffer<TrackingAllocator<uint8_t>> movedBitBuffer(std::move(bitBuffer), newAllocator);
251
1
    ASSERT_EQ(bitSize, movedBitBuffer.getBitSize());
252
1
    ASSERT_EQ(byteSize, movedBitBuffer.getByteSize());
253
1
    ASSERT_EQ(numAllocations, allocator.numAllocs());
254
1
    ASSERT_NE(0, newAllocator.numAllocs());
255
1
}
256
257
TEST(BitBufferTest, moveAssignmentOperator)
258
1
{
259
1
    const size_t bitSize = 11;
260
1
    const std::vector<uint8_t> buffer = {0xAB, 0xE0};
261
1
    const size_t byteSize = buffer.size();
262
1
    BitBuffer bitBuffer(buffer, bitSize);
263
1
    const uint8_t* bufferStart = bitBuffer.getBuffer();
264
265
1
    const BitBuffer movedBitBuffer = std::move(bitBuffer);
266
1
    ASSERT_EQ(bitSize, movedBitBuffer.getBitSize());
267
1
    ASSERT_EQ(byteSize, movedBitBuffer.getByteSize());
268
1
    ASSERT_EQ(bufferStart, movedBitBuffer.getBuffer());
269
1
}
270
271
TEST(BitBufferTest, operatorEquality)
272
1
{
273
1
    const size_t bitSize = 11;
274
1
    const BitBuffer bitBuffer1(std::vector<uint8_t>({0xAB, 0xE0}), bitSize);
275
1
    const BitBuffer bitBuffer2(std::vector<uint8_t>({0xAB, 0xF0}), bitSize);
276
1
    ASSERT_TRUE(bitBuffer1 == bitBuffer2);
277
278
1
    const BitBuffer bitBuffer3(std::vector<uint8_t>({0xAB, 0xFF}), bitSize);
279
1
    ASSERT_TRUE(bitBuffer1 == bitBuffer3);
280
281
1
    const BitBuffer bitBuffer4(std::vector<uint8_t>({0xAB, 0xC0}), bitSize);
282
1
    ASSERT_FALSE(bitBuffer1 == bitBuffer4);
283
284
1
    const BitBuffer bitBuffer5(std::vector<uint8_t>({0xBA, 0xE0}), bitSize);
285
1
    ASSERT_FALSE(bitBuffer1 == bitBuffer5);
286
287
1
    const BitBuffer bitBuffer6(std::vector<uint8_t>({0xAB}));
288
1
    ASSERT_FALSE(bitBuffer1 == bitBuffer6);
289
290
1
    const BitBuffer bitBuffer7;
291
1
    ASSERT_FALSE(bitBuffer1 == bitBuffer7);
292
1
}
293
294
TEST(BitBufferTest, operatorLessThan)
295
1
{
296
1
    const BitBuffer bitBufferEmpty1;
297
1
    const BitBuffer bitBufferEmpty2;
298
1
    ASSERT_FALSE(bitBufferEmpty1 < bitBufferEmpty2);
299
1
    ASSERT_FALSE(bitBufferEmpty2 < bitBufferEmpty1);
300
301
1
    const BitBuffer bitBufferByte1(std::vector<uint8_t>({0xAB}), 8);
302
1
    const BitBuffer bitBufferByte2(std::vector<uint8_t>({0xAC}), 8);
303
1
    ASSERT_TRUE(bitBufferByte1 < bitBufferByte2);
304
1
    ASSERT_FALSE(bitBufferByte2 < bitBufferByte1);
305
306
1
    const BitBuffer bitBuffer1(std::vector<uint8_t>({0xAB, 0xE0}), 11);
307
1
    ASSERT_TRUE(bitBufferEmpty1 < bitBuffer1);
308
1
    ASSERT_TRUE(bitBufferByte1 < bitBuffer1);
309
1
    ASSERT_FALSE(bitBuffer1 < bitBufferEmpty1);
310
1
    ASSERT_FALSE(bitBuffer1 < bitBufferByte1);
311
312
1
    const BitBuffer bitBuffer1Copy(bitBuffer1);
313
1
    ASSERT_FALSE(bitBuffer1 < bitBuffer1Copy);
314
1
    ASSERT_FALSE(bitBuffer1Copy < bitBuffer1);
315
316
1
    const BitBuffer bitBuffer2(std::vector<uint8_t>({0xAB, 0xF0}), 11);
317
1
    ASSERT_FALSE(bitBuffer1 < bitBuffer2);
318
1
    ASSERT_FALSE(bitBuffer2 < bitBuffer1);
319
320
1
    const BitBuffer bitBuffer3(std::vector<uint8_t>({0xAB, 0x00}), 11);
321
1
    ASSERT_TRUE(bitBuffer3 < bitBuffer1);
322
1
    ASSERT_FALSE(bitBuffer1 < bitBuffer3);
323
324
1
    const BitBuffer bitBuffer4(std::vector<uint8_t>({0x00, 0x00}), 11);
325
1
    ASSERT_TRUE(bitBuffer4 < bitBuffer1);
326
1
    ASSERT_FALSE(bitBuffer1 < bitBuffer4);
327
328
1
    const BitBuffer bitBuffer5(std::vector<uint8_t>({0xAB, 0xE0, 0x00}), 20);
329
1
    ASSERT_TRUE(bitBuffer1 < bitBuffer5);
330
1
    ASSERT_FALSE(bitBuffer5 < bitBuffer1);
331
1
}
332
333
TEST(BitBufferTest, hashCode)
334
1
{
335
1
    const size_t bitSize = 11;
336
1
    const BitBuffer bitBuffer1(std::vector<uint8_t>({0xAB, 0xE0}), bitSize);
337
1
    const BitBuffer bitBuffer2(std::vector<uint8_t>({0xAB, 0xF0}), bitSize);
338
1
    ASSERT_EQ(bitBuffer1.hashCode(), bitBuffer2.hashCode());
339
340
1
    const BitBuffer bitBuffer3(std::vector<uint8_t>({0xAB, 0xFF}), bitSize);
341
1
    ASSERT_EQ(bitBuffer1.hashCode(), bitBuffer3.hashCode());
342
343
1
    const BitBuffer bitBuffer4(std::vector<uint8_t>({0xAB, 0xC0}), bitSize);
344
1
    ASSERT_NE(bitBuffer1.hashCode(), bitBuffer4.hashCode());
345
346
1
    const BitBuffer bitBuffer5(std::vector<uint8_t>({0xBA, 0xE0}), bitSize);
347
1
    ASSERT_NE(bitBuffer1.hashCode(), bitBuffer5.hashCode());
348
349
1
    const BitBuffer bitBuffer6(std::vector<uint8_t>({0xAB}));
350
1
    ASSERT_NE(bitBuffer1.hashCode(), bitBuffer6.hashCode());
351
352
1
    const BitBuffer bitBuffer7;
353
1
    ASSERT_NE(bitBuffer1.hashCode(), bitBuffer7.hashCode());
354
1
}
355
356
TEST(BitBufferTest, constGetBuffer)
357
1
{
358
1
    const size_t bitSize = 11;
359
1
    const std::vector<uint8_t> buffer = {0xAB, 0xC0};
360
1
    const BitBuffer bitBuffer(buffer, bitSize);
361
362
1
    const uint8_t* readBuffer = bitBuffer.getBuffer();
363
1
    for (uint8_t element : buffer)
364
2
    {
365
2
        ASSERT_EQ(element, *readBuffer);
366
2
        readBuffer++;
367
2
    }
368
1
}
369
370
TEST(BitBufferTest, getBuffer)
371
1
{
372
1
    const size_t bitSize = 11;
373
1
    const std::vector<uint8_t> buffer = {0xAB, 0xC0};
374
1
    BitBuffer bitBuffer(buffer, bitSize);
375
376
1
    uint8_t* readBuffer = bitBuffer.getBuffer();
377
1
    for (uint8_t element : buffer)
378
2
    {
379
2
        ASSERT_EQ(element, *readBuffer);
380
2
        readBuffer++;
381
2
    }
382
1
}
383
384
TEST(BitBufferTest, getBitSize)
385
1
{
386
1
    const size_t bitSize = 11;
387
1
    const std::vector<uint8_t> buffer = {0xAB, 0xC0};
388
1
    const BitBuffer bitBuffer(buffer, bitSize);
389
1
    ASSERT_EQ(bitSize, bitBuffer.getBitSize());
390
1
}
391
392
TEST(BitBufferTest, getByteSize)
393
1
{
394
1
    const size_t bitSize = 11;
395
1
    const std::vector<uint8_t> buffer = {0xAB, 0xC0};
396
1
    const size_t byteSize = buffer.size();
397
1
    const BitBuffer bitBuffer(buffer, bitSize);
398
1
    ASSERT_EQ(byteSize, bitBuffer.getByteSize());
399
1
}
400
401
TEST(BitBufferTest, getBytes)
402
1
{
403
1
    const size_t bitSize = 11;
404
1
    const std::vector<uint8_t> buffer = {0xAB, 0xC0};
405
1
    const BitBuffer bitBuffer(buffer, bitSize);
406
407
1
    const std::vector<uint8_t>& bytes = bitBuffer.getBytes();
408
1
    ASSERT_EQ(buffer.size(), bytes.size());
409
3
    
for (size_t i = 0; 1
i < buffer.size();
++i2
)
410
2
    {
411
2
        ASSERT_EQ(buffer[i], bytes[i]);
412
2
    }
413
1
}
414
415
TEST(BitBufferTest, getData)
416
1
{
417
1
    const size_t bitSize = 11;
418
1
    const std::vector<uint8_t> buffer = {0xAB, 0xC0};
419
1
    const BitBuffer bitBuffer(buffer, bitSize);
420
421
1
    const Span<const uint8_t> bytes = bitBuffer.getData();
422
1
    ASSERT_EQ(buffer.size(), bytes.size());
423
3
    
for (size_t i = 0; 1
i < buffer.size();
++i2
)
424
2
    {
425
2
        ASSERT_EQ(buffer[i], bytes[i]);
426
2
    }
427
1
}
428
429
TEST(BitBufferTest, cppRuntimeExceptionOperator)
430
1
{
431
1
    CppRuntimeException exception = CppRuntimeException() << BitBuffer();
432
1
    ASSERT_STREQ("BitBuffer([...], 0)", exception.what());
433
1
}
434
435
} // namespace zserio