Coverage Report

Created: 2024-04-30 09:35

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
            writer.writeBits(0, i);
357
569
            arrayWrite(array, owner, writer);
358
569
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
359
360
569
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
361
569
            ASSERT_EQ(0, reader.readBits(i));
362
569
            ArrayT readArray;
363
569
            arrayRead(readArray, owner, reader, rawArray.size());
364
569
            ASSERT_EQ(array, readArray);
365
366
568
            testArrayCopiesAndMoves(array);
367
568
        }
368
72
    }
369
370
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
371
    void testArrayAuto(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
372
71
    {
373
71
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::AUTO, ARRAY_EXPRESSIONS>;
374
375
639
        for (uint8_t i = 0; i < 8; 
++i568
)
376
568
        {
377
568
            ArrayT array(rawArray);
378
379
568
            initializeElements(array, owner);
380
381
568
            const size_t bitSize = arrayBitSizeOf(array, owner, i);
382
568
            ASSERT_EQ(expectedBitSize, bitSize);
383
568
            ASSERT_EQ(i + bitSize, arrayInitializeOffsets(array, owner, i));
384
385
568
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
386
568
            writer.writeBits(0, i);
387
568
            arrayWrite(array, owner, writer);
388
568
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
389
390
568
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
391
568
            ASSERT_EQ(0, reader.readBits(i));
392
568
            ArrayT readArray;
393
568
            arrayRead(readArray, owner, reader);
394
568
            ASSERT_EQ(array, readArray);
395
396
568
            testArrayCopiesAndMoves(array);
397
568
        }
398
71
    }
399
400
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
401
    void testArrayAligned(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
402
71
    {
403
71
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::ALIGNED, ARRAY_EXPRESSIONS>;
404
405
639
        for (uint8_t i = 0; i < 8; 
++i568
)
406
568
        {
407
568
            ArrayT array(rawArray);
408
409
568
            initializeElements(array, owner);
410
411
568
            const size_t bitSize = arrayBitSizeOf(array, owner, i);
412
568
            if (expectedBitSize == 0)
413
200
            {
414
200
                ASSERT_EQ(expectedBitSize, bitSize);
415
200
            }
416
368
            else
417
368
            {
418
368
                ASSERT_EQ(alignTo(8, i) - i + expectedBitSize, bitSize);
419
368
            }
420
568
            ASSERT_EQ(i + bitSize, arrayInitializeOffsets(array, owner, i));
421
422
568
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
423
568
            writer.writeBits(0, i);
424
568
            arrayWrite(array, owner, writer);
425
568
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
426
427
568
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
428
568
            ASSERT_EQ(0, reader.readBits(i));
429
568
            ArrayT readArray;
430
568
            arrayRead(readArray, owner, reader, rawArray.size());
431
568
            ASSERT_EQ(array, readArray);
432
433
568
            testArrayCopiesAndMoves(array);
434
568
        }
435
71
    }
436
437
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
438
    void testArrayAlignedAuto(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
439
71
    {
440
71
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::ALIGNED_AUTO, ARRAY_EXPRESSIONS>;
441
442
639
        for (uint8_t i = 0; i < 8; 
++i568
)
443
568
        {
444
568
            ArrayT array(rawArray);
445
446
568
            initializeElements(array, owner);
447
448
568
            const size_t bitSize = arrayBitSizeOf(array, owner, i);
449
450
568
            if (expectedBitSize == AUTO_LENGTH_BIT_SIZE)
451
200
            {
452
200
                ASSERT_EQ(expectedBitSize, bitSize);
453
200
            }
454
368
            else
455
368
            {
456
736
                ASSERT_EQ(alignTo(8, i) - i + expectedBitSize, bitSize) << expectedBitSize;
457
368
            }
458
568
            ASSERT_EQ(i + bitSize, arrayInitializeOffsets(array, owner, i));
459
460
568
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
461
568
            writer.writeBits(0, i);
462
568
            arrayWrite(array, owner, writer);
463
568
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
464
465
568
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
466
568
            ASSERT_EQ(0, reader.readBits(i));
467
568
            ArrayT readArray;
468
568
            arrayRead(readArray, owner, reader);
469
568
            ASSERT_EQ(array, readArray);
470
471
568
            testArrayCopiesAndMoves(array);
472
568
        }
473
71
    }
474
475
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE,
476
            typename std::enable_if<ARRAY_TRAITS::IS_BITSIZEOF_CONSTANT, int>::type = 0>
477
    void testArrayImplicit(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
478
40
    {
479
40
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::IMPLICIT, ARRAY_EXPRESSIONS>;
480
481
40
        if (detail::arrayTraitsConstBitSizeOf<ARRAY_TRAITS>(owner) % 8 != 0)
482
22
            return; // implicit array allowed for types with constant bitsize rounded to bytes
483
484
162
        
for (uint8_t i = 0; 18
i < 8;
++i144
)
485
144
        {
486
144
            ArrayT array(rawArray);
487
488
144
            initializeElements(array, owner);
489
490
144
            const size_t bitSize = arrayBitSizeOf(array, owner, i);
491
144
            ASSERT_EQ(expectedBitSize, bitSize);
492
144
            ASSERT_EQ(i + bitSize, arrayInitializeOffsets(array, owner, i));
493
494
144
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
495
144
            writer.writeBits(0, i);
496
144
            arrayWrite(array, owner, writer);
497
144
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
498
499
144
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
500
144
            ASSERT_EQ(0, reader.readBits(i));
501
144
            ArrayT readArray;
502
144
            arrayRead(readArray, owner, reader);
503
144
            ASSERT_EQ(array, readArray);
504
505
144
            testArrayCopiesAndMoves(array);
506
144
        }
507
18
    }
508
509
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE,
510
            typename std::enable_if<!ARRAY_TRAITS::IS_BITSIZEOF_CONSTANT, int>::type = 0>
511
    void testArrayImplicit(const RAW_ARRAY&, size_t, OWNER_TYPE&)
512
31
    {
513
        // implicit array not allowed for types with non-constant bitsize, so skip the test
514
31
    }
515
516
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
517
    void testPackedArrayNormal(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
518
28
    {
519
28
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::NORMAL, ARRAY_EXPRESSIONS>;
520
521
252
        for (uint8_t i = 0; i < 8; 
++i224
)
522
224
        {
523
224
            ArrayT array(rawArray);
524
525
224
            initializeElements(array, owner);
526
527
224
            const size_t bitSize = arrayBitSizeOfPacked(array, owner, i);
528
224
            if (expectedBitSize != UNKNOWN_BIT_SIZE)
529
80
            {
530
80
                ASSERT_EQ(expectedBitSize, bitSize);
531
80
            }
532
224
            ASSERT_EQ(i + bitSize, arrayInitializeOffsetsPacked(array, owner, i));
533
534
224
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
535
224
            writer.writeBits(0, i);
536
224
            arrayWritePacked(array, owner, writer);
537
224
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
538
539
224
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
540
224
            ASSERT_EQ(0, reader.readBits(i));
541
224
            ArrayT readArray;
542
224
            arrayReadPacked(readArray, owner, reader, rawArray.size());
543
224
            ASSERT_EQ(array, readArray);
544
545
224
            testArrayCopiesAndMoves(array);
546
224
        }
547
28
    }
548
549
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
550
    void testPackedArrayAuto(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
551
28
    {
552
28
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::AUTO, ARRAY_EXPRESSIONS>;
553
554
252
        for (uint8_t i = 0; i < 8; 
++i224
)
555
224
        {
556
224
            ArrayT array(rawArray);
557
558
224
            initializeElements(array, owner);
559
560
224
            const size_t bitSize = arrayBitSizeOfPacked(array, owner, i);
561
224
            if (expectedBitSize != UNKNOWN_BIT_SIZE)
562
80
            {
563
80
                ASSERT_EQ(expectedBitSize, bitSize);
564
80
            }
565
224
            ASSERT_EQ(i + bitSize, arrayInitializeOffsetsPacked(array, owner, i));
566
567
224
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
568
224
            writer.writeBits(0, i);
569
224
            arrayWritePacked(array, owner, writer);
570
224
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
571
572
224
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
573
224
            ASSERT_EQ(0, reader.readBits(i));
574
224
            ArrayT readArray;
575
224
            arrayReadPacked(readArray, owner, reader);
576
224
            ASSERT_EQ(array, readArray);
577
578
224
            testArrayCopiesAndMoves(array);
579
224
        }
580
28
    }
581
582
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
583
    void testPackedArrayAligned(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
584
28
    {
585
28
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::ALIGNED, ARRAY_EXPRESSIONS>;
586
587
252
        for (uint8_t i = 0; i < 8; 
++i224
)
588
224
        {
589
224
            ArrayT array(rawArray);
590
591
224
            initializeElements(array, owner);
592
593
224
            const size_t bitSize = arrayBitSizeOfPacked(array, owner, i);
594
224
            if (expectedBitSize != UNKNOWN_BIT_SIZE && 
i == 080
)
595
10
            {
596
10
                ASSERT_EQ(expectedBitSize, bitSize);
597
10
            }
598
224
            ASSERT_EQ(i + bitSize, arrayInitializeOffsetsPacked(array, owner, i));
599
600
224
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
601
224
            writer.writeBits(0, i);
602
224
            arrayWritePacked(array, owner, writer);
603
224
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
604
605
224
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
606
224
            ASSERT_EQ(0, reader.readBits(i));
607
224
            ArrayT readArray;
608
224
            arrayReadPacked(readArray, owner, reader, rawArray.size());
609
224
            ASSERT_EQ(array, readArray);
610
611
224
            testArrayCopiesAndMoves(array);
612
224
        }
613
28
    }
614
615
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
616
    void testPackedArrayAlignedAuto(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
617
28
    {
618
28
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::ALIGNED_AUTO, ARRAY_EXPRESSIONS>;
619
620
252
        for (uint8_t i = 0; i < 8; 
++i224
)
621
224
        {
622
224
            ArrayT array(rawArray);
623
624
224
            initializeElements(array, owner);
625
626
224
            const size_t bitSize = arrayBitSizeOfPacked(array, owner, i);
627
224
            if (expectedBitSize != UNKNOWN_BIT_SIZE && 
i == 080
)
628
10
            {
629
10
                ASSERT_EQ(expectedBitSize, bitSize);
630
10
            }
631
224
            ASSERT_EQ(i + bitSize, arrayInitializeOffsetsPacked(array, owner, i));
632
633
224
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
634
224
            writer.writeBits(0, i);
635
224
            arrayWritePacked(array, owner, writer);
636
224
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
637
638
224
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
639
224
            ASSERT_EQ(0, reader.readBits(i));
640
224
            ArrayT readArray;
641
224
            arrayReadPacked(readArray, owner, reader);
642
224
            ASSERT_EQ(array, readArray);
643
644
224
            testArrayCopiesAndMoves(array);
645
224
        }
646
28
    }
647
648
    template <typename ARRAY>
649
    void testArrayCopiesAndMoves(const ARRAY& array)
650
3.31k
    {
651
3.31k
        ARRAY arrayCopy(array);
652
3.31k
        ASSERT_EQ(array, arrayCopy);
653
3.31k
        ASSERT_EQ(array.getRawArray(), arrayCopy.getRawArray());
654
3.31k
        ASSERT_FALSE(array < arrayCopy);
655
3.31k
        ASSERT_FALSE(arrayCopy < array);
656
657
3.31k
        ARRAY arrayCopyAssigned;
658
3.31k
        arrayCopyAssigned = array;
659
3.31k
        ASSERT_EQ(array, arrayCopyAssigned);
660
3.31k
        ASSERT_EQ(array.getRawArray(), arrayCopyAssigned.getRawArray());
661
662
3.31k
        const ARRAY arrayMoved = std::move(arrayCopy);
663
3.31k
        ASSERT_EQ(array, arrayMoved);
664
3.31k
        ASSERT_EQ(array.getRawArray(), arrayMoved.getRawArray());
665
666
3.31k
        ARRAY arrayMoveAssigned;
667
3.31k
        arrayMoveAssigned = std::move(arrayCopyAssigned);
668
3.31k
        ASSERT_EQ(array, arrayMoveAssigned);
669
3.31k
        ASSERT_EQ(array.getRawArray(), arrayMoveAssigned.getRawArray());
670
671
3.31k
        ARRAY arrayCopyWithPropagateAllocator(PropagateAllocator, array, std::allocator<uint8_t>());
672
3.31k
        ASSERT_EQ(array, arrayCopyWithPropagateAllocator);
673
3.31k
        ASSERT_EQ(array.getRawArray(), arrayCopyWithPropagateAllocator.getRawArray());
674
675
3.31k
        testArrayNoInitCopiesAndMoves(array);
676
3.31k
    }
677
678
    template <typename RAW_ARRAY>
679
    void checkUninitialized(const RAW_ARRAY& rawArray)
680
320
    {
681
320
        for (const auto& element : rawArray)
682
960
        {
683
960
            ASSERT_FALSE(element.isInitialized());
684
960
        }
685
320
    }
686
687
    template <typename ARRAY, typename T = typename ARRAY::RawArray::value_type,
688
            typename std::enable_if<std::is_constructible<T, NoInitT, T>::value, int>::type = 0>
689
    void testArrayNoInitCopiesAndMoves(const ARRAY& array)
690
64
    {
691
64
        ARRAY arrayCopy(NoInit, array);
692
64
        ASSERT_EQ(array.getRawArray().size(), arrayCopy.getRawArray().size());
693
64
        checkUninitialized(arrayCopy.getRawArray());
694
695
64
        ARRAY arrayCopyAssigned;
696
64
        arrayCopyAssigned.assign(NoInit, array);
697
64
        ASSERT_EQ(array.getRawArray().size(), arrayCopyAssigned.getRawArray().size());
698
64
        checkUninitialized(arrayCopyAssigned.getRawArray());
699
700
64
        const ARRAY arrayMoved(NoInit, std::move(arrayCopy));
701
64
        ASSERT_EQ(array.getRawArray().size(), arrayMoved.getRawArray().size());
702
64
        checkUninitialized(arrayMoved.getRawArray());
703
704
64
        ARRAY arrayMoveAssigned;
705
64
        arrayMoveAssigned.assign(NoInit, std::move(arrayCopyAssigned));
706
64
        ASSERT_EQ(array.getRawArray().size(), arrayMoveAssigned.getRawArray().size());
707
64
        checkUninitialized(arrayMoveAssigned.getRawArray());
708
709
64
        ARRAY arrayCopyWithPropagateAllocator(PropagateAllocator, NoInit, array, std::allocator<uint8_t>());
710
64
        ASSERT_EQ(array.getRawArray().size(), arrayCopyWithPropagateAllocator.getRawArray().size());
711
64
        checkUninitialized(arrayCopyWithPropagateAllocator.getRawArray());
712
64
    }
713
714
    template <typename ARRAY, typename T = typename ARRAY::RawArray::value_type,
715
            typename std::enable_if<!std::is_constructible<T, NoInitT, T>::value, int>::type = 0>
716
    void testArrayNoInitCopiesAndMoves(const ARRAY&)
717
3.24k
    {}
718
719
    static const size_t AUTO_LENGTH_BIT_SIZE = 8;
720
    static const size_t UNKNOWN_BIT_SIZE = std::numeric_limits<size_t>::max();
721
722
    std::array<uint8_t, 256> m_byteBuffer;
723
};
724
725
TEST_F(ArrayTest, intField4Array)
726
1
{
727
1
    const size_t NUM_BITS = 4;
728
1
    std::vector<int8_t> rawArray = {
729
1
            -static_cast<int8_t>(1U << (NUM_BITS - 1)), 7, static_cast<int8_t>(1U << (NUM_BITS - 1)) - 1};
730
1
    testArray<BitFieldArrayTraits<int8_t, NUM_BITS>>(rawArray, NUM_BITS);
731
732
    // empty
733
1
    testArray<BitFieldArrayTraits<int8_t, NUM_BITS>>(std::vector<int8_t>(), NUM_BITS);
734
1
}
735
736
TEST_F(ArrayTest, intField12Array)
737
1
{
738
1
    constexpr size_t NUM_BITS = 12;
739
1
    std::vector<int16_t> rawArray = {
740
1
            -static_cast<int16_t>(1U << (NUM_BITS - 1)), 7, static_cast<int16_t>(1U << (NUM_BITS - 1)) - 1};
741
1
    testArray<BitFieldArrayTraits<int16_t, NUM_BITS>>(rawArray, NUM_BITS);
742
1
}
743
744
TEST_F(ArrayTest, intField20Array)
745
1
{
746
1
    constexpr size_t NUM_BITS = 20;
747
1
    std::vector<int32_t> rawArray = {
748
1
            -static_cast<int32_t>(1U << (NUM_BITS - 1)), 7, static_cast<int32_t>(1U << (NUM_BITS - 1)) - 1};
749
1
    testArray<BitFieldArrayTraits<int32_t, NUM_BITS>>(rawArray, NUM_BITS);
750
1
}
751
752
TEST_F(ArrayTest, intField36Array)
753
1
{
754
1
    constexpr size_t NUM_BITS = 36;
755
1
    std::vector<int64_t> rawArray = {-static_cast<int64_t>(UINT64_C(1) << (NUM_BITS - 1)), 7,
756
1
            static_cast<int64_t>(UINT64_C(1) << (NUM_BITS - 1)) - 1};
757
1
    testArray<BitFieldArrayTraits<int64_t, NUM_BITS>>(rawArray, NUM_BITS);
758
1
}
759
760
TEST_F(ArrayTest, bitField4Array)
761
1
{
762
1
    constexpr size_t NUM_BITS = 4;
763
1
    std::vector<uint8_t> rawArray = {0, 7, (1U << NUM_BITS) - 1};
764
1
    testArray<BitFieldArrayTraits<uint8_t, NUM_BITS>>(rawArray, NUM_BITS);
765
766
    // empty
767
1
    testArray<BitFieldArrayTraits<uint8_t, NUM_BITS>>(std::vector<uint8_t>(), NUM_BITS);
768
1
}
769
770
TEST_F(ArrayTest, bitField12Array)
771
1
{
772
1
    constexpr size_t NUM_BITS = 12;
773
1
    std::vector<uint16_t> rawArray = {0, 7, (1U << NUM_BITS) - 1};
774
1
    testArray<BitFieldArrayTraits<uint16_t, NUM_BITS>>(rawArray, NUM_BITS);
775
1
}
776
777
TEST_F(ArrayTest, bitField20Array)
778
1
{
779
1
    constexpr size_t NUM_BITS = 20;
780
1
    std::vector<uint32_t> rawArray = {0, 7, (1U << NUM_BITS) - 1};
781
1
    testArray<BitFieldArrayTraits<uint32_t, NUM_BITS>>(rawArray, NUM_BITS);
782
1
}
783
784
TEST_F(ArrayTest, bitField36Array)
785
1
{
786
1
    constexpr size_t NUM_BITS = 36;
787
1
    std::vector<uint64_t> rawArray = {0, 7, (UINT64_C(1) << NUM_BITS) - 1};
788
1
    testArray<BitFieldArrayTraits<uint64_t, NUM_BITS>>(rawArray, NUM_BITS);
789
1
}
790
791
TEST_F(ArrayTest, dynamicIntField4Array)
792
1
{
793
1
    constexpr size_t NUM_BITS = 4;
794
1
    std::vector<int8_t> rawArray = {
795
1
            -static_cast<int8_t>(1U << (NUM_BITS - 1)), 7, static_cast<int8_t>(1U << (NUM_BITS - 1)) - 1};
796
1
    testArray<DynamicBitFieldArrayTraits<int8_t, ElementBitSizeWithOwner>>(
797
1
            rawArray, NUM_BITS, ArrayTestOwnerWithBitSize(NUM_BITS));
798
799
    // empty
800
1
    testArray<DynamicBitFieldArrayTraits<int8_t, ElementBitSizeWithoutOwner<NUM_BITS>>>(
801
1
            std::vector<int8_t>(), NUM_BITS);
802
1
}
803
804
TEST_F(ArrayTest, dynamicIntField8Array)
805
1
{
806
1
    constexpr size_t NUM_BITS = 8; // aligned to allow implicit array
807
1
    std::vector<int8_t> rawArray = {INT8_MIN, 7, INT8_MAX};
808
1
    testArray<DynamicBitFieldArrayTraits<int8_t, ElementBitSizeWithOwner>>(
809
1
            rawArray, NUM_BITS, ArrayTestOwnerWithBitSize(NUM_BITS));
810
1
}
811
812
TEST_F(ArrayTest, dynamicIntField12Array)
813
1
{
814
1
    constexpr size_t NUM_BITS = 12;
815
1
    std::vector<int16_t> rawArray = {
816
1
            -static_cast<int16_t>(1U << (NUM_BITS - 1)), 7, static_cast<int16_t>(1U << (NUM_BITS - 1)) - 1};
817
1
    testArray<DynamicBitFieldArrayTraits<int16_t, ElementBitSizeWithoutOwner<NUM_BITS>>>(rawArray, NUM_BITS);
818
1
}
819
820
TEST_F(ArrayTest, dynamicIntField20Array)
821
1
{
822
1
    constexpr size_t NUM_BITS = 20;
823
1
    std::vector<int32_t> rawArray = {
824
1
            -static_cast<int32_t>(1U << (NUM_BITS - 1)), 7, static_cast<int32_t>(1U << (NUM_BITS - 1)) - 1};
825
1
    testArray<DynamicBitFieldArrayTraits<int32_t, ElementBitSizeWithOwner>>(
826
1
            rawArray, NUM_BITS, ArrayTestOwnerWithBitSize(NUM_BITS));
827
1
}
828
829
TEST_F(ArrayTest, dynamicIntField36Array)
830
1
{
831
1
    constexpr size_t NUM_BITS = 36;
832
1
    std::vector<int64_t> rawArray = {-static_cast<int64_t>(UINT64_C(1) << (NUM_BITS - 1)), 7,
833
1
            static_cast<int64_t>(UINT64_C(1) << (NUM_BITS - 1)) - 1};
834
1
    testArray<DynamicBitFieldArrayTraits<int64_t, ElementBitSizeWithoutOwner<NUM_BITS>>>(rawArray, NUM_BITS);
835
1
}
836
837
TEST_F(ArrayTest, dynamicBitField4Array)
838
1
{
839
1
    constexpr size_t NUM_BITS = 4;
840
1
    std::vector<uint8_t> rawArray = {0, 7, (1U << NUM_BITS) - 1};
841
1
    testArray<DynamicBitFieldArrayTraits<uint8_t, ElementBitSizeWithOwner>>(
842
1
            rawArray, NUM_BITS, ArrayTestOwnerWithBitSize(NUM_BITS));
843
844
    // empty
845
1
    testArray<DynamicBitFieldArrayTraits<uint8_t, ElementBitSizeWithoutOwner<NUM_BITS>>>(
846
1
            std::vector<uint8_t>(), NUM_BITS);
847
1
}
848
849
TEST_F(ArrayTest, dynamicBitField8Array)
850
1
{
851
1
    constexpr size_t NUM_BITS = 8; // aligned to allow implicit array
852
1
    std::vector<uint8_t> rawArray = {0, 7, UINT8_MAX};
853
1
    testArray<DynamicBitFieldArrayTraits<uint8_t, ElementBitSizeWithOwner>>(
854
1
            rawArray, NUM_BITS, ArrayTestOwnerWithBitSize(NUM_BITS));
855
1
}
856
857
TEST_F(ArrayTest, dynamicBitField12Array)
858
1
{
859
1
    constexpr size_t NUM_BITS = 12;
860
1
    std::vector<uint16_t> rawArray = {0, 7, (1U << NUM_BITS) - 1};
861
1
    testArray<DynamicBitFieldArrayTraits<uint16_t, ElementBitSizeWithoutOwner<NUM_BITS>>>(rawArray, NUM_BITS);
862
1
}
863
864
TEST_F(ArrayTest, dynamicBitField20Array)
865
1
{
866
1
    constexpr size_t NUM_BITS = 20;
867
1
    std::vector<uint32_t> rawArray = {0, 7, (1U << NUM_BITS) - 1};
868
1
    testArray<DynamicBitFieldArrayTraits<uint32_t, ElementBitSizeWithOwner>>(
869
1
            rawArray, NUM_BITS, ArrayTestOwnerWithBitSize(NUM_BITS));
870
1
}
871
872
TEST_F(ArrayTest, dynamicBitField36Array)
873
1
{
874
1
    constexpr size_t NUM_BITS = 36;
875
1
    std::vector<uint64_t> rawArray = {0, 7, (UINT64_C(1) << NUM_BITS) - 1};
876
1
    testArray<DynamicBitFieldArrayTraits<uint64_t, ElementBitSizeWithoutOwner<NUM_BITS>>>(rawArray, NUM_BITS);
877
1
}
878
879
TEST_F(ArrayTest, stdInt8Array)
880
1
{
881
1
    std::vector<int8_t> rawArray = {INT8_MIN, 7, INT8_MAX};
882
1
    testArray<StdIntArrayTraits<int8_t>>(rawArray, 8);
883
884
    // empty
885
1
    testArray<StdIntArrayTraits<int8_t>>(std::vector<int8_t>(), 8);
886
1
}
887
888
TEST_F(ArrayTest, stdInt16Array)
889
1
{
890
1
    std::vector<int16_t> rawArray = {INT16_MIN, 7, INT16_MAX};
891
1
    testArray<StdIntArrayTraits<int16_t>>(rawArray, 16);
892
1
}
893
894
TEST_F(ArrayTest, stdInt32Array)
895
1
{
896
1
    std::vector<int32_t> rawArray = {INT32_MIN, 7, INT32_MAX};
897
1
    testArray<StdIntArrayTraits<int32_t>>(rawArray, 32);
898
1
}
899
900
TEST_F(ArrayTest, stdInt64Array)
901
1
{
902
1
    std::vector<int64_t> rawArray = {INT64_MIN, 7, INT64_MAX};
903
1
    testArray<StdIntArrayTraits<int64_t>>(rawArray, 64);
904
1
}
905
906
TEST_F(ArrayTest, stdUInt8Array)
907
1
{
908
1
    std::vector<uint8_t> rawArray = {0, 7, UINT8_MAX};
909
1
    testArray<StdIntArrayTraits<uint8_t>>(rawArray, 8);
910
911
    // empty
912
1
    testArray<StdIntArrayTraits<uint8_t>>(std::vector<uint8_t>(), 8);
913
1
}
914
915
TEST_F(ArrayTest, stdUInt16Array)
916
1
{
917
1
    std::vector<uint16_t> rawArray = {0, 7, UINT16_MAX};
918
1
    testArray<StdIntArrayTraits<uint16_t>>(rawArray, 16);
919
1
}
920
921
TEST_F(ArrayTest, stdUInt32Array)
922
1
{
923
1
    std::vector<uint32_t> rawArray = {0, 7, UINT32_MAX};
924
1
    testArray<StdIntArrayTraits<uint32_t>>(rawArray, 32);
925
1
}
926
927
TEST_F(ArrayTest, stdUInt64Array)
928
1
{
929
1
    std::vector<uint64_t> rawArray = {0, 7, UINT64_MAX};
930
1
    testArray<StdIntArrayTraits<uint64_t>>(rawArray, 64);
931
1
}
932
933
TEST_F(ArrayTest, varInt16Array)
934
1
{
935
1
    std::vector<int16_t> rawArray = {static_cast<int16_t>(1U << 5U), static_cast<int16_t>(1U << (5U + 8))};
936
1
    const size_t bitSize = 8 * (1 + 2);
937
1
    testArray<VarIntNNArrayTraits<int16_t>>(rawArray, bitSize, bitSize);
938
939
    // empty
940
1
    testArray<VarIntNNArrayTraits<int16_t>>(std::vector<int16_t>(), 0, 0);
941
1
}
942
943
TEST_F(ArrayTest, varInt32Array)
944
1
{
945
1
    std::vector<int32_t> rawArray = {
946
1
            static_cast<int32_t>(1U << 5U),
947
1
            static_cast<int32_t>(1U << (5U + 7)),
948
1
            static_cast<int32_t>(1U << (5U + 7 + 7)),
949
1
            static_cast<int32_t>(1U << (5U + 7 + 7 + 8)),
950
1
    };
951
1
    const size_t bitSize = 8 * (1 + 2 + 3 + 4);
952
1
    testArray<VarIntNNArrayTraits<int32_t>>(rawArray, bitSize, bitSize);
953
954
    // empty
955
1
    testArray<VarIntNNArrayTraits<int32_t>>(std::vector<int32_t>(), 0, 0);
956
1
}
957
958
TEST_F(ArrayTest, varInt64Array)
959
1
{
960
1
    std::vector<int64_t> rawArray = {
961
1
            static_cast<int64_t>(UINT64_C(1) << 5U),
962
1
            static_cast<int64_t>(UINT64_C(1) << (5U + 7)),
963
1
            static_cast<int64_t>(UINT64_C(1) << (5U + 7 + 7)),
964
1
            static_cast<int64_t>(UINT64_C(1) << (5U + 7 + 7 + 7)),
965
1
            static_cast<int64_t>(UINT64_C(1) << (5U + 7 + 7 + 7 + 7)),
966
1
            static_cast<int64_t>(UINT64_C(1) << (5U + 7 + 7 + 7 + 7 + 7)),
967
1
            static_cast<int64_t>(UINT64_C(1) << (5U + 7 + 7 + 7 + 7 + 7 + 7)),
968
1
            static_cast<int64_t>(UINT64_C(1) << (5U + 7 + 7 + 7 + 7 + 7 + 7 + 8)),
969
1
    };
970
1
    const size_t bitSize = 8 * (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8);
971
1
    testArray<VarIntNNArrayTraits<int64_t>>(rawArray, bitSize, bitSize);
972
973
    // empty
974
1
    testArray<VarIntNNArrayTraits<int64_t>>(std::vector<int64_t>(), 0, 0);
975
1
}
976
977
TEST_F(ArrayTest, varUInt16Array)
978
1
{
979
1
    std::vector<uint16_t> rawArray = {1U << 6U, 1U << (6U + 8)};
980
1
    const size_t bitSize = 8 * (1 + 2);
981
1
    testArray<VarIntNNArrayTraits<uint16_t>>(rawArray, bitSize, bitSize);
982
983
    // empty
984
1
    testArray<VarIntNNArrayTraits<uint16_t>>(std::vector<uint16_t>(), 0, 0);
985
1
}
986
987
TEST_F(ArrayTest, varUInt32Array)
988
1
{
989
1
    std::vector<uint32_t> rawArray = {1U << 6U, 1U << (6U + 7), 1U << (6U + 7 + 7), 1U << (6U + 7 + 7 + 8)};
990
1
    const size_t bitSize = 8 * (1 + 2 + 3 + 4);
991
1
    testArray<VarIntNNArrayTraits<uint32_t>>(rawArray, bitSize, bitSize);
992
993
    // empty
994
1
    testArray<VarIntNNArrayTraits<uint32_t>>(std::vector<uint32_t>(), 0, 0);
995
1
}
996
997
TEST_F(ArrayTest, varUInt64Array)
998
1
{
999
1
    std::vector<uint64_t> rawArray = {
1000
1
            UINT64_C(1) << 6U,
1001
1
            UINT64_C(1) << (6U + 7),
1002
1
            UINT64_C(1) << (6U + 7 + 7),
1003
1
            UINT64_C(1) << (6U + 7 + 7 + 7),
1004
1
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7),
1005
1
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7 + 7),
1006
1
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7 + 7 + 7),
1007
1
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7 + 7 + 7 + 8),
1008
1
    };
1009
1
    const size_t bitSize = 8 * (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8);
1010
1
    testArray<VarIntNNArrayTraits<uint64_t>>(rawArray, bitSize, bitSize);
1011
1012
    // empty
1013
1
    testArray<VarIntNNArrayTraits<uint64_t>>(std::vector<uint64_t>(), 0, 0);
1014
1
}
1015
1016
TEST_F(ArrayTest, varIntArray)
1017
1
{
1018
1
    std::vector<int64_t> rawArray;
1019
    // 1 byte
1020
1
    rawArray.push_back(0);
1021
1
    rawArray.push_back(-1);
1022
1
    rawArray.push_back(1);
1023
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 6U) + 1);
1024
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 6U) - 1);
1025
    // 2 bytes
