Coverage Report

Created: 2023-12-13 14:58

test/zserio/ArrayTest.cpp
Line
Count
Source
1
#include <string>
2
#include <vector>
3
#include <limits>
4
#include <array>
5
6
#include "gtest/gtest.h"
7
8
#include "zserio/Array.h"
9
#include "zserio/ArrayTraits.h"
10
#include "zserio/Enums.h"
11
#include "zserio/CppRuntimeException.h"
12
#include "zserio/BitBuffer.h"
13
14
#include "test_object/std_allocator/ArrayBitmask.h"
15
#include "test_object/std_allocator/ArrayEnum.h"
16
#include "test_object/std_allocator/ArrayObject.h"
17
#include "test_object/std_allocator/ArrayParamObject.h"
18
19
namespace zserio
20
{
21
22
using ArrayEnum = test_object::std_allocator::ArrayEnum;
23
using ArrayBitmask = test_object::std_allocator::ArrayBitmask;
24
using ArrayObject = test_object::std_allocator::ArrayObject;
25
using ArrayParamObject = test_object::std_allocator::ArrayParamObject;
26
27
namespace
28
{
29
30
class ArrayTestOwner
31
{};
32
33
class ArrayTestOwnerWithBitSize
34
{
35
public:
36
    explicit ArrayTestOwnerWithBitSize(uint8_t bitSize) :
37
            m_bitSize(bitSize)
38
7
    {}
39
40
    uint8_t getBitSize() const
41
3.44k
    {
42
3.44k
        return m_bitSize;
43
3.44k
    }
44
45
private:
46
    uint8_t m_bitSize;
47
};
48
49
template <typename ARRAY, typename OWNER_TYPE>
50
size_t arrayBitSizeOf(const ARRAY& array, const OWNER_TYPE& owner, size_t bitPosition)
51
304
{
52
304
    return array.bitSizeOf(owner, bitPosition);
53
304
}
54
55
template <typename ARRAY>
56
size_t arrayBitSizeOf(const ARRAY& array, const detail::DummyArrayOwner&, size_t bitPosition)
57
2.11k
{
58
2.11k
    return array.bitSizeOf(bitPosition);
59
2.11k
}
60
61
template <typename ARRAY, typename OWNER_TYPE>
62
size_t arrayBitSizeOfPacked(const ARRAY& array, const OWNER_TYPE& owner, size_t bitPosition)
63
96
{
64
96
    return array.bitSizeOfPacked(owner, bitPosition);
65
96
}
66
67
template <typename ARRAY>
68
size_t arrayBitSizeOfPacked(const ARRAY& array, const detail::DummyArrayOwner&, size_t bitPosition)
69
800
{
70
800
    return array.bitSizeOfPacked(bitPosition);
71
800
}
72
73
template <typename ARRAY, typename OWNER_TYPE>
74
size_t arrayInitializeOffsets(ARRAY& array, OWNER_TYPE& owner, size_t bitPosition)
75
304
{
76
304
    return array.initializeOffsets(owner, bitPosition);
77
304
}
78
79
template <typename ARRAY>
80
size_t arrayInitializeOffsets(ARRAY& array, detail::DummyArrayOwner&, size_t bitPosition)
81
2.11k
{
82
2.11k
    return array.initializeOffsets(bitPosition);
83
2.11k
}
84
85
template <typename ARRAY, typename OWNER_TYPE>
86
size_t arrayInitializeOffsetsPacked(ARRAY& array, OWNER_TYPE& owner, size_t bitPosition)
87
96
{
88
96
    return array.initializeOffsetsPacked(owner, bitPosition);
89
96
}
90
91
template <typename ARRAY>
92
size_t arrayInitializeOffsetsPacked(ARRAY& array, detail::DummyArrayOwner&, size_t bitPosition)
93
800
{
94
800
    return array.initializeOffsetsPacked(bitPosition);
95
800
}
96
97
template <typename ARRAY, typename OWNER_TYPE>
98
void arrayRead(ARRAY& array, OWNER_TYPE& owner, BitStreamReader& in, size_t arrayLength = 0)
99
304
{
100
304
    array.read(owner, in, arrayLength);
101
304
}
102
103
template <typename ARRAY>
104
void arrayRead(ARRAY& array, detail::DummyArrayOwner&, BitStreamReader& in, size_t arrayLength = 0)
105
2.11k
{
106
2.11k
    array.read(in, arrayLength);
107
2.11k
}
108
109
template <typename ARRAY, typename OWNER_TYPE>
110
void arrayReadPacked(ARRAY& array, OWNER_TYPE& owner, BitStreamReader& in, size_t arrayLength = 0)
111
96
{
112
96
    array.readPacked(owner, in, arrayLength);
113
96
}
114
115
template <typename ARRAY>
116
void arrayReadPacked(ARRAY& array, detail::DummyArrayOwner&, BitStreamReader& in, size_t arrayLength = 0)
117
800
{
118
800
    array.readPacked(in, arrayLength);
119
800
}
120
121
template <typename ARRAY, typename OWNER_TYPE>
122
void arrayWrite(const ARRAY& array, const OWNER_TYPE& owner, BitStreamWriter& out)
123
304
{
124
304
    array.write(owner, out);
125
304
}
126
127
template <typename ARRAY>
128
void arrayWrite(const ARRAY& array, const detail::DummyArrayOwner&, BitStreamWriter& out)
129
2.11k
{
130
2.11k
    array.write(out);
131
2.11k
}
132
133
template <typename ARRAY, typename OWNER_TYPE>
134
void arrayWritePacked(const ARRAY& array, const OWNER_TYPE& owner, BitStreamWriter& out)
135
96
{
136
96
    array.writePacked(owner, out);
137
96
}
138
139
template <typename ARRAY>
140
void arrayWritePacked(const ARRAY& array, const detail::DummyArrayOwner&, BitStreamWriter& out)
141
800
{
142
800
    array.writePacked(out);
143
800
}
144
145
class ElementBitSizeWithOwner
146
{
147
public:
148
    using OwnerType = ArrayTestOwnerWithBitSize;
149
150
    static uint8_t get(const ArrayTestOwnerWithBitSize& owner)
151
3.44k
    {
152
3.44k
        return owner.getBitSize();
153
3.44k
    }
154
};
155
156
template <uint8_t BIT_SIZE>
157
class ElementBitSizeWithoutOwner
158
{
159
public:
160
    static uint8_t get()
161
2.63k
    {
162
2.63k
        return BIT_SIZE;
163
2.63k
    }
164
};
165
166
class ArrayObjectArrayExpressions
167
{
168
public:
169
    using OwnerType = ArrayTestOwner;
170
171
    static void initializeOffset(ArrayTestOwner&, size_t, size_t)
172
96
    {}
173
174
    static void checkOffset(const ArrayTestOwner&, size_t, size_t)
175
192
    {}
176
};
177
178
class ArrayObjectElementFactory
179
{
180
public:
181
    using OwnerType = ArrayTestOwner;
182
    using allocator_type = std::allocator<uint8_t>;
183
184
    static void create(OwnerType&, std::vector<ArrayObject>& array, BitStreamReader& in, size_t)
185
96
    {
186
96
        array.emplace_back(in, array.get_allocator());
187
96
    }
188
189
    static void create(OwnerType&, std::vector<ArrayObject>& array,
190
            ArrayObject::ZserioPackingContext& contextNode, BitStreamReader& in, size_t)
191
96
    {
192
96
        array.emplace_back(contextNode, in, array.get_allocator());
193
96
    }
194
};
195
196
struct ArrayParamObjectOwner
197
{
198
    ArrayObject arrayObject;
199
};
200
201
class ArrayParamObjectArrayExpressions
202
{
203
public:
204
    using OwnerType = ArrayParamObjectOwner;
205
206
    static void initializeOffset(ArrayParamObjectOwner&, size_t, size_t)
207
96
    {}
208
209
    static void checkOffset(const ArrayParamObjectOwner&, size_t, size_t)
210
192
    {}
211
212
    static void initializeElement(ArrayParamObjectOwner& owner, ArrayParamObject& element, size_t)
213
192
    {
214
192
        element.initialize(owner.arrayObject);
215
192
    }
216
217
    static bool checkInitialization(const ArrayParamObjectOwner& owner, const ArrayParamObject& element)
218
192
    {
219
192
        return owner.arrayObject == element.getParam();
220
192
    }
221
};
222
223
class ArrayParamObjectElementFactory
224
{
225
public:
226
    using OwnerType = ArrayParamObjectOwner;
227
228
    static void create(ArrayParamObjectOwner& owner,
229
            ::zserio::vector<ArrayParamObject>& array, ::zserio::BitStreamReader& in, size_t)
230
96
    {
231
96
        array.emplace_back(in, owner.arrayObject, array.get_allocator());
232
96
    }
233
234
    static void create(ArrayParamObjectOwner& owner,
235
            ::zserio::vector<ArrayParamObject>& array, ArrayParamObject::ZserioPackingContext& context,
236
            ::zserio::BitStreamReader& in, size_t)
237
96
    {
238
96
        array.emplace_back(context, in, owner.arrayObject, array.get_allocator());
239
96
    }
240
};
241
242
} // namespace
243
244
class ArrayTest : public ::testing::Test
245
{
246
public:
247
    ArrayTest() :
248
            m_byteBuffer()
249
61
    {}
250
251
protected:
252
    template <typename ARRAY_TRAITS, typename RAW_ARRAY,
253
            typename ARRAY_EXPRESSIONS = detail::DummyArrayExpressions,
254
            typename OWNER_TYPE = typename detail::array_owner_type<ARRAY_TRAITS, ARRAY_EXPRESSIONS>::type,
255
            typename std::enable_if<!std::is_integral<OWNER_TYPE>::value, int>::type = 0>
256
    void testArray(const RAW_ARRAY& rawArray, size_t elementBitSize, OWNER_TYPE owner = OWNER_TYPE())
257
54
    {
258
54
        const size_t arraySize = rawArray.size();
259
54
        const size_t unalignedBitSize = elementBitSize * arraySize;
260
54
        const size_t alignedBitSize = (arraySize > 0)
261
54
                ? 
alignTo(8, elementBitSize) * (arraySize - 1) + elementBitSize38
262
54
                : 
016
;
263
54
        testArray<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(
264
54
                rawArray, unalignedBitSize, alignedBitSize, owner);
265
54
    }
266
267
    template <typename ARRAY_TRAITS, typename RAW_ARRAY,
268
            typename ARRAY_EXPRESSIONS = detail::DummyArrayExpressions,
269
            typename OWNER_TYPE = typename detail::array_owner_type<ARRAY_TRAITS, ARRAY_EXPRESSIONS>::type>
270
    void testArray(const RAW_ARRAY& rawArray, size_t unalignedBitSize, size_t alignedBitSize,
271
            OWNER_TYPE owner = OWNER_TYPE())
272
72
    {
273
72
        testArrayNormal<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(rawArray, unalignedBitSize, owner);
274
72
        testArrayAuto<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(
275
72
                rawArray, AUTO_LENGTH_BIT_SIZE + unalignedBitSize, owner);
276
72
        testArrayAligned<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(rawArray, alignedBitSize, owner);
277
72
        testArrayAlignedAuto<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(
278
72
                rawArray, AUTO_LENGTH_BIT_SIZE + alignedBitSize, owner);
279
72
        testArrayImplicit<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(rawArray, unalignedBitSize, owner);
280
72
    }
281
282
    template <typename ARRAY_TRAITS, typename RAW_ARRAY,
283
            typename ARRAY_EXPRESSIONS = detail::DummyArrayExpressions,
284
            typename OWNER_TYPE = typename detail::array_owner_type<ARRAY_TRAITS, ARRAY_EXPRESSIONS>::type>
285
    void testPackedArray(const RAW_ARRAY& rawArray, OWNER_TYPE owner = OWNER_TYPE())
286
18
    {
287
18
        testPackedArray<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(
288
18
                rawArray, UNKNOWN_BIT_SIZE, UNKNOWN_BIT_SIZE, owner);
289
18
    }
290
291
    template <typename ARRAY_TRAITS, typename RAW_ARRAY,
292
            typename ARRAY_EXPRESSIONS = detail::DummyArrayExpressions,
293
            typename OWNER_TYPE = typename detail::array_owner_type<ARRAY_TRAITS, ARRAY_EXPRESSIONS>::type>
294
    void testPackedArray(const RAW_ARRAY& rawArray, size_t unalignedBitSize, size_t alignedBitSize,
295
            OWNER_TYPE owner = OWNER_TYPE())
296
28
    {
297
28
        testPackedArrayNormal<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(
298
28
                rawArray, unalignedBitSize, owner);
299
28
        testPackedArrayAuto<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(
300
28
                rawArray, (unalignedBitSize != UNKNOWN_BIT_SIZE)
301
28
                        ? 
AUTO_LENGTH_BIT_SIZE + unalignedBitSize10
:
UNKNOWN_BIT_SIZE18
, owner);
302
28
        testPackedArrayAligned<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(
303
28
                rawArray, alignedBitSize, owner);
304
28
        testPackedArrayAlignedAuto<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(
305
28
                rawArray, (alignedBitSize != UNKNOWN_BIT_SIZE)
306
28
                        ? 
AUTO_LENGTH_BIT_SIZE + alignedBitSize10
:
UNKNOWN_BIT_SIZE18
, owner);
307
28
    }
308
309
    size_t calcPackedBitSize(size_t elementBitSize, size_t arraySize, size_t maxDeltaBitSize)
310
1
    {
311
1
        return PACKING_DESCRIPTOR_BITSIZE + elementBitSize + (arraySize - 1) * (maxDeltaBitSize + 1);
312
1
    }
313
314
    size_t calcAlignedPackedBitSize(size_t elementBitSize, size_t arraySize, size_t maxDeltaBitSize)
315
1
    {
316
1
        const size_t firstElementWithDescriptorBitSize = PACKING_DESCRIPTOR_BITSIZE + elementBitSize;
317
1
        const size_t alignedFirstElementWithDescriptorBitSize = (firstElementWithDescriptorBitSize + 7) / 8 * 8;
318
1
        const size_t alignedMaxDeltaBitSize = (maxDeltaBitSize + 1 + 7) / 8 * 8;
319
320
1
        return alignedFirstElementWithDescriptorBitSize +
321
1
                (arraySize - 2) * alignedMaxDeltaBitSize + (maxDeltaBitSize + 1);
322
1
    }
323
324
    static const size_t PACKING_DESCRIPTOR_BITSIZE = 1 + 6;
325
326
private:
327
    template <typename ARRAY, typename ARRAY_EXPRESSIONS = typename ARRAY::ArrayExpressions,
328
            typename std::enable_if<has_initialize_element<ARRAY_EXPRESSIONS>::value, int>::type = 0>
329
    void initializeElements(ARRAY& array, typename ARRAY::OwnerType& owner)
330
64
    {
331
64
        array.initializeElements(owner);
332
64
        for (const auto& element : array.getRawArray())
333
192
        {
334
192
            ASSERT_TRUE(element.isInitialized());
335
192
            ASSERT_TRUE(ARRAY_EXPRESSIONS::checkInitialization(owner, element));
336
192
        }
337
64
    }
338
339
    template <typename ARRAY, typename ARRAY_EXPRESSIONS = typename ARRAY::ArrayExpressions,
340
            typename std::enable_if<!has_initialize_element<ARRAY_EXPRESSIONS>::value, int>::type = 0>
341
    void initializeElements(ARRAY&, typename ARRAY::OwnerType&)
342
3.24k
    {}
343
344
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
345
    void testArrayNormal(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
346
72
    {
347
72
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::NORMAL, ARRAY_EXPRESSIONS>;
348
349
640
        for (uint8_t i = 0; i < 8; 
++i568
)
350
569
        {
351
569
            ArrayT array(rawArray);
352
353
569
            initializeElements(array, owner);
354
355
569
            const size_t bitSize = arrayBitSizeOf(array, owner, i);
356
569
            ASSERT_EQ(expectedBitSize, bitSize);
357
569
            ASSERT_EQ(i + bitSize, arrayInitializeOffsets(array, owner, i));
358
359
569
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
360
569
            writer.writeBits(0, i);
361
569
            arrayWrite(array, owner, writer);
362
569
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
363
364
569
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
365
569
            ASSERT_EQ(0, reader.readBits(i));
366
569
            ArrayT readArray;
367
569
            arrayRead(readArray, owner, reader, rawArray.size());
368
569
            ASSERT_EQ(array, readArray);
369
370
568
            testArrayCopiesAndMoves(array);
371
568
        }
372
72
    }
373
374
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
375
    void testArrayAuto(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
376
71
    {
377
71
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::AUTO, ARRAY_EXPRESSIONS>;
378
379
639
        for (uint8_t i = 0; i < 8; 
++i568
)
380
568
        {
381
568
            ArrayT array(rawArray);
382
383
568
            initializeElements(array, owner);
384
385
568
            const size_t bitSize = arrayBitSizeOf(array, owner, i);
386
568
            ASSERT_EQ(expectedBitSize, bitSize);
387
568
            ASSERT_EQ(i + bitSize, arrayInitializeOffsets(array, owner, i));
388
389
568
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
390
568
            writer.writeBits(0, i);
391
568
            arrayWrite(array, owner, writer);
392
568
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
393
394
568
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
395
568
            ASSERT_EQ(0, reader.readBits(i));
396
568
            ArrayT readArray;
397
568
            arrayRead(readArray, owner, reader);
398
568
            ASSERT_EQ(array, readArray);
399
400
568
            testArrayCopiesAndMoves(array);
401
568
        }
402
71
    }
403
404
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
405
    void testArrayAligned(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
406
71
    {
407
71
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::ALIGNED, ARRAY_EXPRESSIONS>;
408
409
639
        for (uint8_t i = 0; i < 8; 
++i568
)
410
568
        {
411
568
            ArrayT array(rawArray);
412
413
568
            initializeElements(array, owner);
414
415
568
            const size_t bitSize = arrayBitSizeOf(array, owner, i);
416
568
            if (expectedBitSize == 0)
417
200
            {
418
200
                ASSERT_EQ(expectedBitSize, bitSize);
419
200
            }
420
368
            else
421
368
            {
422
368
                ASSERT_EQ(alignTo(8, i) - i + expectedBitSize, bitSize);
423
368
            }
424
568
            ASSERT_EQ(i + bitSize, arrayInitializeOffsets(array, owner, i));
425
426
568
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
427
568
            writer.writeBits(0, i);
428
568
            arrayWrite(array, owner, writer);
429
568
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
430
431
568
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
432
568
            ASSERT_EQ(0, reader.readBits(i));
433
568
            ArrayT readArray;
434
568
            arrayRead(readArray, owner, reader, rawArray.size());
435
568
            ASSERT_EQ(array, readArray);
436
437
568
            testArrayCopiesAndMoves(array);
438
568
        }
439
71
    }
440
441
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
442
    void testArrayAlignedAuto(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
443
71
    {
444
71
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::ALIGNED_AUTO, ARRAY_EXPRESSIONS>;
445
446
639
        for (uint8_t i = 0; i < 8; 
++i568
)
447
568
        {
448
568
            ArrayT array(rawArray);
449
450
568
            initializeElements(array, owner);
451
452
568
            const size_t bitSize = arrayBitSizeOf(array, owner, i);
453
454
568
            if (expectedBitSize == AUTO_LENGTH_BIT_SIZE)
455
200
            {
456
200
                ASSERT_EQ(expectedBitSize, bitSize);
457
200
            }
458
368
            else
459
368
            {
460
736
                ASSERT_EQ(alignTo(8, i) - i + expectedBitSize, bitSize) << expectedBitSize;
461
368
            }
462
568
            ASSERT_EQ(i + bitSize, arrayInitializeOffsets(array, owner, i));
463
464
568
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
465
568
            writer.writeBits(0, i);
466
568
            arrayWrite(array, owner, writer);
467
568
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
468
469
568
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
470
568
            ASSERT_EQ(0, reader.readBits(i));
471
568
            ArrayT readArray;
472
568
            arrayRead(readArray, owner, reader);
473
568
            ASSERT_EQ(array, readArray);
474
475
568
            testArrayCopiesAndMoves(array);
476
568
        }
477
71
    }
478
479
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE,
480
            typename std::enable_if<ARRAY_TRAITS::IS_BITSIZEOF_CONSTANT, int>::type = 0>
481
    void testArrayImplicit(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
482
40
    {
483
40
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::IMPLICIT, ARRAY_EXPRESSIONS>;
484
485
40
        if (detail::arrayTraitsConstBitSizeOf<ARRAY_TRAITS>(owner) % 8 != 0)
486
22
            return; // implicit array allowed for types with constant bitsize rounded to bytes
487
488
162
        
for (uint8_t i = 0; 18
i < 8;
++i144
)
489
144
        {
490
144
            ArrayT array(rawArray);
491
492
144
            initializeElements(array, owner);
493
494
144
            const size_t bitSize = arrayBitSizeOf(array, owner, i);
495
144
            ASSERT_EQ(expectedBitSize, bitSize);
496
144
            ASSERT_EQ(i + bitSize, arrayInitializeOffsets(array, owner, i));
497
498
144
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
499
144
            writer.writeBits(0, i);
500
144
            arrayWrite(array, owner, writer);
501
144
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
502
503
144
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
504
144
            ASSERT_EQ(0, reader.readBits(i));
505
144
            ArrayT readArray;
506
144
            arrayRead(readArray, owner, reader);
507
144
            ASSERT_EQ(array, readArray);
508
509
144
            testArrayCopiesAndMoves(array);
510
144
        }
511
18
    }
512
513
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE,
514
            typename std::enable_if<!ARRAY_TRAITS::IS_BITSIZEOF_CONSTANT, int>::type = 0>
515
    void testArrayImplicit(const RAW_ARRAY&, size_t, OWNER_TYPE&)
516
31
    {
517
        // implicit array not allowed for types with non-constant bitsize, so skip the test
518
31
    }
519
520
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
521
    void testPackedArrayNormal(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
522
28
    {
523
28
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::NORMAL, ARRAY_EXPRESSIONS>;
524
525
252
        for (uint8_t i = 0; i < 8; 
++i224
)
526
224
        {
527
224
            ArrayT array(rawArray);
528
529
224
            initializeElements(array, owner);
530
531
224
            const size_t bitSize = arrayBitSizeOfPacked(array, owner, i);
532
224
            if (expectedBitSize != UNKNOWN_BIT_SIZE)
533
80
            {
534
80
                ASSERT_EQ(expectedBitSize, bitSize);
535
80
            }
536
224
            ASSERT_EQ(i + bitSize, arrayInitializeOffsetsPacked(array, owner, i));
537
538
224
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
539
224
            writer.writeBits(0, i);
540
224
            arrayWritePacked(array, owner, writer);
541
224
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
542
543
224
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
544
224
            ASSERT_EQ(0, reader.readBits(i));
545
224
            ArrayT readArray;
546
224
            arrayReadPacked(readArray, owner, reader, rawArray.size());
547
224
            ASSERT_EQ(array, readArray);
548
549
224
            testArrayCopiesAndMoves(array);
550
224
        }
551
28
    }
552
553
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
554
    void testPackedArrayAuto(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
555
28
    {
556
28
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::AUTO, ARRAY_EXPRESSIONS>;
557
558
252
        for (uint8_t i = 0; i < 8; 
++i224
)
559
224
        {
560
224
            ArrayT array(rawArray);
561
562
224
            initializeElements(array, owner);
563
564
224
            const size_t bitSize = arrayBitSizeOfPacked(array, owner, i);
565
224
            if (expectedBitSize != UNKNOWN_BIT_SIZE)
566
80
            {
567
80
                ASSERT_EQ(expectedBitSize, bitSize);
568
80
            }
569
224
            ASSERT_EQ(i + bitSize, arrayInitializeOffsetsPacked(array, owner, i));
570
571
224
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
572
224
            writer.writeBits(0, i);
573
224
            arrayWritePacked(array, owner, writer);
574
224
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
575
576
224
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
577
224
            ASSERT_EQ(0, reader.readBits(i));
578
224
            ArrayT readArray;
579
224
            arrayReadPacked(readArray, owner, reader);
580
224
            ASSERT_EQ(array, readArray);
581
582
224
            testArrayCopiesAndMoves(array);
583
224
        }
584
28
    }
585
586
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
587
    void testPackedArrayAligned(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
588
28
    {
589
28
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::ALIGNED, ARRAY_EXPRESSIONS>;
590
591
252
        for (uint8_t i = 0; i < 8; 
++i224
)
592
224
        {
593
224
            ArrayT array(rawArray);
594
595
224
            initializeElements(array, owner);
596
597
224
            const size_t bitSize = arrayBitSizeOfPacked(array, owner, i);
598
224
            if (expectedBitSize != UNKNOWN_BIT_SIZE && 
i == 080
)
599
10
            {
600
10
                ASSERT_EQ(expectedBitSize, bitSize);
601
10
            }
602
224
            ASSERT_EQ(i + bitSize, arrayInitializeOffsetsPacked(array, owner, i));
603
604
224
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
605
224
            writer.writeBits(0, i);
606
224
            arrayWritePacked(array, owner, writer);
607
224
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
608
609
224
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
610
224
            ASSERT_EQ(0, reader.readBits(i));
611
224
            ArrayT readArray;
612
224
            arrayReadPacked(readArray, owner, reader, rawArray.size());
613
224
            ASSERT_EQ(array, readArray);
614
615
224
            testArrayCopiesAndMoves(array);
616
224
        }
617
28
    }
618
619
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
620
    void testPackedArrayAlignedAuto(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
621
28
    {
622
28
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::ALIGNED_AUTO, ARRAY_EXPRESSIONS>;
623
624
252
        for (uint8_t i = 0; i < 8; 
++i224
)
625
224
        {
626
224
            ArrayT array(rawArray);
627
628
224
            initializeElements(array, owner);
629
630
224
            const size_t bitSize = arrayBitSizeOfPacked(array, owner, i);
631
224
            if (expectedBitSize != UNKNOWN_BIT_SIZE && 
i == 080
)
632
10
            {
633
10
                ASSERT_EQ(expectedBitSize, bitSize);
634
10
            }
635
224
            ASSERT_EQ(i + bitSize, arrayInitializeOffsetsPacked(array, owner, i));
636
637
224
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
638
224
            writer.writeBits(0, i);
639
224
            arrayWritePacked(array, owner, writer);
640
224
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
641
642
224
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
643
224
            ASSERT_EQ(0, reader.readBits(i));
644
224
            ArrayT readArray;
645
224
            arrayReadPacked(readArray, owner, reader);
646
224
            ASSERT_EQ(array, readArray);
647
648
224
            testArrayCopiesAndMoves(array);
649
224
        }
650
28
    }
651
652
    template <typename ARRAY>
653
    void testArrayCopiesAndMoves(const ARRAY& array)
654
3.31k
    {
655
3.31k
        ARRAY arrayCopy(array);
656
3.31k
        ASSERT_EQ(array, arrayCopy);
657
3.31k
        ASSERT_EQ(array.getRawArray(), arrayCopy.getRawArray());
658
3.31k
        ASSERT_FALSE(array < arrayCopy);
659
3.31k
        ASSERT_FALSE(arrayCopy < array);
660
661
3.31k
        ARRAY arrayCopyAssigned;
662
3.31k
        arrayCopyAssigned = array;
663
3.31k
        ASSERT_EQ(array, arrayCopyAssigned);
664
3.31k
        ASSERT_EQ(array.getRawArray(), arrayCopyAssigned.getRawArray());
665
666
3.31k
        const ARRAY arrayMoved = std::move(arrayCopy);
667
3.31k
        ASSERT_EQ(array, arrayMoved);
668
3.31k
        ASSERT_EQ(array.getRawArray(), arrayMoved.getRawArray());
669
670
3.31k
        ARRAY arrayMoveAssigned;
671
3.31k
        arrayMoveAssigned = std::move(arrayCopyAssigned);
672
3.31k
        ASSERT_EQ(array, arrayMoveAssigned);
673
3.31k
        ASSERT_EQ(array.getRawArray(), arrayMoveAssigned.getRawArray());
674
675
3.31k
        ARRAY arrayCopyWithPropagateAllocator(PropagateAllocator, array, std::allocator<uint8_t>());
676
3.31k
        ASSERT_EQ(array, arrayCopyWithPropagateAllocator);
677
3.31k
        ASSERT_EQ(array.getRawArray(), arrayCopyWithPropagateAllocator.getRawArray());
678
679
3.31k
        testArrayNoInitCopiesAndMoves(array);
680
3.31k
    }
681
682
    template <typename RAW_ARRAY>
683
    void checkUninitialized(const RAW_ARRAY& rawArray)
684
320
    {
685
320
        for (const auto& element : rawArray)
686
960
        {
687
960
            ASSERT_FALSE(element.isInitialized());
688
960
        }
689
320
    }
690
691
    template <typename ARRAY, typename T = typename ARRAY::RawArray::value_type,
692
            typename std::enable_if<std::is_constructible<T, NoInitT, T>::value, int>::type = 0>
693
    void testArrayNoInitCopiesAndMoves(const ARRAY& array)
694
64
    {
695
64
        ARRAY arrayCopy(NoInit, array);
696
64
        ASSERT_EQ(array.getRawArray().size(), arrayCopy.getRawArray().size());
697
64
        checkUninitialized(arrayCopy.getRawArray());
698
699
64
        ARRAY arrayCopyAssigned;
700
64
        arrayCopyAssigned.assign(NoInit, array);
701
64
        ASSERT_EQ(array.getRawArray().size(), arrayCopyAssigned.getRawArray().size());
702
64
        checkUninitialized(arrayCopyAssigned.getRawArray());
703
704
64
        const ARRAY arrayMoved(NoInit, std::move(arrayCopy));
705
64
        ASSERT_EQ(array.getRawArray().size(), arrayMoved.getRawArray().size());
706
64
        checkUninitialized(arrayMoved.getRawArray());
707
708
64
        ARRAY arrayMoveAssigned;
709
64
        arrayMoveAssigned.assign(NoInit, std::move(arrayCopyAssigned));
710
64
        ASSERT_EQ(array.getRawArray().size(), arrayMoveAssigned.getRawArray().size());
711
64
        checkUninitialized(arrayMoveAssigned.getRawArray());
712
713
64
        ARRAY arrayCopyWithPropagateAllocator(PropagateAllocator, NoInit, array, std::allocator<uint8_t>());
714
64
        ASSERT_EQ(array.getRawArray().size(), arrayCopyWithPropagateAllocator.getRawArray().size());
715
64
        checkUninitialized(arrayCopyWithPropagateAllocator.getRawArray());
716
64
    }
717
718
    template <typename ARRAY, typename T = typename ARRAY::RawArray::value_type,
719
            typename std::enable_if<!std::is_constructible<T, NoInitT, T>::value, int>::type = 0>
720
    void testArrayNoInitCopiesAndMoves(const ARRAY&)
721
3.24k
    {}
722
723
    static const size_t AUTO_LENGTH_BIT_SIZE = 8;
724
    static const size_t UNKNOWN_BIT_SIZE = std::numeric_limits<size_t>::max();
725
726
    std::array<uint8_t, 256> m_byteBuffer;
727
};
728
729
TEST_F(ArrayTest, intField4Array)
730
1
{
731
1
    const size_t NUM_BITS = 4;
732
1
    std::vector<int8_t> rawArray = {
733
1
            -static_cast<int8_t>(1U << (NUM_BITS - 1)),
734
1
            7,
735
1
            static_cast<int8_t>(1U << (NUM_BITS - 1)) - 1};
736
1
    testArray<BitFieldArrayTraits<int8_t, NUM_BITS>>(rawArray, NUM_BITS);
737
738
    // empty
739
1
    testArray<BitFieldArrayTraits<int8_t, NUM_BITS>>(std::vector<int8_t>(), NUM_BITS);
740
1
}
741
742
TEST_F(ArrayTest, intField12Array)
743
1
{
744
1
    constexpr size_t NUM_BITS = 12;
745
1
    std::vector<int16_t> rawArray = {
746
1
            -static_cast<int16_t>(1U << (NUM_BITS - 1)),
747
1
            7,
748
1
            static_cast<int16_t>(1U << (NUM_BITS - 1)) - 1};
749
1
    testArray<BitFieldArrayTraits<int16_t, NUM_BITS>>(rawArray, NUM_BITS);
750
1
}
751
752
TEST_F(ArrayTest, intField20Array)
753
1
{
754
1
    constexpr size_t NUM_BITS = 20;
755
1
    std::vector<int32_t> rawArray = {
756
1
            -static_cast<int32_t>(1U << (NUM_BITS - 1)),
757
1
            7,
758
1
            static_cast<int32_t>(1U << (NUM_BITS - 1)) - 1};
759
1
    testArray<BitFieldArrayTraits<int32_t, NUM_BITS>>(rawArray, NUM_BITS);
760
1
}
761
762
TEST_F(ArrayTest, intField36Array)
763
1
{
764
1
    constexpr size_t NUM_BITS = 36;
765
1
    std::vector<int64_t> rawArray = {
766
1
            -static_cast<int64_t>(UINT64_C(1) << (NUM_BITS - 1)),
767
1
            7,
768
1
            static_cast<int64_t>(UINT64_C(1) << (NUM_BITS - 1)) - 1};
769
1
    testArray<BitFieldArrayTraits<int64_t, NUM_BITS>>(rawArray, NUM_BITS);
770
1
}
771
772
TEST_F(ArrayTest, bitField4Array)
773
1
{
774
1
    constexpr size_t NUM_BITS = 4;
775
1
    std::vector<uint8_t> rawArray = {0, 7, (1U << NUM_BITS) - 1};
776
1
    testArray<BitFieldArrayTraits<uint8_t, NUM_BITS>>(rawArray, NUM_BITS);
777
778
    // empty
779
1
    testArray<BitFieldArrayTraits<uint8_t, NUM_BITS>>(std::vector<uint8_t>(), NUM_BITS);
780
1
}
781
782
TEST_F(ArrayTest, bitField12Array)
783
1
{
784
1
    constexpr size_t NUM_BITS = 12;
785
1
    std::vector<uint16_t> rawArray = {0, 7, (1U << NUM_BITS) - 1};
786
1
    testArray<BitFieldArrayTraits<uint16_t, NUM_BITS>>(rawArray, NUM_BITS);
787
1
}
788
789
TEST_F(ArrayTest, bitField20Array)
790
1
{
791
1
    constexpr size_t NUM_BITS = 20;
792
1
    std::vector<uint32_t> rawArray = {0, 7, (1U << NUM_BITS) - 1};
793
1
    testArray<BitFieldArrayTraits<uint32_t, NUM_BITS>>(rawArray, NUM_BITS);
794
1
}
795
796
TEST_F(ArrayTest, bitField36Array)
797
1
{
798
1
    constexpr size_t NUM_BITS = 36;
799
1
    std::vector<uint64_t> rawArray = {0, 7, (UINT64_C(1) << NUM_BITS) - 1};
800
1
    testArray<BitFieldArrayTraits<uint64_t, NUM_BITS>>(rawArray, NUM_BITS);
801
1
}
802
803
TEST_F(ArrayTest, dynamicIntField4Array)
804
1
{
805
1
    constexpr size_t NUM_BITS = 4;
806
1
    std::vector<int8_t> rawArray = {
807
1
            -static_cast<int8_t>(1U << (NUM_BITS - 1)),
808
1
            7,
809
1
            static_cast<int8_t>(1U << (NUM_BITS - 1)) - 1};
810
1
    testArray<DynamicBitFieldArrayTraits<int8_t, ElementBitSizeWithOwner>>(rawArray, NUM_BITS,
811
1
            ArrayTestOwnerWithBitSize(NUM_BITS));
812
813
    // empty
814
1
    testArray<DynamicBitFieldArrayTraits<int8_t, ElementBitSizeWithoutOwner<NUM_BITS>>>(
815
1
            std::vector<int8_t>(), NUM_BITS);
816
1
}
817
818
TEST_F(ArrayTest, dynamicIntField8Array)
819
1
{
820
1
    constexpr size_t NUM_BITS = 8; // aligned to allow implicit array
821
1
    std::vector<int8_t> rawArray = {INT8_MIN, 7, INT8_MAX};
822
1
    testArray<DynamicBitFieldArrayTraits<int8_t, ElementBitSizeWithOwner>>(rawArray, NUM_BITS,
823
1
            ArrayTestOwnerWithBitSize(NUM_BITS));
824
1
}
825
826
TEST_F(ArrayTest, dynamicIntField12Array)
827
1
{
828
1
    constexpr size_t NUM_BITS = 12;
829
1
    std::vector<int16_t> rawArray = {
830
1
            -static_cast<int16_t>(1U << (NUM_BITS - 1)),
831
1
            7,
832
1
            static_cast<int16_t>(1U << (NUM_BITS - 1)) - 1};
833
1
    testArray<DynamicBitFieldArrayTraits<int16_t, ElementBitSizeWithoutOwner<NUM_BITS>>>(rawArray, NUM_BITS);
834
1
}
835
836
TEST_F(ArrayTest, dynamicIntField20Array)
837
1
{
838
1
    constexpr size_t NUM_BITS = 20;
839
1
    std::vector<int32_t> rawArray = {
840
1
            -static_cast<int32_t>(1U << (NUM_BITS - 1)),
841
1
            7,
842
1
            static_cast<int32_t>(1U << (NUM_BITS - 1)) - 1};
843
1
    testArray<DynamicBitFieldArrayTraits<int32_t, ElementBitSizeWithOwner>>(rawArray, NUM_BITS,
844
1
            ArrayTestOwnerWithBitSize(NUM_BITS));
845
1
}
846
847
TEST_F(ArrayTest, dynamicIntField36Array)
848
1
{
849
1
    constexpr size_t NUM_BITS = 36;
850
1
    std::vector<int64_t> rawArray = {
851
1
            -static_cast<int64_t>(UINT64_C(1) << (NUM_BITS - 1)),
852
1
            7,
853
1
            static_cast<int64_t>(UINT64_C(1) << (NUM_BITS - 1)) - 1};
854
1
    testArray<DynamicBitFieldArrayTraits<int64_t, ElementBitSizeWithoutOwner<NUM_BITS>>>(rawArray, NUM_BITS);
855
1
}
856
857
TEST_F(ArrayTest, dynamicBitField4Array)
858
1
{
859
1
    constexpr size_t NUM_BITS = 4;
860
1
    std::vector<uint8_t> rawArray = {0, 7, (1U << NUM_BITS) - 1};
861
1
    testArray<DynamicBitFieldArrayTraits<uint8_t, ElementBitSizeWithOwner>>(rawArray, NUM_BITS,
862
1
            ArrayTestOwnerWithBitSize(NUM_BITS));
863
864
    // empty
865
1
    testArray<DynamicBitFieldArrayTraits<uint8_t, ElementBitSizeWithoutOwner<NUM_BITS>>>(
866
1
            std::vector<uint8_t>(), NUM_BITS);
867
1
}
868
869
TEST_F(ArrayTest, dynamicBitField8Array)
870
1
{
871
1
    constexpr size_t NUM_BITS = 8; // aligned to allow implicit array
872
1
    std::vector<uint8_t> rawArray = {0, 7, UINT8_MAX};
873
1
    testArray<DynamicBitFieldArrayTraits<uint8_t, ElementBitSizeWithOwner>>(rawArray, NUM_BITS,
874
1
            ArrayTestOwnerWithBitSize(NUM_BITS));
875
1
}
876
877
TEST_F(ArrayTest, dynamicBitField12Array)
878
1
{
879
1
    constexpr size_t NUM_BITS = 12;
880
1
    std::vector<uint16_t> rawArray = {0, 7, (1U << NUM_BITS) - 1};
881
1
    testArray<DynamicBitFieldArrayTraits<uint16_t, ElementBitSizeWithoutOwner<NUM_BITS>>>(rawArray, NUM_BITS);
882
1
}
883
884
TEST_F(ArrayTest, dynamicBitField20Array)
885
1
{
886
1
    constexpr size_t NUM_BITS = 20;
887
1
    std::vector<uint32_t> rawArray = {0, 7, (1U << NUM_BITS) - 1};
888
1
    testArray<DynamicBitFieldArrayTraits<uint32_t, ElementBitSizeWithOwner>>(rawArray, NUM_BITS,
889
1
            ArrayTestOwnerWithBitSize(NUM_BITS));
890
1
}
891
892
TEST_F(ArrayTest, dynamicBitField36Array)
893
1
{
894
1
    constexpr size_t NUM_BITS = 36;
895
1
    std::vector<uint64_t> rawArray = {0, 7, (UINT64_C(1) << NUM_BITS) - 1};
896
1
    testArray<DynamicBitFieldArrayTraits<uint64_t, ElementBitSizeWithoutOwner<NUM_BITS>>>(rawArray, NUM_BITS);
897
1
}
898
899
TEST_F(ArrayTest, stdInt8Array)
900
1
{
901
1
    std::vector<int8_t> rawArray = {INT8_MIN, 7, INT8_MAX};
902
1
    testArray<StdIntArrayTraits<int8_t>>(rawArray, 8);
903
904
    // empty
905
1
    testArray<StdIntArrayTraits<int8_t>>(std::vector<int8_t>(), 8);
906
1
}
907
908
TEST_F(ArrayTest, stdInt16Array)
909
1
{
910
1
    std::vector<int16_t> rawArray = {INT16_MIN, 7, INT16_MAX};
911
1
    testArray<StdIntArrayTraits<int16_t>>(rawArray, 16);
912
1
}
913
914
TEST_F(ArrayTest, stdInt32Array)
915
1
{
916
1
    std::vector<int32_t> rawArray = {INT32_MIN, 7, INT32_MAX};
917
1
    testArray<StdIntArrayTraits<int32_t>>(rawArray, 32);
918
1
}
919
920
TEST_F(ArrayTest, stdInt64Array)
921
1
{
922
1
    std::vector<int64_t> rawArray = {INT64_MIN, 7, INT64_MAX};
923
1
    testArray<StdIntArrayTraits<int64_t>>(rawArray, 64);
924
1
}
925
926
TEST_F(ArrayTest, stdUInt8Array)
927
1
{
928
1
    std::vector<uint8_t> rawArray = {0, 7, UINT8_MAX};
929
1
    testArray<StdIntArrayTraits<uint8_t>>(rawArray, 8);
930
931
    // empty
932
1
    testArray<StdIntArrayTraits<uint8_t>>(std::vector<uint8_t>(), 8);
933
1
}
934
935
TEST_F(ArrayTest, stdUInt16Array)
936
1
{
937
1
    std::vector<uint16_t> rawArray = {0, 7, UINT16_MAX};
938
1
    testArray<StdIntArrayTraits<uint16_t>>(rawArray, 16);
939
1
}
940
941
TEST_F(ArrayTest, stdUInt32Array)
942
1
{
943
1
    std::vector<uint32_t> rawArray = {0, 7, UINT32_MAX};
944
1
    testArray<StdIntArrayTraits<uint32_t>>(rawArray, 32);
945
1
}
946
947
TEST_F(ArrayTest, stdUInt64Array)
948
1
{
949
1
    std::vector<uint64_t> rawArray = {0, 7, UINT64_MAX};
950
1
    testArray<StdIntArrayTraits<uint64_t>>(rawArray, 64);
951
1
}
952
953
TEST_F(ArrayTest, varInt16Array)
954
1
{
955
1
    std::vector<int16_t> rawArray = {static_cast<int16_t>(1U << 5U), static_cast<int16_t>(1U << (5U + 8))};
956
1
    const size_t bitSize = 8 * (1 + 2);
957
1
    testArray<VarIntNNArrayTraits<int16_t>>(rawArray, bitSize, bitSize);
958
959
    // empty
960
1
    testArray<VarIntNNArrayTraits<int16_t>>(std::vector<int16_t>(), 0, 0);
961
1
}
962
963
TEST_F(ArrayTest, varInt32Array)
964
1
{
965
1
    std::vector<int32_t> rawArray = {
966
1
            static_cast<int32_t>(1U << 5U),
967
1
            static_cast<int32_t>(1U << (5U + 7)),
968
1
            static_cast<int32_t>(1U << (5U + 7 + 7)),
969
1
            static_cast<int32_t>(1U << (5U + 7 + 7 + 8))};
970
1
    const size_t bitSize = 8 * (1 + 2 + 3 + 4);
971
1
    testArray<VarIntNNArrayTraits<int32_t>>(rawArray, bitSize, bitSize);
972
973
    // empty
974
1
    testArray<VarIntNNArrayTraits<int32_t>>(std::vector<int32_t>(), 0, 0);
975
1
}
976
977
TEST_F(ArrayTest, varInt64Array)
978
1
{
979
1
    std::vector<int64_t> rawArray = {
980
1
            static_cast<int64_t>(UINT64_C(1) << 5U),
981
1
            static_cast<int64_t>(UINT64_C(1) << (5U + 7)),
982
1
            static_cast<int64_t>(UINT64_C(1) << (5U + 7 + 7)),
983
1
            static_cast<int64_t>(UINT64_C(1) << (5U + 7 + 7 + 7)),
984
1
            static_cast<int64_t>(UINT64_C(1) << (5U + 7 + 7 + 7 + 7)),
985
1
            static_cast<int64_t>(UINT64_C(1) << (5U + 7 + 7 + 7 + 7 + 7)),
986
1
            static_cast<int64_t>(UINT64_C(1) << (5U + 7 + 7 + 7 + 7 + 7 + 7)),
987
1
            static_cast<int64_t>(UINT64_C(1) << (5U + 7 + 7 + 7 + 7 + 7 + 7 + 8))};
988
1
    const size_t bitSize = 8 * (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8);
989
1
    testArray<VarIntNNArrayTraits<int64_t>>(rawArray, bitSize, bitSize);
990
991
    // empty
992
1
    testArray<VarIntNNArrayTraits<int64_t>>(std::vector<int64_t>(), 0, 0);
993
1
}
994
995
TEST_F(ArrayTest, varUInt16Array)
996
1
{
997
1
    std::vector<uint16_t> rawArray = {1U << 6U, 1U << (6U + 8)};
998
1
    const size_t bitSize = 8 * (1 + 2);
999
1
    testArray<VarIntNNArrayTraits<uint16_t>>(rawArray, bitSize, bitSize);
1000
1001
    // empty
1002
1
    testArray<VarIntNNArrayTraits<uint16_t>>(std::vector<uint16_t>(), 0, 0);
1003
1
}
1004
1005
TEST_F(ArrayTest, varUInt32Array)
1006
1
{
1007
1
    std::vector<uint32_t> rawArray = {1U << 6U, 1U << (6U + 7), 1U << (6U + 7 + 7), 1U << (6U + 7 + 7 + 8)};
1008
1
    const size_t bitSize = 8 * (1 + 2 + 3 + 4);
1009
1
    testArray<VarIntNNArrayTraits<uint32_t>>(rawArray, bitSize, bitSize);
1010
1011
    // empty
1012
1
    testArray<VarIntNNArrayTraits<uint32_t>>(std::vector<uint32_t>(), 0, 0);
1013
1
}
1014
1015
TEST_F(ArrayTest, varUInt64Array)
1016
1
{
1017
1
    std::vector<uint64_t> rawArray = {
1018
1
            UINT64_C(1) << 6U,
1019
1
            UINT64_C(1) << (6U + 7),
1020
1
            UINT64_C(1) << (6U + 7 + 7),
1021
1
            UINT64_C(1) << (6U + 7 + 7 + 7),
1022
1
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7),
1023
1
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7 + 7),
1024
1
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7 + 7 + 7),
1025
1
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7 + 7 + 7 + 8)};
1026
1
    const size_t bitSize = 8 * (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8);
1027
1
    testArray<VarIntNNArrayTraits<uint64_t>>(rawArray, bitSize, bitSize);
1028
1029
    // empty
1030
1
    testArray<VarIntNNArrayTraits<uint64_t>>(std::vector<uint64_t>(), 0, 0);
1031
1
}
1032
1033
TEST_F(ArrayTest, varIntArray)
1034
1
{
1035
1
    std::vector<int64_t> rawArray;
1036
    // 1 byte
1037
1
    rawArray.push_back(0);
1038
1
    rawArray.push_back(-1);
1039
1
    rawArray.push_back(1);
1040
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 6U) + 1);
1041
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 6U) - 1);
1042
    // 2 bytes
1043
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 13U) + 1);
1044
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 13U) - 1);
1045
    // 3 bytes
