Coverage Report

Created: 2024-12-05 10:39

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