1026
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 13U) + 1);
1027
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 13U) - 1);
1028
    // 3 bytes
1029
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 20U) + 1);
1030
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 20U) - 1);
1031
    // 4 bytes
1032
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 27U) + 1);
1033
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 27U) - 1);
1034
    // 5 bytes
1035
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 34U) + 1);
1036
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 34U) - 1);
1037
    // 6 bytes
1038
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 41U) + 1);
1039
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 41U) - 1);
1040
    // 7 bytes
1041
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 48U) + 1);
1042
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 48U) - 1);
1043
    // 8 bytes
1044
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 55U) + 1);
1045
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 55U) - 1);
1046
    // 9 bytes
1047
1
    rawArray.push_back(INT64_MIN + 1);
1048
1
    rawArray.push_back(INT64_MAX);
1049
    // 1 byte - special case, INT64_MIN stored as -0
1050
1
    rawArray.push_back(INT64_MIN);
1051
1
    const size_t bitSize = 8 * (3 + 2 * (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9) + 1);
1052
1
    testArray<VarIntArrayTraits<int64_t>>(rawArray, bitSize, bitSize);
1053
1054
    // empty
1055
1
    testArray<VarIntArrayTraits<int64_t>>(std::vector<int64_t>(), 0, 0);
1056
1
}
1057
1058
TEST_F(ArrayTest, varUIntArray)
1059
1
{
1060
1
    std::vector<uint64_t> rawArray;
1061
    // 1 byte
1062
1
    rawArray.push_back(0);
1063
1
    rawArray.push_back(1);
1064
1
    rawArray.push_back((UINT64_C(1) << 7U) - 1);
1065
    // 2 bytes
1066
1
    rawArray.push_back((UINT64_C(1) << 14U) - 1);
1067
    // 3 bytes
1068
1
    rawArray.push_back((UINT64_C(1) << 21U) - 1);
1069
    // 4 bytes
1070
1
    rawArray.push_back((UINT64_C(1) << 28U) - 1);
1071
    // 5 bytes
1072
1
    rawArray.push_back((UINT64_C(1) << 35U) - 1);
1073
    // 6 bytes
1074
1
    rawArray.push_back((UINT64_C(1) << 42U) - 1);
1075
    // 7 bytes
1076
1
    rawArray.push_back((UINT64_C(1) << 49U) - 1);
1077
    // 8 bytes
1078
1
    rawArray.push_back((UINT64_C(1) << 56U) - 1);
1079
    // 9 bytes
1080
1
    rawArray.push_back(UINT64_MAX);
1081
1
    const size_t bitSize = 8 * (2 + (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9));
1082
1
    testArray<VarIntArrayTraits<uint64_t>>(rawArray, bitSize, bitSize);
1083
1084
    // empty
1085
1
    testArray<VarIntArrayTraits<uint64_t>>(std::vector<uint64_t>(), 0, 0);
1086
1
}
1087
1088
TEST_F(ArrayTest, varSizeArray)
1089
1
{
1090
1
    std::vector<uint32_t> rawArray = {
1091
1
            UINT32_C(1) << 6U,
1092
1
            UINT32_C(1) << (6U + 7),
1093
1
            UINT32_C(1) << (6U + 7 + 7),
1094
1
            UINT32_C(1) << (6U + 7 + 7 + 7),
1095
1
            UINT32_C(1) << (1U + 7 + 7 + 7 + 8),
1096
1
    };
1097
1
    const size_t bitSize = 8 * (1 + 2 + 3 + 4 + 5);
1098
1
    testArray<VarSizeArrayTraits>(rawArray, bitSize, bitSize);
1099
1100
    // empty
1101
1
    testArray<VarSizeArrayTraits>(std::vector<uint32_t>(), 0, 0);
1102
1
}
1103
1104
TEST_F(ArrayTest, float16Array)
1105
1
{
1106
1
    const size_t elementBitSize = 16;
1107
1
    std::vector<float> rawArray = {-9.0, 0.0, 10.0};
1108
1
    testArray<Float16ArrayTraits>(rawArray, elementBitSize);
1109
1110
    // empty
1111
1
    testArray<Float16ArrayTraits>(std::vector<float>(), elementBitSize);
1112
1
}
1113
1114
TEST_F(ArrayTest, float32Array)
1115
1
{
1116
1
    const size_t elementBitSize = 32;
1117
1
    std::vector<float> rawArray = {-9.0, 0.0, 10.0};
1118
1
    testArray<Float32ArrayTraits>(rawArray, elementBitSize);
1119
1120
    // empty
1121
1
    testArray<Float32ArrayTraits>(std::vector<float>(), elementBitSize);
1122
1
}
1123
1124
TEST_F(ArrayTest, float64Array)
1125
1
{
1126
1
    const size_t elementBitSize = 64;
1127
1
    std::vector<double> rawArray = {-9.0, 0.0, 10.0};
1128
1
    testArray<Float64ArrayTraits>(rawArray, elementBitSize);
1129
1130
    // empty
1131
1
    testArray<Float64ArrayTraits>(std::vector<double>(), elementBitSize);
1132
1
}
1133
1134
TEST_F(ArrayTest, boolArray)
1135
1
{
1136
1
    const size_t elementBitSize = 1;
1137
1
    std::vector<bool> rawArray = {false, true};
1138
1
    testArray<BoolArrayTraits>(rawArray, elementBitSize);
1139
1140
    // empty
1141
1
    testArray<BoolArrayTraits>(std::vector<bool>(), elementBitSize);
1142
1
}
1143
1144
TEST_F(ArrayTest, bytesArray)
1145
1
{
1146
1
    const size_t bytesLengthBitSize = 8;
1147
1
    const size_t bytesBitSize = 2 * 8;
1148
1
    const size_t elementBitSize = bytesLengthBitSize + bytesBitSize;
1149
1
    std::vector<std::vector<uint8_t>> rawArray = {{{{1, 255}}, {{127, 128}}}};
1150
1
    testArray<BytesArrayTraits>(rawArray, elementBitSize);
1151
1152
    // empty
1153
1
    testArray<BytesArrayTraits>(std::vector<std::vector<uint8_t>>(), elementBitSize);
1154
1
}
1155
1156
TEST_F(ArrayTest, stringArray)
1157
1
{
1158
1
    const size_t stringLengthBitSize = 8;
1159
1
    const size_t stringBitSize = (sizeof("StringX") - 1) * 8; // without terminating character
1160
1
    const size_t elementBitSize = stringLengthBitSize + stringBitSize;
1161
1
    std::vector<std::string> rawArray = {"String0", "String1", "String2"};
1162
1
    testArray<StringArrayTraits>(rawArray, elementBitSize);
1163
1164
    // empty
1165
1
    testArray<StringArrayTraits>(std::vector<std::string>(), 0);
1166
1
}
1167
1168
TEST_F(ArrayTest, bitBufferArray)
1169
1
{
1170
1
    const size_t bitBufferLengthBitSize = 8;
1171
1
    const size_t bitBufferBitSize = 10;
1172
1
    const size_t elementBitSize = bitBufferLengthBitSize + bitBufferBitSize;
1173
1
    std::vector<BitBuffer> rawArray = {
1174
1
            BitBuffer(bitBufferBitSize), BitBuffer(bitBufferBitSize), BitBuffer(bitBufferBitSize)};
1175
1
    testArray<BitBufferArrayTraits>(rawArray, elementBitSize);
1176
1177
    // empty
1178
1
    testArray<BitBufferArrayTraits>(std::vector<BitBuffer>(), 0);
1179
1
}
1180
1181
TEST_F(ArrayTest, enumArray)
1182
1
{
1183
1
    std::vector<ArrayEnum> rawArray = {ArrayEnum::VALUE1, ArrayEnum::VALUE2, ArrayEnum::VALUE3};
1184
1
    const size_t elementBitSize = 8;
1185
1
    testArray<EnumArrayTraits<ArrayEnum>>(rawArray, elementBitSize);
1186
1187
    // empty
1188
1
    testArray<EnumArrayTraits<ArrayEnum>>(std::vector<ArrayEnum>(), elementBitSize);
1189
1190
1
    std::vector<ArrayEnum> invalidRawArray = {static_cast<ArrayEnum>(10)};
1191
1
    ASSERT_THROW(testArray<EnumArrayTraits<ArrayEnum>>(invalidRawArray, elementBitSize), CppRuntimeException);
1192
1
}
1193
1194
TEST_F(ArrayTest, bitmaskArray)
1195
1
{
1196
1
    std::vector<ArrayBitmask> rawArray = {
1197
1
            ArrayBitmask::Values::READ, ArrayBitmask::Values::WRITE, ArrayBitmask::Values::CREATE};
1198
1
    const size_t elementBitSize = 8;
1199
1
    testArray<BitmaskArrayTraits<ArrayBitmask>>(rawArray, elementBitSize);
1200
1201
    // empty
1202
1
    testArray<BitmaskArrayTraits<ArrayBitmask>>(std::vector<ArrayBitmask>(), elementBitSize);
1203
1
}
1204
1205
TEST_F(ArrayTest, objectArray)
1206
1
{
1207
1
    std::vector<ArrayObject> rawArray = {ArrayObject(0xAB), ArrayObject(0xCD), ArrayObject(0xEF)};
1208
1
    testArray<ObjectArrayTraits<ArrayObject, ArrayObjectElementFactory>, std::vector<ArrayObject>,
1209
1
            ArrayObjectArrayExpressions>(rawArray, 31);
1210
1211
    // empty
1212
1
    testArray<ObjectArrayTraits<ArrayObject, ArrayObjectElementFactory>, std::vector<ArrayObject>,
1213
1
            ArrayObjectArrayExpressions>(std::vector<ArrayObject>(), 31);
1214
1
}
1215
1216
TEST_F(ArrayTest, paramObjectArray)
1217
1
{
1218
1
    ArrayParamObjectOwner owner{ArrayObject(0xEF)};
1219
1
    std::vector<ArrayParamObject> rawArray = {
1220
1
            ArrayParamObject(0xAB), ArrayParamObject(0xBC), ArrayParamObject(0xCD)};
1221
1
    testArray<ObjectArrayTraits<ArrayParamObject, ArrayParamObjectElementFactory>,
1222
1
            std::vector<ArrayParamObject>, ArrayParamObjectArrayExpressions>(rawArray, 32, owner);
1223
1
}
1224
1225
TEST_F(ArrayTest, stdInt8PackedArray)
1226
1
{
1227
1
    std::vector<int8_t> rawArray = {-4, -3, -1, 0, 2, 4, 6, 8, 10, 10, 11};
1228
1
    testPackedArray<StdIntArrayTraits<int8_t>>(rawArray);
1229
1
}
1230
1231
TEST_F(ArrayTest, stdInt64PackedArray)
1232
1
{
1233
    // will not be packed
1234
1
    std::vector<int64_t> rawArray = {INT64_MIN, 1, -1, INT64_MAX};
1235
1
    testPackedArray<StdIntArrayTraits<int64_t>>(rawArray);
1236
1
}
1237
1238
TEST_F(ArrayTest, stdUInt64PackedArray)
1239
1
{
1240
    // will have maxBitNumber 62 bits
1241
1
    std::vector<uint64_t> rawArray = {0, INT64_MAX / 2, 100, 200, 300, 400, 500, 600, 700};
1242
1
    testPackedArray<StdIntArrayTraits<uint64_t>>(rawArray);
1243
1
}
1244
1245
TEST_F(ArrayTest, bitField64PackedArray)
1246
1
{
1247
1
    using ArrayTraits = BitFieldArrayTraits<uint64_t, 64>;
1248
1249
    // none-zero delta
1250
1
    std::vector<uint64_t> rawArray1 = {10, 11, 12};
1251
1
    const size_t array1MaxDeltaBitSize = 1;
1252
1
    const size_t array1BitSizeOf = calcPackedBitSize(64, rawArray1.size(), array1MaxDeltaBitSize);
1253
1
    const size_t array1AlignedBitSizeOf = calcAlignedPackedBitSize(64, rawArray1.size(), array1MaxDeltaBitSize);
1254
1
    testPackedArray<ArrayTraits>(rawArray1, array1BitSizeOf, array1AlignedBitSizeOf);
1255
1256
    // zero delta
1257
1
    std::vector<uint64_t> rawArray2 = {10, 10, 10};
1258
1
    const size_t array2BitSizeOf = PACKING_DESCRIPTOR_BITSIZE + 64;
1259
1
    const size_t array2AlignedBitSizeOf = PACKING_DESCRIPTOR_BITSIZE + 64 +
1260
1
            /* alignment before element 2 */ (8 - PACKING_DESCRIPTOR_BITSIZE);
1261
1
    testPackedArray<ArrayTraits>(rawArray2, array2BitSizeOf, array2AlignedBitSizeOf);
1262
1263
    // one-element array
1264
1
    std::vector<uint64_t> rawArray3 = {10};
1265
1
    const size_t array3BitSizeOf = 1 + 64;
1266
1
    const size_t array3AlignedBitSizeOf = 1 + 64; // no alignment before first element, no more elements
1267
1
    testPackedArray<ArrayTraits>(rawArray3, array3BitSizeOf, array3AlignedBitSizeOf);
1268
1269
    // empty array
1270
1
    std::vector<uint64_t> rawArray4 = {};
1271
1
    const size_t array4BitSizeOf = 0;
1272
1
    const size_t array4AlignedBitSizeOf = 0;
1273
1
    testPackedArray<ArrayTraits>(rawArray4, array4BitSizeOf, array4AlignedBitSizeOf);
1274
1275
    // packing not enabled, delta is too big
1276
1
    testPackedArray<ArrayTraits>(std::vector<uint64_t>{0, UINT64_MAX});
1277
1
    testPackedArray<ArrayTraits>(std::vector<uint64_t>{UINT64_MAX, UINT64_MAX / 2, 0});
1278
1279
    // will have maxBitNumber 62 bits
1280
1
    testPackedArray<ArrayTraits>(
1281
1
            std::vector<uint64_t>{0, static_cast<uint64_t>(INT64_MAX / 2), 100, 200, 300, 400, 500, 600, 700});
1282
1
}
1283
1284
TEST_F(ArrayTest, bitField8PackedArray)
1285
1
{
1286
1
    using ArrayTraits = BitFieldArrayTraits<uint8_t, 8>;
1287
1288
    // will not be packed because unpacked 8bit values will be more efficient
1289
1
    std::vector<uint8_t> rawArray1 = {UINT8_MAX, 0, 10, 20, 30, 40}; // max_bit_number 8, delta needs 9 bits
1290
1
    const size_t array1BitSizeOf = 1 + 6 * 8;
1291
1
    const size_t array1AlignedBitSizeOf = 1 + 8 + /* alignment */ 7 + 5 * 8;
1292
1
    testPackedArray<ArrayTraits>(rawArray1, array1BitSizeOf, array1AlignedBitSizeOf);
1293
1294
    // will not be packed because unpacked 8bit values will be more efficient
1295
    // (6 bits more are needed to store max_bit_number in descriptor if packing was enabled)
1296
1
    std::vector<uint8_t> rawArray2 = {
1297
1
            UINT8_MAX, UINT8_MAX / 2 + 1, 10, 20, 30, 40}; // max_bit_number 7, delta needs 8 bits
1298
1
    const size_t array2BitSizeOf = 1 + 6 * 8;
1299
1
    const size_t array2AlignedBitSizeOf = 1 + 8 + /* alignment */ 7 + 5 * 8;
1300
1
    testPackedArray<ArrayTraits>(rawArray2, array2BitSizeOf, array2AlignedBitSizeOf);
1301
1
}
1302
1303
TEST_F(ArrayTest, intField64PackedArray)
1304
1
{
1305
1
    using ArrayTraits = BitFieldArrayTraits<int64_t, 64>;
1306
1307
1
    testPackedArray<ArrayTraits>(std::vector<int64_t>{-10, 11, -12});
1308
1
    testPackedArray<ArrayTraits>(std::vector<int64_t>{-10, -10, -10}); // zero delta
1309
1310
1
    testPackedArray<ArrayTraits>(std::vector<int64_t>{}); // empty
1311
1
    testPackedArray<ArrayTraits>(std::vector<int64_t>{10}); // single element
1312
1313
    // packing not enabled, delta is too big
1314
1
    testPackedArray<ArrayTraits>(std::vector<int64_t>{INT64_MIN, INT64_MAX});
1315
1
    testPackedArray<ArrayTraits>(std::vector<int64_t>{INT64_MIN, 0, INT64_MAX});
1316
1
}
1317
1318
TEST_F(ArrayTest, intField16PackedArray)
1319
1
{
1320
1
    using ArrayTraits = BitFieldArrayTraits<int16_t, 16>;
1321
1322
    // will not be packed because unpacked 16bit values will be more efficient
1323
    // (6 bits more are needed to store max_bit_number in descriptor if packing was enabled)
1324
1
    std::vector<int16_t> rawArray = {INT16_MIN, -1, 10, 20, 30, 40}; // max_bit_number 15, delta needs 16 bits
1325
1
    const size_t unpackedBitSizeOf = 1 + 6 * 16;
1326
1
    const size_t unpackedAlignedBitSizeOf = 1 + 16 + /* alignment */ 7 + 5 * 16;
1327
1
    testPackedArray<ArrayTraits>(rawArray, unpackedBitSizeOf, unpackedAlignedBitSizeOf);
1328
1
}
1329
1330
TEST_F(ArrayTest, dynamicBitField8PackedArray)
1331
1
{
1332
    // will not be packed because unpacked 8bit values will be more efficient
1333
1
    std::vector<uint8_t> rawArray1 = {UINT8_MAX, 0, 10, 20, 30, 40}; // max_bit_number 8, delta needs 9 bits
1334
1
    const size_t array1BitSizeOf = 1 + 6 * 8;
1335
1
    const size_t array1AlignedBitSizeOf = 1 + 8 + /* alignment */ 7 + 5 * 8;
1336
1
    testPackedArray<DynamicBitFieldArrayTraits<uint8_t, ElementBitSizeWithOwner>>(
1337
1
            rawArray1, array1BitSizeOf, array1AlignedBitSizeOf, ArrayTestOwnerWithBitSize(8));
1338
1339
    // will not be packed because unpacked 8bit 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<uint8_t> rawArray2 = {
1342
1
            UINT8_MAX, UINT8_MAX / 2 + 1, 10, 20, 30, 40}; // max_bit_number 7, delta needs 8 bits
