Coverage Report

Created: 2023-12-13 14:58

test/zserio/BitBufferTest.cpp
Line
Count
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
TEST(BitBufferTest, emptyConstructor)
16
1
{
17
1
    const BitBuffer bitBuffer;
18
1
    ASSERT_EQ(0, bitBuffer.getBitSize());
19
1
    ASSERT_EQ(0, bitBuffer.getByteSize());
20
1
}
21
22
TEST(BitBufferTest, allocatorConstructor)
23
1
{
24
1
    const std::allocator<uint8_t> allocator;
25
1
    const BitBuffer bitBuffer(allocator);
26
1
    ASSERT_EQ(0, bitBuffer.getBitSize());
27
1
    ASSERT_EQ(0, bitBuffer.getByteSize());
28
1
}
29
30
TEST(BitBufferTest, bitSizeConstructor)
31
1
{
32
1
    const size_t bitSize = 11;
33
1
    const BitBuffer bitBuffer(bitSize);
34
1
    ASSERT_EQ(bitSize, bitBuffer.getBitSize());
35
1
}
36
37
TEST(BitBufferTest, spanConstructor)
38
1
{
39
    // vector
40
1
    std::vector<uint8_t> buffer1(2);
41
1
    const BitBuffer bitBuffer1(buffer1);
42
1
    ASSERT_EQ(8 * buffer1.size(), bitBuffer1.getBitSize());
43
44
1
    const size_t emptyBitSize = 0;
45
1
    const std::vector<uint8_t> emptyBuffer;
46
1
    const BitBuffer emptyBitBuffer(emptyBuffer);
47
1
    ASSERT_EQ(emptyBitSize, emptyBitBuffer.getBitSize());
48
49
    // const vector
50
1
    const std::vector<uint8_t> buffer2(2);
51
1
    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
1
    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
1
    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
1
    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
1
    const BitBuffer bitBuffer6(buffer6);
74
1
    ASSERT_EQ(8 * buffer6.size(), bitBuffer6.getBitSize());
75
1
}
76
77
TEST(BitBufferTest, spanBitSizeConstructor)
78
1
{
79
    // vector
80
1
    const size_t bitSize = 11;
81
1
    std::vector<uint8_t> buffer1((bitSize + 7) / 8);
82
1
    const BitBuffer bitBuffer1(buffer1, bitSize);
83
1
    ASSERT_EQ(bitSize, bitBuffer1.getBitSize());
84
85
1
    const size_t emptyBitSize = 0;
86
1
    const std::vector<uint8_t> emptyBuffer;
87
1
    const BitBuffer emptyBitBuffer(emptyBuffer, emptyBitSize);
88
1
    ASSERT_EQ(emptyBitSize, emptyBitBuffer.getBitSize());
89
90
1
    const size_t outOfRangeBitSize = 9;
91
1
    const std::vector<uint8_t> outOfRangeBuffer(1);
92
1
    ASSERT_THROW(BitBuffer(outOfRangeBuffer, outOfRangeBitSize), CppRuntimeException);
93
94
    // const vector
95
1
    const std::vector<uint8_t> buffer2((bitSize + 7) / 8);
96
1
    const BitBuffer bitBuffer2(buffer2, bitSize);
97
1
    ASSERT_EQ(bitSize, bitBuffer2.getBitSize());
98
99
    // array
100
1
    std::array<uint8_t, 2> buffer3{};
101
1
    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
1
    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
1
    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
1
    const BitBuffer bitBuffer6(buffer6, bitSize);
119
1
    ASSERT_EQ(bitSize, bitBuffer6.getBitSize());
120
1
}
121
122
TEST(BitBufferTest, vectorMoveConstructor)
123
1
{
124
1
    const size_t byteSize = 2;
125
1
    std::vector<uint8_t> buffer(byteSize);
126
1
    const uint8_t* bufferStart = buffer.data();
127
1
    const BitBuffer bitBuffer(std::move(buffer));
128
1
    ASSERT_EQ(8 * byteSize, bitBuffer.getBitSize());
129
1
    ASSERT_EQ(bufferStart, bitBuffer.getBuffer());
130
1
}
131
132
TEST(BitBufferTest, vectorBitSizeMoveConstructor)
133
1
{
134
1
    const size_t bitSize = 11;
135
1
    std::vector<uint8_t> buffer((bitSize + 7) / 8);
136
1
    const uint8_t* bufferStart = buffer.data();
137
1
    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
1
    ASSERT_THROW(BitBuffer(std::vector<uint8_t>(1), outOfRangeBitSize), CppRuntimeException);
143
1
}
144
145
TEST(BitBufferTest, rawPointerConstructor)
146
1
{
147
1
    const size_t bitSize = 11;
148
1
    const std::vector<uint8_t> buffer((bitSize + 7) / 8);
149
1
    const BitBuffer bitBuffer(buffer.data(), bitSize);
150
1
    ASSERT_EQ(bitSize, bitBuffer.getBitSize());
151
152
1
    const size_t emptyBitSize = 0;
153
1
    const std::vector<uint8_t> emptyBuffer;
154
1
    const BitBuffer emptyBitBuffer(emptyBuffer.data(), emptyBitSize);
155
1
    ASSERT_EQ(emptyBitSize, emptyBitBuffer.getBitSize());
156
1
}
157
158
TEST(BitBufferTest, copyConstructor)
159
1
{
160
1
    const size_t bitSize = 11;
161
1
    const std::vector<uint8_t> buffer = {0xAB, 0xE0};
162
1
    const BitBuffer bitBuffer(buffer, bitSize);
163
164
1
    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
1
    for (uint8_t element : buffer)
170
2
    {
171
2
        ASSERT_EQ(element, copiedBuffer[index]);
172
2
        ++index;
173
2
    }
174
1
}
175
176
TEST(BitBufferTest, copyConstructorWithAllocator)
177
1
{
178
1
    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
1
    const BasicBitBuffer<TrackingAllocator<uint8_t>> bitBuffer(buffer, bitSize, allocator);
183
1
    const size_t numAllocations = allocator.numAllocs();
184
185
1
    const TrackingAllocator<uint8_t> newAllocator;
186
1
    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
1
    for (uint8_t element : buffer)
192
2
    {
193
2
        ASSERT_EQ(element, copiedBuffer[index]);
194
2
        ++index;
195
2
    }
196
1
    ASSERT_EQ(numAllocations, allocator.numAllocs());
197
1
    ASSERT_NE(0, newAllocator.numAllocs());
198
1
}
199
200
TEST(BitBufferTest, assignmentOperator)
201
1
{
202
1
    const size_t bitSize = 11;
203
1
    const std::vector<uint8_t> buffer = {0xAB, 0xE0};
204
1
    const BitBuffer bitBuffer(buffer, bitSize);
205
206
1
    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
1
    for (uint8_t element : buffer)
213
2
    {
214
2
        ASSERT_EQ(element, copiedBuffer[index]);
215
2
        ++index;
216
2
    }
217
218
1
    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
1
}
225
226
TEST(BitBufferTest, moveConstructor)
227
1
{
228
1
    const size_t bitSize = 11;
229
1
    const std::vector<uint8_t> buffer = {0xAB, 0xE0};
230
1
    const size_t byteSize = buffer.size();
231
1
    BitBuffer bitBuffer(buffer, bitSize);
232
1
    const uint8_t* bufferStart = &bitBuffer.getData()[0];
233
234
1
    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
1
}
239
240
TEST(BitBufferTest, moveConstructorWithAllocator)
241
1
{
242
1
    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
1
    BasicBitBuffer<TrackingAllocator<uint8_t>> bitBuffer(buffer, bitSize, allocator);
248
1
    const size_t numAllocations = allocator.numAllocs();
249
250
1
    const TrackingAllocator<uint8_t> newAllocator;
251
1
    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
1
}
257
258
TEST(BitBufferTest, moveAssignmentOperator)
259
1
{
260
1
    const size_t bitSize = 11;
261
1
    const std::vector<uint8_t> buffer = {0xAB, 0xE0};
262
1
    const size_t byteSize = buffer.size();
263
1
    BitBuffer bitBuffer(buffer, bitSize);
264
1
    const uint8_t* bufferStart = bitBuffer.getBuffer();
265
266
1
    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
1
}
271
272
TEST(BitBufferTest, operatorEquality)
273
1
{
274
1
    const size_t bitSize = 11;
275
1
    const BitBuffer bitBuffer1(std::vector<uint8_t>({0xAB, 0xE0}), bitSize);
276
1
    const BitBuffer bitBuffer2(std::vector<uint8_t>({0xAB, 0xF0}), bitSize);
277
1
    ASSERT_TRUE(bitBuffer1 == bitBuffer2);
278
279
1
    const BitBuffer bitBuffer3(std::vector<uint8_t>({0xAB, 0xFF}), bitSize);
280
1
    ASSERT_TRUE(bitBuffer1 == bitBuffer3);
281
282
1
    const BitBuffer bitBuffer4(std::vector<uint8_t>({0xAB, 0xC0}), bitSize);
283
1
    ASSERT_FALSE(bitBuffer1 == bitBuffer4);
284
285
1
    const BitBuffer bitBuffer5(std::vector<uint8_t>({0xBA, 0xE0}), bitSize);
286
1
    ASSERT_FALSE(bitBuffer1 == bitBuffer5);
287
288
1
    const BitBuffer bitBuffer6(std::vector<uint8_t>({0xAB}));
289
1
    ASSERT_FALSE(bitBuffer1 == bitBuffer6);
290
291
1
    const BitBuffer bitBuffer7;
292
1
    ASSERT_FALSE(bitBuffer1 == bitBuffer7);
293
1
}
294
295
TEST(BitBufferTest, operatorLessThan)
296
1
{
297
1
    const BitBuffer bitBufferEmpty1;
298
1
    const BitBuffer bitBufferEmpty2;
299
1
    ASSERT_FALSE(bitBufferEmpty1 < bitBufferEmpty2);
300
1
    ASSERT_FALSE(bitBufferEmpty2 < bitBufferEmpty1);
301
302
1
    const BitBuffer bitBufferByte1(std::vector<uint8_t>({0xAB}), 8);
303
1
    const BitBuffer bitBufferByte2(std::vector<uint8_t>({0xAC}), 8);
304
1
    ASSERT_TRUE(bitBufferByte1 < bitBufferByte2);
305
1
    ASSERT_FALSE(bitBufferByte2 < bitBufferByte1);
306
307
1
    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
1
    const BitBuffer bitBuffer1Copy(bitBuffer1);
314
1
    ASSERT_FALSE(bitBuffer1 < bitBuffer1Copy);
315
1
    ASSERT_FALSE(bitBuffer1Copy < bitBuffer1);
316
317
1
    const BitBuffer bitBuffer2(std::vector<uint8_t>({0xAB, 0xF0}), 11);
318
1
    ASSERT_FALSE(bitBuffer1 < bitBuffer2);
319
1
    ASSERT_FALSE(bitBuffer2 < bitBuffer1);
320
321
1
    const BitBuffer bitBuffer3(std::vector<uint8_t>({0xAB, 0x00}), 11);
322
1
    ASSERT_TRUE(bitBuffer3 < bitBuffer1);
323
1
    ASSERT_FALSE(bitBuffer1 < bitBuffer3);
324
325
1
    const BitBuffer bitBuffer4(std::vector<uint8_t>({0x00, 0x00}), 11);
326
1
    ASSERT_TRUE(bitBuffer4 < bitBuffer1);
327
1
    ASSERT_FALSE(bitBuffer1 < bitBuffer4);
328
329
1
    const BitBuffer bitBuffer5(std::vector<uint8_t>({0xAB, 0xE0, 0x00}), 20);
330
1
    ASSERT_TRUE(bitBuffer1 < bitBuffer5);
331
1
    ASSERT_FALSE(bitBuffer5 < bitBuffer1);
332
1
}
333
334
TEST(BitBufferTest, hashCode)
335
1
{
336
1
    const size_t bitSize = 11;
337
1
    const BitBuffer bitBuffer1(std::vector<uint8_t>({0xAB, 0xE0}), bitSize);
338
1
    const BitBuffer bitBuffer2(std::vector<uint8_t>({0xAB, 0xF0}), bitSize);
339
1
    ASSERT_EQ(bitBuffer1.hashCode(), bitBuffer2.hashCode());
340
341
1
    const BitBuffer bitBuffer3(std::vector<uint8_t>({0xAB, 0xFF}), bitSize);
342
1
    ASSERT_EQ(bitBuffer1.hashCode(), bitBuffer3.hashCode());
343
344
1
    const BitBuffer bitBuffer4(std::vector<uint8_t>({0xAB, 0xC0}), bitSize);
345
1
    ASSERT_NE(bitBuffer1.hashCode(), bitBuffer4.hashCode());
346
347
1
    const BitBuffer bitBuffer5(std::vector<uint8_t>({0xBA, 0xE0}), bitSize);
348
1
    ASSERT_NE(bitBuffer1.hashCode(), bitBuffer5.hashCode());
349
350
1
    const BitBuffer bitBuffer6(std::vector<uint8_t>({0xAB}));
351
1
    ASSERT_NE(bitBuffer1.hashCode(), bitBuffer6.hashCode());
352
353
1
    const BitBuffer bitBuffer7;
354
1
    ASSERT_NE(bitBuffer1.hashCode(), bitBuffer7.hashCode());
355
1
}
356
357
TEST(BitBufferTest, constGetBuffer)
358
1
{
359
1
    const size_t bitSize = 11;
360
1
    const std::vector<uint8_t> buffer = {0xAB, 0xC0};
361
1
    const BitBuffer bitBuffer(buffer, bitSize);
362
363
1
    const uint8_t* readBuffer = bitBuffer.getBuffer();
364
1
    for (uint8_t element : buffer)
365
2
    {
366
2
        ASSERT_EQ(element, *readBuffer);
367
2
        readBuffer++;
368
2
    }
369
1
}
370
371
TEST(BitBufferTest, getBuffer)
372
1
{
373
1
    const size_t bitSize = 11;
374
1
    const std::vector<uint8_t> buffer = {0xAB, 0xC0};
375
1
    BitBuffer bitBuffer(buffer, bitSize);
376
377
1
    uint8_t* readBuffer = bitBuffer.getBuffer();
378
1
    for (uint8_t element : buffer)
379
2
    {
380
2
        ASSERT_EQ(element, *readBuffer);
381
2
        readBuffer++;
382
2
    }
383
1
}
384
385
TEST(BitBufferTest, getBitSize)
386
1
{
387
1
    const size_t bitSize = 11;
388
1
    const std::vector<uint8_t> buffer = {0xAB, 0xC0};
389
1
    const BitBuffer bitBuffer(buffer, bitSize);
390
1
    ASSERT_EQ(bitSize, bitBuffer.getBitSize());
391
1
}
392
393
TEST(BitBufferTest, getByteSize)
394
1
{
395
1
    const size_t bitSize = 11;
396
1
    const std::vector<uint8_t> buffer = {0xAB, 0xC0};
397
1
    const size_t byteSize = buffer.size();
398
1
    const BitBuffer bitBuffer(buffer, bitSize);
399
1
    ASSERT_EQ(byteSize, bitBuffer.getByteSize());
400
1
}
401
402
TEST(BitBufferTest, getBytes)
403
1
{
404
1
    const size_t bitSize = 11;
405
1
    const std::vector<uint8_t> buffer = {0xAB, 0xC0};
406
1
    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; 1
i < buffer.size();
++i2
)
411
2
    {
412
2
        ASSERT_EQ(buffer[i], bytes[i]);
413
2
    }
414
1
}
415
416
TEST(BitBufferTest, getData)
417
1
{
418
1
    const size_t bitSize = 11;
419
1
    const std::vector<uint8_t> buffer = {0xAB, 0xC0};
420
1
    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; 1
i < buffer.size();
++i2
)
425
2
    {
426
2
        ASSERT_EQ(buffer[i], bytes[i]);
427
2
    }
428
1
}
429
430
TEST(BitBufferTest, cppRuntimeExceptionOperator)
431
1
{
432
1
    CppRuntimeException exception = CppRuntimeException() << BitBuffer();
433
1
    ASSERT_STREQ("BitBuffer([...], 0)", exception.what());
434
1
}
435
436
} // namespace zserio