1046
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 20U) + 1);
1047
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 20U) - 1);
1048
    // 4 bytes
1049
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 27U) + 1);
1050
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 27U) - 1);
1051
    // 5 bytes
1052
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 34U) + 1);
1053
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 34U) - 1);
1054
    // 6 bytes
1055
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 41U) + 1);
1056
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 41U) - 1);
1057
    // 7 bytes
1058
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 48U) + 1);
1059
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 48U) - 1);
1060
    // 8 bytes
1061
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 55U) + 1);
1062
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 55U) - 1);
1063
    // 9 bytes
1064
1
    rawArray.push_back(INT64_MIN + 1);
1065
1
    rawArray.push_back(INT64_MAX);
1066
    // 1 byte - special case, INT64_MIN stored as -0
1067
1
    rawArray.push_back(INT64_MIN);
1068
1
    const size_t bitSize = 8 * (3 + 2 * (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9) + 1);
1069
1
    testArray<VarIntArrayTraits<int64_t>>(rawArray, bitSize, bitSize);
1070
1071
    // empty
1072
1
    testArray<VarIntArrayTraits<int64_t>>(std::vector<int64_t>(), 0, 0);
1073
1
}
1074
1075
TEST_F(ArrayTest, varUIntArray)
1076
1
{
1077
1
    std::vector<uint64_t> rawArray;
1078
    // 1 byte
1079
1
    rawArray.push_back(0);
1080
1
    rawArray.push_back(1);
1081
1
    rawArray.push_back((UINT64_C(1) << 7U) - 1);
1082
    // 2 bytes
1083
1
    rawArray.push_back((UINT64_C(1) << 14U) - 1);
1084
    // 3 bytes
1085
1
    rawArray.push_back((UINT64_C(1) << 21U) - 1);
1086
    // 4 bytes
1087
1
    rawArray.push_back((UINT64_C(1) << 28U) - 1);
1088
    // 5 bytes
1089
1
    rawArray.push_back((UINT64_C(1) << 35U) - 1);
1090
    // 6 bytes
1091
1
    rawArray.push_back((UINT64_C(1) << 42U) - 1);
1092
    // 7 bytes
1093
1
    rawArray.push_back((UINT64_C(1) << 49U) - 1);
1094
    // 8 bytes
1095
1
    rawArray.push_back((UINT64_C(1) << 56U) - 1);
1096
    // 9 bytes
1097
1
    rawArray.push_back(UINT64_MAX);
1098
1
    const size_t bitSize = 8 * (2 + (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9));
1099
1
    testArray<VarIntArrayTraits<uint64_t>>(rawArray, bitSize, bitSize);
1100
1101
    // empty
1102
1
    testArray<VarIntArrayTraits<uint64_t>>(std::vector<uint64_t>(), 0, 0);
1103
1
}
1104
1105
TEST_F(ArrayTest, varSizeArray)
1106
1
{
1107
1
    std::vector<uint32_t> rawArray = {
1108
1
            UINT32_C(1) << 6U,
1109
1
            UINT32_C(1) << (6U + 7),
1110
1
            UINT32_C(1) << (6U + 7 + 7),
1111
1
            UINT32_C(1) << (6U + 7 + 7 + 7),
1112
1
            UINT32_C(1) << (1U + 7 + 7 + 7 + 8)};
1113
1
    const size_t bitSize = 8 * (1 + 2 + 3 + 4 + 5);
1114
1
    testArray<VarSizeArrayTraits>(rawArray, bitSize, bitSize);
1115
1116
    // empty
1117
1
    testArray<VarSizeArrayTraits>(std::vector<uint32_t>(), 0, 0);
1118
1
}
1119
1120
TEST_F(ArrayTest, float16Array)
1121
1
{
1122
1
    const size_t elementBitSize = 16;
1123
1
    std::vector<float> rawArray = {-9.0, 0.0,  10.0};
1124
1
    testArray<Float16ArrayTraits>(rawArray, elementBitSize);
1125
1126
    // empty
1127
1
    testArray<Float16ArrayTraits>(std::vector<float>(), elementBitSize);
1128
1
}
1129
1130
TEST_F(ArrayTest, float32Array)
1131
1
{
1132
1
    const size_t elementBitSize = 32;
1133
1
    std::vector<float> rawArray = {-9.0, 0.0,  10.0};
1134
1
    testArray<Float32ArrayTraits>(rawArray, elementBitSize);
1135
1136
    // empty
1137
1
    testArray<Float32ArrayTraits>(std::vector<float>(), elementBitSize);
1138
1
}
1139
1140
TEST_F(ArrayTest, float64Array)
1141
1
{
1142
1
    const size_t elementBitSize = 64;
1143
1
    std::vector<double> rawArray = {-9.0, 0.0, 10.0};
1144
1
    testArray<Float64ArrayTraits>(rawArray, elementBitSize);
1145
1146
    // empty
1147
1
    testArray<Float64ArrayTraits>(std::vector<double>(), elementBitSize);
1148
1
}
1149
1150
TEST_F(ArrayTest, boolArray)
1151
1
{
1152
1
    const size_t elementBitSize = 1;
1153
1
    std::vector<bool> rawArray = {false, true};
1154
1
    testArray<BoolArrayTraits>(rawArray, elementBitSize);
1155
1156
    // empty
1157
1
    testArray<BoolArrayTraits>(std::vector<bool>(), elementBitSize);
1158
1
}
1159
1160
TEST_F(ArrayTest, bytesArray)
1161
1
{
1162
1
    const size_t bytesLengthBitSize = 8;
1163
1
    const size_t bytesBitSize = 2 * 8;
1164
1
    const size_t elementBitSize = bytesLengthBitSize + bytesBitSize;
1165
1
    std::vector<std::vector<uint8_t>> rawArray = {{ {{ 1, 255 }}, {{ 127, 128 }} }};
1166
1
    testArray<BytesArrayTraits>(rawArray, elementBitSize);
1167
1168
    // empty
1169
1
    testArray<BytesArrayTraits>(std::vector<std::vector<uint8_t>>(), elementBitSize);
1170
1
}
1171
1172
TEST_F(ArrayTest, stringArray)
1173
1
{
1174
1
    const size_t stringLengthBitSize = 8;
1175
1
    const size_t stringBitSize = (sizeof("StringX") - 1) * 8; // without terminating character
1176
1
    const size_t elementBitSize = stringLengthBitSize + stringBitSize;
1177
1
    std::vector<std::string> rawArray = {"String0", "String1", "String2"};
1178
1
    testArray<StringArrayTraits>(rawArray, elementBitSize);
1179
1180
    // empty
1181
1
    testArray<StringArrayTraits>(std::vector<std::string>(), 0);
1182
1
}
1183
1184
TEST_F(ArrayTest, bitBufferArray)
1185
1
{
1186
1
    const size_t bitBufferLengthBitSize = 8;
1187
1
    const size_t bitBufferBitSize = 10;
1188
1
    const size_t elementBitSize = bitBufferLengthBitSize + bitBufferBitSize;
1189
1
    std::vector<BitBuffer> rawArray = {BitBuffer(bitBufferBitSize), BitBuffer(bitBufferBitSize),
1190
1
            BitBuffer(bitBufferBitSize)};
1191
1
    testArray<BitBufferArrayTraits>(rawArray, elementBitSize);
1192
1193
    // empty
1194
1
    testArray<BitBufferArrayTraits>(std::vector<BitBuffer>(), 0);
1195
1
}
1196
1197
TEST_F(ArrayTest, enumArray)
1198
1
{
1199
1
    std::vector<ArrayEnum> rawArray = {ArrayEnum::VALUE1, ArrayEnum::VALUE2, ArrayEnum::VALUE3};
1200
1
    const size_t elementBitSize = 8;
1201
1
    testArray<EnumArrayTraits<ArrayEnum>>(rawArray, elementBitSize);
1202
1203
    // empty
1204
1
    testArray<EnumArrayTraits<ArrayEnum>>(std::vector<ArrayEnum>(), elementBitSize);
1205
1206
1
    std::vector<ArrayEnum> invalidRawArray = {static_cast<ArrayEnum>(10)};
1207
1
    ASSERT_THROW(testArray<EnumArrayTraits<ArrayEnum>>(invalidRawArray, elementBitSize), CppRuntimeException);
1208
1
}
1209
1210
TEST_F(ArrayTest, bitmaskArray)
1211
1
{
1212
1
    std::vector<ArrayBitmask> rawArray = {ArrayBitmask::Values::READ, ArrayBitmask::Values::WRITE,
1213
1
            ArrayBitmask::Values::CREATE};
1214
1
    const size_t elementBitSize = 8;
1215
1
    testArray<BitmaskArrayTraits<ArrayBitmask>>(rawArray, elementBitSize);
1216
1217
    // empty
1218
1
    testArray<BitmaskArrayTraits<ArrayBitmask>>(std::vector<ArrayBitmask>(), elementBitSize);
1219
1
}
1220
1221
TEST_F(ArrayTest, objectArray)
1222
1
{
1223
1
    std::vector<ArrayObject> rawArray = {ArrayObject(0xAB), ArrayObject(0xCD), ArrayObject(0xEF)};
1224
1
    testArray<ObjectArrayTraits<ArrayObject, ArrayObjectElementFactory>, std::vector<ArrayObject>,
1225
1
            ArrayObjectArrayExpressions>(rawArray, 31);
1226
1227
    // empty
1228
1
    testArray<ObjectArrayTraits<ArrayObject, ArrayObjectElementFactory>, std::vector<ArrayObject>,
1229
1
            ArrayObjectArrayExpressions>(std::vector<ArrayObject>(), 31);
1230
1
}
1231
1232
TEST_F(ArrayTest, paramObjectArray)
1233
1
{
1234
1
    ArrayParamObjectOwner owner{ArrayObject(0xEF)};
1235
1
    std::vector<ArrayParamObject> rawArray = {
1236
1
        ArrayParamObject(0xAB), ArrayParamObject(0xBC), ArrayParamObject(0xCD)
1237
1
    };
1238
1
    testArray<ObjectArrayTraits<ArrayParamObject, ArrayParamObjectElementFactory>,
1239
1
            std::vector<ArrayParamObject>, ArrayParamObjectArrayExpressions>(rawArray, 32, owner);
1240
1
}
1241
1242
TEST_F(ArrayTest, stdInt8PackedArray)
1243
1
{
1244
1
    std::vector<int8_t> rawArray = { -4, -3, -1, 0, 2, 4, 6, 8, 10, 10, 11 };
1245
1
    testPackedArray<StdIntArrayTraits<int8_t>>(rawArray);
1246
1
}
1247
1248
TEST_F(ArrayTest, stdInt64PackedArray)
1249
1
{
1250
    // will not be packed
1251
1
    std::vector<int64_t> rawArray = { INT64_MIN, 1, -1, INT64_MAX };
1252
1
    testPackedArray<StdIntArrayTraits<int64_t>>(rawArray);
1253
1
}
1254
1255
TEST_F(ArrayTest, stdUInt64PackedArray)
1256
1
{
1257
    // will have maxBitNumber 62 bits
1258
1
    std::vector<uint64_t> rawArray = { 0, INT64_MAX / 2, 100, 200, 300, 400, 500, 600, 700 };
1259
1
    testPackedArray<StdIntArrayTraits<uint64_t>>(rawArray);
1260
1
}
1261
1262
TEST_F(ArrayTest, bitField64PackedArray)
1263
1
{
1264
1
    using ArrayTraits = BitFieldArrayTraits<uint64_t, 64>;
1265
1266
    // none-zero delta
1267
1
    std::vector<uint64_t> rawArray1 = {10, 11, 12};
1268
1
    const size_t array1MaxDeltaBitSize = 1;
1269
1
    const size_t array1BitSizeOf = calcPackedBitSize(64, rawArray1.size(), array1MaxDeltaBitSize);
1270
1
    const size_t array1AlignedBitSizeOf = calcAlignedPackedBitSize(64, rawArray1.size(), array1MaxDeltaBitSize);
1271
1
    testPackedArray<ArrayTraits>(rawArray1, array1BitSizeOf, array1AlignedBitSizeOf);
1272
1273
    // zero delta
1274
1
    std::vector<uint64_t> rawArray2 = {10, 10, 10};
1275
1
    const size_t array2BitSizeOf = PACKING_DESCRIPTOR_BITSIZE + 64;
1276
1
    const size_t array2AlignedBitSizeOf = PACKING_DESCRIPTOR_BITSIZE + 64 +
1277
1
            /* alignment before element 2 */ (8 - PACKING_DESCRIPTOR_BITSIZE);
1278
1
    testPackedArray<ArrayTraits>(rawArray2, array2BitSizeOf, array2AlignedBitSizeOf);
1279
1280
    // one-element array
1281
1
    std::vector<uint64_t> rawArray3 = {10};
1282
1
    const size_t array3BitSizeOf = 1 + 64;
1283
1
    const size_t array3AlignedBitSizeOf = 1 + 64; // no alignment before first element, no more elements
1284
1
    testPackedArray<ArrayTraits>(rawArray3, array3BitSizeOf, array3AlignedBitSizeOf);
1285
1286
    // empty array
1287
1
    std::vector<uint64_t> rawArray4 = {};
1288
1
    const size_t array4BitSizeOf = 0;
1289
1
    const size_t array4AlignedBitSizeOf = 0;
1290
1
    testPackedArray<ArrayTraits>(rawArray4, array4BitSizeOf, array4AlignedBitSizeOf);
1291
1292
    // packing not enabled, delta is too big
1293
1
    testPackedArray<ArrayTraits>(std::vector<uint64_t>{0, UINT64_MAX});
1294
1
    testPackedArray<ArrayTraits>(std::vector<uint64_t>{UINT64_MAX, UINT64_MAX / 2, 0});
1295
1296
    // will have maxBitNumber 62 bits
1297
1
    testPackedArray<ArrayTraits>(
1298
1
            std::vector<uint64_t>{0, static_cast<uint64_t>(INT64_MAX / 2), 100, 200, 300, 400, 500, 600, 700});
1299
1
}
1300
1301
TEST_F(ArrayTest, bitField8PackedArray)
1302
1
{
1303
1
    using ArrayTraits = BitFieldArrayTraits<uint8_t, 8>;
1304
1305
    // will not be packed because unpacked 8bit values will be more efficient
1306
1
    std::vector<uint8_t> rawArray1 = {UINT8_MAX, 0, 10, 20, 30, 40}; // max_bit_number 8, delta needs 9 bits
1307
1
    const size_t array1BitSizeOf = 1 + 6 * 8;
1308
1
    const size_t array1AlignedBitSizeOf = 1 + 8 + /* alignment */ 7 + 5 * 8;
1309
1
    testPackedArray<ArrayTraits>(rawArray1, array1BitSizeOf, array1AlignedBitSizeOf);
1310
1311
    // will not be packed because unpacked 8bit values will be more efficient
1312
    // (6 bits more are needed to store max_bit_number in descriptor if packing was enabled)
1313
1
    std::vector<uint8_t> rawArray2 =
1314
1
            {UINT8_MAX, UINT8_MAX / 2 + 1, 10, 20, 30, 40}; // max_bit_number 7, delta needs 8 bits
1315
1
    const size_t array2BitSizeOf = 1 + 6 * 8;
1316
1
    const size_t array2AlignedBitSizeOf = 1 + 8 + /* alignment */ 7 + 5 * 8;
1317
1
    testPackedArray<ArrayTraits>(rawArray2, array2BitSizeOf, array2AlignedBitSizeOf);
1318
1
}
1319
1320
TEST_F(ArrayTest, intField64PackedArray)
1321
1
{
1322
1
    using ArrayTraits = BitFieldArrayTraits<int64_t, 64>;
1323
1324
1
    testPackedArray<ArrayTraits>(std::vector<int64_t>{-10, 11, -12});
1325
1
    testPackedArray<ArrayTraits>(std::vector<int64_t>{-10, -10, -10}); // zero delta
1326
1327
1
    testPackedArray<ArrayTraits>(std::vector<int64_t>{}); // empty
1328
1
    testPackedArray<ArrayTraits>(std::vector<int64_t>{10}); // single element
1329
1330
    // packing not enabled, delta is too big
1331
1
    testPackedArray<ArrayTraits>(std::vector<int64_t>{INT64_MIN, INT64_MAX});
1332
1
    testPackedArray<ArrayTraits>(std::vector<int64_t>{INT64_MIN, 0, INT64_MAX});
1333
1
}
1334
1335
TEST_F(ArrayTest, intField16PackedArray)
1336
1
{
1337
1
    using ArrayTraits = BitFieldArrayTraits<int16_t, 16>;
1338
1339
    // will not be packed because unpacked 16bit values will be more efficient
1340
    // (6 bits more are needed to store max_bit_number in descriptor if packing was enabled)
1341
1
    std::vector<int16_t> rawArray = {INT16_MIN, -1, 10, 20, 30, 40}; // max_bit_number 15, delta needs 16 bits
1342
1
    const size_t unpackedBitSizeOf = 1 + 6 * 16;
1343
1
    const size_t unpackedAlignedBitSizeOf = 1 + 16 + /* alignment */ 7 + 5 * 16;
1344
1
    testPackedArray<ArrayTraits>(rawArray, unpackedBitSizeOf, unpackedAlignedBitSizeOf);
1345
1
}
1346
1347
TEST_F(ArrayTest, dynamicBitField8PackedArray)
1348
1
{
1349
    // will not be packed because unpacked 8bit values will be more efficient
1350
1
    std::vector<uint8_t> rawArray1 = {UINT8_MAX, 0, 10, 20, 30, 40}; // max_bit_number 8, delta needs 9 bits
1351
1
    const size_t array1BitSizeOf = 1 + 6 * 8;
1352
1
    const size_t array1AlignedBitSizeOf = 1 + 8 + /* alignment */ 7 + 5 * 8;
1353
1
    testPackedArray<DynamicBitFieldArrayTraits<uint8_t, ElementBitSizeWithOwner>>(
1354
1
            rawArray1, array1BitSizeOf, array1AlignedBitSizeOf, ArrayTestOwnerWithBitSize(8));
1355
1356
    // will not be packed because unpacked 8bit values will be more efficient
1357
    // (6 bits more are needed to store max_bit_number in descriptor if packing was enabled)
1358
1
    std::vector<uint8_t> rawArray2 =
1359
1
            {UINT8_MAX, UINT8_MAX / 2 + 1, 10, 20, 30, 40}; // max_bit_number 7, delta needs 8 bits
1360
1
    const size_t array2BitSizeOf = 1 + 6 * 8;
1361
1
    const size_t array2AlignedBitSizeOf = 1 + 8 + /* alignment */ 7 + 5 * 8;
1362
1
    testPackedArray<DynamicBitFieldArrayTraits<uint8_t, ElementBitSizeWithoutOwner<8>>>(
1363
1
            rawArray2, array2BitSizeOf, array2AlignedBitSizeOf);
1364
1
}
1365
1366
TEST_F(ArrayTest, varUInt64PackedArray)
1367
1
{
1368
1
    std::vector<uint64_t> rawArray = {
1369
1
            UINT64_C(1) << 6U,
1370
1
            UINT64_C(1) << (6U + 7),
1371
1
            UINT64_C(1) << (6U + 7 + 7),
1372
1
            UINT64_C(1) << (6U + 7 + 7 + 7),
1373
1
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7),
1374
1
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7 + 7),
1375
1
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7 + 7 + 7),
1376
1
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7 + 7 + 7 + 8)};
1377
1
    testPackedArray<VarIntNNArrayTraits<uint64_t>>(rawArray);