1343
1
    const size_t array2BitSizeOf = 1 + 6 * 8;
1344
1
    const size_t array2AlignedBitSizeOf = 1 + 8 + /* alignment */ 7 + 5 * 8;
1345
1
    testPackedArray<DynamicBitFieldArrayTraits<uint8_t, ElementBitSizeWithoutOwner<8>>>(
1346
1
            rawArray2, array2BitSizeOf, array2AlignedBitSizeOf);
1347
1
}
1348
1349
TEST_F(ArrayTest, varUInt64PackedArray)
1350
1
{
1351
1
    std::vector<uint64_t> rawArray = {
1352
1
            UINT64_C(1) << 6U,
1353
1
            UINT64_C(1) << (6U + 7),
1354
1
            UINT64_C(1) << (6U + 7 + 7),
1355
1
            UINT64_C(1) << (6U + 7 + 7 + 7),
1356
1
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7),
1357
1
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7 + 7),
1358
1
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7 + 7 + 7),
1359
1
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7 + 7 + 7 + 8),
1360
1
    };
1361
1
    testPackedArray<VarIntNNArrayTraits<uint64_t>>(rawArray);
1362
1363
1
    std::vector<uint64_t> unpackedRawArray = {UINT64_C(5000000), 0, 0, 0, 0, 0, 0};