1378
1379
1
    std::vector<uint64_t> unpackedRawArray = {UINT64_C(5000000), 0, 0, 0, 0, 0, 0};
1380
1
    const size_t unpackedBitSizeOf = 1 + 32 + 6 * 8;
1381
1
    const size_t unpackedAlignedBitSizeOf = 1 + 32 + /* alignment */ 7 + 6 * 8;
1382
1
    testPackedArray<VarIntNNArrayTraits<uint64_t>>(unpackedRawArray,
1383
1
            unpackedBitSizeOf, unpackedAlignedBitSizeOf);
1384
1
}
1385
1386
TEST_F(ArrayTest, varSizePackedArray)
1387
1
{
1388
1
    std::vector<uint32_t> rawArray = {
1389
1
            UINT32_C(1) << 6U,
1390
1
            UINT32_C(1) << (6U + 7),
1391
1
            UINT32_C(1) << (6U + 7 + 7),
1392
1
            UINT32_C(1) << (6U + 7 + 7 + 7),
1393
1
            UINT32_C(1) << (1U + 7 + 7 + 7 + 8)};
1394
1
    testPackedArray<VarSizeArrayTraits>(rawArray);
1395
1
}
1396
1397
TEST_F(ArrayTest, enumPackedArray)
1398
1
{
1399
1
    std::vector<ArrayEnum> rawArray = {ArrayEnum::VALUE1, ArrayEnum::VALUE2, ArrayEnum::VALUE3};
1400
1
    testPackedArray<EnumArrayTraits<ArrayEnum>>(rawArray);
1401
1
}
1402
1403
TEST_F(ArrayTest, bitmaskPackedArray)
1404
1
{
1405
1
    std::vector<ArrayBitmask> rawArray = {ArrayBitmask::Values::READ, ArrayBitmask::Values::WRITE,
1406
1
            ArrayBitmask::Values::CREATE};
1407
1
    testPackedArray<BitmaskArrayTraits<ArrayBitmask>>(rawArray);
1408
1
}
1409
1410
TEST_F(ArrayTest, objectPackedArray)
1411
1
{
1412
1
    std::vector<ArrayObject> rawArray = {ArrayObject(0xAB), ArrayObject(0xCD), ArrayObject(0xEF)};
1413
1
    testPackedArray<ObjectArrayTraits<ArrayObject, ArrayObjectElementFactory>, std::vector<ArrayObject>,
1414
1
            ArrayObjectArrayExpressions>(rawArray);
1415
1
}
1416
1417
TEST_F(ArrayTest, paramObjectPackedArray)
1418
1
{
1419
1
    ArrayParamObjectOwner owner{ArrayObject(0xEF)};
1420
1
    std::vector<ArrayParamObject> rawArray = {
1421
1
        ArrayParamObject(0xAB), ArrayParamObject(0xBC), ArrayParamObject(0xCD)
1422
1
    };
1423
1
    testPackedArray<ObjectArrayTraits<ArrayParamObject, ArrayParamObjectElementFactory>,
1424
1
            std::vector<ArrayParamObject>, ArrayParamObjectArrayExpressions>(rawArray, owner);
1425
1
}
1426
1427
TEST_F(ArrayTest, createOptionalArray)
1428
1
{
1429
1
    using ArrayT = Array<std::vector<uint8_t>, BitFieldArrayTraits<uint8_t, 8>, ArrayType::NORMAL>;
1430
1
    InplaceOptionalHolder<ArrayT> optionalArray = createOptionalArray<ArrayT>(NullOpt);
1431
1
    ASSERT_FALSE(optionalArray.hasValue());
1432
1433
1
    const std::vector<uint8_t> array = {0, 7, UINT8_MAX};
1434
1
    optionalArray = createOptionalArray<ArrayT>(array);
1435
1
    ASSERT_TRUE(optionalArray.hasValue());
1436
1
    ASSERT_EQ(array, optionalArray->getRawArray());
1437
1
}
1438
1439
} // namespace zserio