1364
1
    const size_t unpackedBitSizeOf = 1 + 32 + 6 * 8;
1365
1
    const size_t unpackedAlignedBitSizeOf = 1 + 32 + /* alignment */ 7 + 6 * 8;
1366
1
    testPackedArray<VarIntNNArrayTraits<uint64_t>>(
1367
1
            unpackedRawArray, unpackedBitSizeOf, unpackedAlignedBitSizeOf);
1368
1
}
1369
1370
TEST_F(ArrayTest, varSizePackedArray)
1371
1
{
1372
1
    std::vector<uint32_t> rawArray = {
1373
1
            UINT32_C(1) << 6U,
1374
1
            UINT32_C(1) << (6U + 7),
1375
1
            UINT32_C(1) << (6U + 7 + 7),
1376
1
            UINT32_C(1) << (6U + 7 + 7 + 7),
1377
1
            UINT32_C(1) << (1U + 7 + 7 + 7 + 8),
1378
1
    };
1379
1
    testPackedArray<VarSizeArrayTraits>(rawArray);
1380
1
}
1381
1382
TEST_F(ArrayTest, enumPackedArray)
1383
1
{
1384
1
    std::vector<ArrayEnum> rawArray = {ArrayEnum::VALUE1, ArrayEnum::VALUE2, ArrayEnum::VALUE3};
1385
1
    testPackedArray<EnumArrayTraits<ArrayEnum>>(rawArray);
1386
1
}
1387
1388
TEST_F(ArrayTest, bitmaskPackedArray)
1389
1
{
1390
1
    std::vector<ArrayBitmask> rawArray = {
1391
1
            ArrayBitmask::Values::READ, ArrayBitmask::Values::WRITE, ArrayBitmask::Values::CREATE};
1392
1
    testPackedArray<BitmaskArrayTraits<ArrayBitmask>>(rawArray);
1393
1
}
1394
1395
TEST_F(ArrayTest, objectPackedArray)
1396
1
{
1397
1
    std::vector<ArrayObject> rawArray = {ArrayObject(0xAB), ArrayObject(0xCD), ArrayObject(0xEF)};
1398
1
    testPackedArray<ObjectArrayTraits<ArrayObject, ArrayObjectElementFactory>, std::vector<ArrayObject>,
1399
1
            ArrayObjectArrayExpressions>(rawArray);
1400
1
}
1401
1402
TEST_F(ArrayTest, paramObjectPackedArray)
1403
1
{
1404
1
    ArrayParamObjectOwner owner{ArrayObject(0xEF)};
1405
1
    std::vector<ArrayParamObject> rawArray = {
1406
1
            ArrayParamObject(0xAB), ArrayParamObject(0xBC), ArrayParamObject(0xCD)};
1407
1
    testPackedArray<ObjectArrayTraits<ArrayParamObject, ArrayParamObjectElementFactory>,
1408
1
            std::vector<ArrayParamObject>, ArrayParamObjectArrayExpressions>(rawArray, owner);
1409
1
}
1410
1411
TEST_F(ArrayTest, createOptionalArray)
1412
1
{
1413
1
    using ArrayT = Array<std::vector<uint8_t>, BitFieldArrayTraits<uint8_t, 8>, ArrayType::NORMAL>;
1414
1
    InplaceOptionalHolder<ArrayT> optionalArray = createOptionalArray<ArrayT>(NullOpt);
1415
1
    ASSERT_FALSE(optionalArray.hasValue());
1416
1417
1
    const std::vector<uint8_t> array = {0, 7, UINT8_MAX};
1418
1
    optionalArray = createOptionalArray<ArrayT>(array);
1419
1
    ASSERT_TRUE(optionalArray.hasValue());
1420
1
    ASSERT_EQ(array, optionalArray->getRawArray());
1421
1
}
1422
1423
} // namespace zserio