test/zserio/ArrayViewTest.cpp
Line | Count | Source |
1 | | #include <algorithm> |
2 | | |
3 | | #include "gtest/gtest.h" |
4 | | #include "zserio/ArrayView.h" |
5 | | #include "zserio/Types.h" |
6 | | |
7 | | namespace zserio |
8 | | { |
9 | | |
10 | | namespace |
11 | | { |
12 | | |
13 | | struct TestObject |
14 | | { |
15 | | UInt32 field; |
16 | | |
17 | | constexpr bool operator==(const TestObject& other) const |
18 | 15 | { |
19 | 15 | return field == other.field; |
20 | 15 | } |
21 | | |
22 | | constexpr bool operator<(const TestObject& other) const |
23 | 3 | { |
24 | 3 | return field < other.field; |
25 | 3 | } |
26 | | }; |
27 | | |
28 | | struct VarDynInt16Owner |
29 | | { |
30 | | uint8_t numBits = 10; |
31 | | }; |
32 | | |
33 | | } // namespace |
34 | | |
35 | | template <> |
36 | | class View<TestObject> |
37 | | { |
38 | | public: |
39 | | explicit View(const TestObject& data) : |
40 | 58 | m_data(data) |
41 | 58 | {} |
42 | | |
43 | | UInt32 field() const |
44 | 35 | { |
45 | 35 | return m_data.field; |
46 | 35 | } |
47 | | |
48 | | constexpr bool operator==(const View& other) const |
49 | 8 | { |
50 | 8 | return m_data == other.m_data; |
51 | 8 | } |
52 | | |
53 | | constexpr bool operator!=(const View& other) const |
54 | 4 | { |
55 | 4 | return !operator==(other); |
56 | 4 | } |
57 | | |
58 | | constexpr bool operator<(const View& other) const |
59 | 3 | { |
60 | 3 | return m_data < other.m_data; |
61 | 3 | } |
62 | | |
63 | | private: |
64 | | const TestObject& m_data; |
65 | | }; |
66 | | |
67 | | namespace detail |
68 | | { |
69 | | |
70 | | template <> |
71 | | struct ObjectTraits<TestObject> |
72 | | { |
73 | | struct PackingContext |
74 | | { |
75 | | DeltaContext field; |
76 | | }; |
77 | | |
78 | | static BitSize bitSizeOf(const View<TestObject>& view, BitSize bitPosition) |
79 | 2 | { |
80 | 2 | BitSize endBitPosition = bitPosition; |
81 | 2 | endBitPosition += detail::bitSizeOf(view.field(), endBitPosition); |
82 | 2 | return endBitPosition - bitPosition; |
83 | 2 | } |
84 | | |
85 | | static void write(BitStreamWriter& writer, const View<TestObject>& view) |
86 | 2 | { |
87 | 2 | detail::write(writer, view.field()); |
88 | 2 | } |
89 | | |
90 | | static View<TestObject> read(BitStreamReader& reader, TestObject& data) |
91 | 2 | { |
92 | 2 | View<TestObject> view(data); |
93 | 2 | detail::read(reader, data.field); |
94 | 2 | return view; |
95 | 2 | } |
96 | | |
97 | | static void initContext(PackingContext& packingContext, const View<TestObject>& view) |
98 | 10 | { |
99 | 10 | detail::initContext(packingContext.field, view.field()); |
100 | 10 | } |
101 | | |
102 | | static BitSize bitSizeOf(PackingContext& packingContext, const View<TestObject>& view, BitSize bitPosition) |
103 | 5 | { |
104 | 5 | BitSize endBitPosition = bitPosition; |
105 | 5 | endBitPosition += detail::bitSizeOf(packingContext.field, view.field(), endBitPosition); |
106 | 5 | return endBitPosition - bitPosition; |
107 | 5 | } |
108 | | |
109 | | static void write(PackingContext& packingContext, BitStreamWriter& writer, const View<TestObject>& view) |
110 | 5 | { |
111 | 5 | detail::write(packingContext.field, writer, view.field()); |
112 | 5 | } |
113 | | |
114 | | static void read(PackingContext& packingContext, BitStreamReader& reader, TestObject& data) |
115 | 5 | { |
116 | | |
117 | 5 | detail::read(packingContext.field, reader, data.field); |
118 | 5 | } |
119 | | }; |
120 | | |
121 | | } // namespace detail |
122 | | |
123 | | struct VarDynInt16ArrayTraits |
124 | | { |
125 | | using OwnerType = VarDynInt16Owner; |
126 | | |
127 | | static View<DynInt16> at(const VarDynInt16Owner& owner, const DynInt16& element, size_t) |
128 | 48 | { |
129 | 48 | return View<DynInt16>(element, owner.numBits); |
130 | 48 | } |
131 | | |
132 | | static void read(BitStreamReader& reader, const VarDynInt16Owner& owner, DynInt16& element, size_t) |
133 | 2 | { |
134 | 2 | detail::read(reader, element, owner.numBits); |
135 | 2 | } |
136 | | |
137 | | static void read(detail::DeltaContext& context, BitStreamReader& reader, const VarDynInt16Owner& owner, |
138 | | DynInt16& element, size_t) |
139 | 7 | { |
140 | 7 | detail::read(context, reader, element, owner.numBits); |
141 | 7 | } |
142 | | }; |
143 | | |
144 | | TEST(ArrayViewTest, boolArray) |
145 | 1 | { |
146 | 1 | Vector<Bool> rawArray1{true, false}; |
147 | 1 | Vector<Bool> rawArray2{true, true}; |
148 | | |
149 | 1 | ArrayView<const Bool> array1(rawArray1); |
150 | 1 | ASSERT_EQ(rawArray1.at(0), array1.at(0)); |
151 | 1 | ASSERT_EQ(rawArray1.at(1), array1.at(1)); |
152 | | |
153 | 1 | ArrayView<const Bool> array2(rawArray2); |
154 | 1 | ASSERT_FALSE(array1 == array2); |
155 | 1 | ASSERT_TRUE(array1 != array2); |
156 | 1 | ASSERT_LT(array1, array2); |
157 | | |
158 | 1 | const BitSize bitSize = detail::bitSizeOf<detail::ArrayType::AUTO>(array1); |
159 | 1 | BitBuffer buffer(bitSize); |
160 | 1 | BitStreamWriter writer(buffer); |
161 | 1 | detail::write<detail::ArrayType::AUTO>(writer, array1); |
162 | 1 | ASSERT_EQ(bitSize, writer.getBitPosition()); |
163 | | |
164 | 1 | BitStreamReader reader(buffer); |
165 | 1 | Vector<Bool> readRawArray; |
166 | 1 | detail::read<detail::ArrayType::AUTO>(reader, readRawArray); |
167 | 1 | ASSERT_EQ(bitSize, reader.getBitPosition()); |
168 | 1 | ASSERT_EQ(rawArray1, readRawArray); |
169 | 1 | } |
170 | | |
171 | | TEST(ArrayViewTest, boolPackedArray) |
172 | 1 | { |
173 | 1 | Vector<Bool> rawArray{true, false, true, false, true}; |
174 | 1 | ArrayView<const Bool> array(rawArray); |
175 | | |
176 | 1 | const BitSize packedBitSize = detail::bitSizeOfPacked<detail::ArrayType::AUTO>(array); |
177 | 1 | BitBuffer buffer(packedBitSize); |
178 | 1 | BitStreamWriter writer(buffer); |
179 | 1 | detail::writePacked<detail::ArrayType::AUTO>(writer, array); |
180 | 1 | ASSERT_EQ(packedBitSize, writer.getBitPosition()); |
181 | | |
182 | 1 | BitStreamReader reader(buffer); |
183 | 1 | Vector<Bool> readRawArray; |
184 | 1 | detail::readPacked<detail::ArrayType::AUTO>(reader, readRawArray, rawArray.size()); |
185 | 1 | ASSERT_EQ(packedBitSize, reader.getBitPosition()); |
186 | 1 | ASSERT_EQ(rawArray, readRawArray); |
187 | 1 | } |
188 | | |
189 | | TEST(ArrayViewTest, int8Array) |
190 | 1 | { |
191 | 1 | Vector<Int8> rawArray1{0, 13}; |
192 | 1 | Vector<Int8> rawArray2{0, 42}; |
193 | | |
194 | 1 | ArrayView<const Int8> array1(rawArray1); |
195 | 1 | ASSERT_EQ(rawArray1.at(0), array1.at(0)); |
196 | 1 | ASSERT_EQ(rawArray1.at(1), array1.at(1)); |
197 | | |
198 | 1 | ArrayView<const Int8> array2(rawArray2); |
199 | 1 | ASSERT_FALSE(array1 == array2); |
200 | 1 | ASSERT_TRUE(array1 != array2); |
201 | 1 | ASSERT_LT(array1, array2); |
202 | | |
203 | 1 | const BitSize bitSize = detail::bitSizeOf<detail::ArrayType::AUTO>(array1); |
204 | 1 | BitBuffer buffer(bitSize); |
205 | 1 | BitStreamWriter writer(buffer); |
206 | 1 | detail::write<detail::ArrayType::AUTO>(writer, array1); |
207 | 1 | ASSERT_EQ(bitSize, writer.getBitPosition()); |
208 | | |
209 | 1 | BitStreamReader reader(buffer); |
210 | 1 | Vector<Int8> readRawArray; |
211 | 1 | detail::read<detail::ArrayType::AUTO>(reader, readRawArray); |
212 | 1 | ASSERT_EQ(bitSize, reader.getBitPosition()); |
213 | 1 | ASSERT_EQ(rawArray1, readRawArray); |
214 | 1 | } |
215 | | |
216 | | TEST(ArrayViewTest, int8PackedArray) |
217 | 1 | { |
218 | 1 | Vector<Int8> rawArray = {-4, -3, -1, 0, 2, 4, 6, 8, 10, 10, 11}; |
219 | 1 | ArrayView<const Int8> array(rawArray); |
220 | | |
221 | 1 | static_assert(detail::is_packable_v<Int8>, "shall be packable"); |
222 | 1 | static_assert(detail::is_packable_v<const Int8>, "shall be packable"); |
223 | | |
224 | | // maxBitNumber == 2 |
225 | | // packingDescriptor 7 + firstElement 8 + 10 * (maxBitNumber 2 + 1) |
226 | 1 | static constexpr BitSize packedBitSize = 45; |
227 | 1 | ASSERT_EQ(packedBitSize, detail::bitSizeOfPacked<detail::ArrayType::NORMAL>(array)); |
228 | | |
229 | 1 | BitBuffer buffer(packedBitSize); |
230 | 1 | BitStreamWriter writer(buffer); |
231 | 1 | detail::writePacked<detail::ArrayType::NORMAL>(writer, array); |
232 | 1 | ASSERT_EQ(packedBitSize, writer.getBitPosition()); |
233 | | |
234 | 1 | BitStreamReader reader(buffer); |
235 | 1 | Vector<Int8> readRawArray; |
236 | 1 | detail::readPacked<detail::ArrayType::NORMAL>(reader, readRawArray, rawArray.size()); |
237 | 1 | ASSERT_EQ(rawArray, readRawArray); |
238 | | |
239 | 1 | ASSERT_EQ(rawArray.size(), array.size()); |
240 | 1 | ASSERT_FALSE(array.empty()); |
241 | | |
242 | 1 | Vector<Int8> emptyRawArray; |
243 | 1 | ArrayView<const Int8> emptyArray(emptyRawArray); |
244 | 1 | ASSERT_TRUE(emptyArray.empty()); |
245 | | |
246 | 1 | ASSERT_THROW(emptyArray.front(), CppRuntimeException); |
247 | | |
248 | 1 | ASSERT_EQ(rawArray.front(), array.front()); |
249 | 1 | ASSERT_EQ(rawArray.back(), array.back()); |
250 | | |
251 | 1 | auto it = array.begin(); |
252 | 1 | ASSERT_EQ(-4, *it); |
253 | 1 | ASSERT_EQ(-1, it[2]); |
254 | 1 | it += 2; |
255 | 1 | ASSERT_EQ(-1, *it); |
256 | 1 | ASSERT_EQ(-3, it[-1]); |
257 | 1 | it -= 1; |
258 | 1 | ASSERT_EQ(-3, *it); |
259 | 1 | auto otherIt = it + 2; |
260 | 1 | ASSERT_EQ(0, *otherIt); |
261 | 1 | ASSERT_EQ(2, *(++otherIt)); |
262 | 1 | ASSERT_EQ(2, *(otherIt++)); |
263 | 1 | ASSERT_EQ(4, *otherIt); |
264 | 1 | ASSERT_EQ(2, *(--otherIt)); |
265 | 1 | ASSERT_EQ(2, *(otherIt--)); |
266 | 1 | ASSERT_EQ(0, *otherIt); |
267 | 1 | otherIt = 2 + it; |
268 | 1 | ASSERT_EQ(0, *otherIt); |
269 | 1 | otherIt = it - 1; |
270 | 1 | ASSERT_EQ(-4, *otherIt); |
271 | 1 | ASSERT_EQ(1, it - otherIt); |
272 | 1 | ASSERT_EQ(-1, otherIt - it); |
273 | 1 | ASSERT_EQ(array.size(), array.end() - array.begin()); |
274 | | |
275 | 1 | ASSERT_TRUE(otherIt == array.begin()); |
276 | 1 | ASSERT_FALSE(otherIt == array.end()); |
277 | | |
278 | 1 | ASSERT_TRUE(otherIt != array.end()); |
279 | 1 | ASSERT_FALSE(otherIt != array.begin()); |
280 | | |
281 | 1 | ASSERT_TRUE(otherIt < array.end()); |
282 | 1 | ASSERT_FALSE(array.end() < otherIt); |
283 | | |
284 | 1 | ASSERT_TRUE(array.end() > array.begin()); |
285 | 1 | ASSERT_FALSE(array.begin() > array.end()); |
286 | | |
287 | 1 | ASSERT_TRUE(array.begin() <= array.end()); |
288 | 1 | ASSERT_TRUE(array.begin() <= array.begin()); |
289 | 1 | ASSERT_FALSE(array.end() <= array.begin()); |
290 | | |
291 | 1 | ASSERT_TRUE(array.end() >= array.begin()); |
292 | 1 | ASSERT_TRUE(array.end() >= array.end()); |
293 | 1 | ASSERT_FALSE(array.begin() >= array.end()); |
294 | | |
295 | 1 | size_t i = 0; |
296 | 1 | for (auto element : array) |
297 | 11 | { |
298 | 11 | ASSERT_EQ(rawArray[i++], element); |
299 | 11 | } |
300 | | |
301 | 1 | i = array.size() - 1; |
302 | 12 | for (auto rit = array.rbegin(); rit < array.rend(); ++rit11 ) |
303 | 11 | { |
304 | 11 | ASSERT_EQ(rawArray[i--], *rit); |
305 | 11 | } |
306 | | |
307 | 5 | auto foundIt = std::find_if(array.begin(), array.end(), [](auto value) 1 { |
308 | 5 | return value > 0; |
309 | 5 | }); |
310 | 1 | ASSERT_NE(array.end(), foundIt); |
311 | 1 | ASSERT_EQ(2, *foundIt); |
312 | 1 | } |
313 | | |
314 | | TEST(ArrayViewTest, fixedDynInt16Array) |
315 | 1 | { |
316 | 1 | Vector<Int<9>> rawArray1{-2, 13}; |
317 | 1 | Vector<Int<9>> rawArray2{-2, 42}; |
318 | | |
319 | 1 | ArrayView<const Int<9>> array1(rawArray1); |
320 | 1 | ASSERT_EQ(rawArray1.at(0), array1.at(0)); |
321 | 1 | ASSERT_EQ(rawArray1.at(1), array1.at(1)); |
322 | | |
323 | 1 | ArrayView<const Int<9>> array2(rawArray2); |
324 | 1 | ASSERT_FALSE(array1 == array2); |
325 | 1 | ASSERT_TRUE(array1 != array2); |
326 | 1 | ASSERT_LT(array1, array2); |
327 | | |
328 | 1 | const BitSize bitSize = detail::bitSizeOf<detail::ArrayType::AUTO>(array1); |
329 | 1 | BitBuffer buffer(bitSize); |
330 | 1 | BitStreamWriter writer(buffer); |
331 | 1 | detail::write<detail::ArrayType::AUTO>(writer, array1); |
332 | 1 | ASSERT_EQ(bitSize, writer.getBitPosition()); |
333 | | |
334 | 1 | BitStreamReader reader(buffer); |
335 | 1 | Vector<Int<9>> readRawArray; |
336 | 1 | detail::read<detail::ArrayType::AUTO>(reader, readRawArray, rawArray1.size()); |
337 | 1 | ASSERT_EQ(bitSize, reader.getBitPosition()); |
338 | 1 | ASSERT_EQ(rawArray1, readRawArray); |
339 | 1 | } |
340 | | |
341 | | TEST(ArrayViewTest, variableDynInt16Array) |
342 | 1 | { |
343 | 1 | Vector<DynInt16> rawArray1{-2, 13}; |
344 | 1 | Vector<DynInt16> rawArray2{-2, 42}; |
345 | | |
346 | 1 | VarDynInt16Owner owner; |
347 | | |
348 | 1 | ArrayView<const DynInt16, VarDynInt16ArrayTraits> array1(rawArray1, owner); |
349 | 1 | ASSERT_EQ(rawArray1.at(0), array1.at(0).value()); |
350 | 1 | ASSERT_EQ(rawArray1.at(1), array1.at(1).value()); |
351 | | |
352 | 1 | ArrayView<const DynInt16, VarDynInt16ArrayTraits> array2(rawArray2, owner); |
353 | 1 | ASSERT_FALSE(array1 == array2); |
354 | 1 | ASSERT_TRUE(array1 != array2); |
355 | 1 | ASSERT_LT(array1, array2); |
356 | | |
357 | 1 | const BitSize bitSize = detail::bitSizeOf<detail::ArrayType::AUTO>(array1); |
358 | 1 | BitBuffer buffer(bitSize); |
359 | 1 | BitStreamWriter writer(buffer); |
360 | 1 | detail::write<detail::ArrayType::AUTO>(writer, array1); |
361 | 1 | ASSERT_EQ(bitSize, writer.getBitPosition()); |
362 | | |
363 | 1 | BitStreamReader reader(buffer); |
364 | 1 | Vector<DynInt16> readRawArray; |
365 | 1 | detail::readWithTraits<detail::ArrayType::AUTO, VarDynInt16ArrayTraits>( |
366 | 1 | reader, readRawArray, owner, rawArray1.size()); |
367 | 1 | ASSERT_EQ(bitSize, reader.getBitPosition()); |
368 | 1 | ASSERT_EQ(rawArray1, readRawArray); |
369 | 1 | } |
370 | | |
371 | | TEST(ArrayViewTest, variableDynInt16PackedArray) |
372 | 1 | { |
373 | 1 | Vector<DynInt16> rawArray{-2, 0, 2, 4, 6, 8, 10}; |
374 | | |
375 | 1 | VarDynInt16Owner owner; |
376 | 1 | ArrayView<const DynInt16, VarDynInt16ArrayTraits> array(rawArray, owner); |
377 | | |
378 | | // maxBitNumber == 2 |
379 | | // packingDescriptor 7 + firstElement 10 + 6 * (maxBitNumber 2 + 1) |
380 | 1 | const BitSize packedBitSize = 35; |
381 | 1 | ASSERT_EQ(packedBitSize, detail::bitSizeOfPacked<detail::ArrayType::NORMAL>(array)); |
382 | | |
383 | 1 | BitBuffer buffer(packedBitSize); |
384 | 1 | BitStreamWriter writer(buffer); |
385 | 1 | detail::writePacked<detail::ArrayType::NORMAL>(writer, array); |
386 | 1 | ASSERT_EQ(packedBitSize, writer.getBitPosition()); |
387 | | |
388 | 1 | BitStreamReader reader(buffer); |
389 | 1 | Vector<DynInt16> readRawArray; |
390 | 1 | detail::readPackedWithTraits<detail::ArrayType::NORMAL, VarDynInt16ArrayTraits>( |
391 | 1 | reader, readRawArray, owner, rawArray.size()); |
392 | 1 | ASSERT_EQ(packedBitSize, reader.getBitPosition()); |
393 | 1 | ASSERT_EQ(rawArray, readRawArray); |
394 | 1 | } |
395 | | |
396 | | TEST(ArrayViewTest, varUInt16Array) |
397 | 1 | { |
398 | 1 | Vector<VarUInt16> rawArray1{0, 13}; |
399 | 1 | Vector<VarUInt16> rawArray2{0, 42}; |
400 | | |
401 | 1 | ArrayView<const VarUInt16> array1(rawArray1); |
402 | 1 | ASSERT_EQ(rawArray1.at(0), array1.at(0)); |
403 | 1 | ASSERT_EQ(rawArray1.at(1), array1.at(1)); |
404 | | |
405 | 1 | ArrayView<const VarUInt16> array2(rawArray2); |
406 | 1 | ASSERT_FALSE(array1 == array2); |
407 | 1 | ASSERT_TRUE(array1 != array2); |
408 | 1 | ASSERT_LT(array1, array2); |
409 | | |
410 | 1 | const BitSize bitSize = detail::bitSizeOf<detail::ArrayType::AUTO>(array1); |
411 | 1 | BitBuffer buffer(bitSize); |
412 | 1 | BitStreamWriter writer(buffer); |
413 | 1 | detail::write<detail::ArrayType::AUTO>(writer, array1); |
414 | 1 | ASSERT_EQ(bitSize, writer.getBitPosition()); |
415 | | |
416 | 1 | BitStreamReader reader(buffer); |
417 | 1 | Vector<VarUInt16> readRawArray; |
418 | 1 | detail::read<detail::ArrayType::AUTO>(reader, readRawArray, rawArray1.size()); |
419 | 1 | ASSERT_EQ(bitSize, reader.getBitPosition()); |
420 | 1 | ASSERT_EQ(rawArray1, readRawArray); |
421 | 1 | } |
422 | | |
423 | | TEST(ArrayViewTest, varUInt16PackedArray) |
424 | 1 | { |
425 | 1 | Vector<VarUInt16> rawArray{0, 2, 4, 6, 8, 10, 12}; |
426 | 1 | ArrayView<const VarUInt16> array(rawArray); |
427 | | |
428 | 1 | const BitSize packedBitSize = detail::bitSizeOfPacked<detail::ArrayType::AUTO>(array); |
429 | 1 | BitBuffer buffer(packedBitSize); |
430 | 1 | BitStreamWriter writer(buffer); |
431 | 1 | detail::writePacked<detail::ArrayType::AUTO>(writer, array); |
432 | 1 | ASSERT_EQ(packedBitSize, writer.getBitPosition()); |
433 | | |
434 | 1 | BitStreamReader reader(buffer); |
435 | 1 | Vector<VarUInt16> readRawArray; |
436 | 1 | detail::readPacked<detail::ArrayType::AUTO>(reader, readRawArray, rawArray.size()); |
437 | 1 | ASSERT_EQ(packedBitSize, reader.getBitPosition()); |
438 | 1 | ASSERT_EQ(rawArray, readRawArray); |
439 | 1 | } |
440 | | |
441 | | TEST(ArrayViewTest, float16Array) |
442 | 1 | { |
443 | 1 | Vector<Float16> rawArray1{-9.0F, 0.0F, 10.0F}; |
444 | 1 | Vector<Float16> rawArray2{-9.0F, 0.0F, 10.1F}; |
445 | | |
446 | 1 | ArrayView<const Float16> array1(rawArray1); |
447 | 1 | ArrayView<const Float16> array2(rawArray2); |
448 | | |
449 | 1 | ASSERT_EQ(16, ArrayTraits<Float16>::bitSizeOf()); |
450 | | |
451 | 1 | ASSERT_LT(array1, array2); |
452 | 1 | ASSERT_GT(array2, array1); |
453 | | |
454 | 1 | const BitSize bitSize = detail::bitSizeOf<detail::ArrayType::AUTO>(array1); |
455 | 1 | BitBuffer buffer(bitSize); |
456 | 1 | BitStreamWriter writer(buffer); |
457 | 1 | detail::write<detail::ArrayType::AUTO>(writer, array1); |
458 | 1 | ASSERT_EQ(bitSize, writer.getBitPosition()); |
459 | | |
460 | 1 | BitStreamReader reader(buffer); |
461 | 1 | Vector<Float16> readRawArray; |
462 | 1 | detail::read<detail::ArrayType::AUTO>(reader, readRawArray, rawArray1.size()); |
463 | 1 | ASSERT_EQ(bitSize, reader.getBitPosition()); |
464 | 1 | ASSERT_EQ(rawArray1, readRawArray); |
465 | 1 | } |
466 | | |
467 | | TEST(ArrayViewTest, bytesArray) |
468 | 1 | { |
469 | 1 | Vector<Bytes> rawArray1{{{{1, 255}}, {{127, 128}}}}; |
470 | 1 | Vector<Bytes> rawArray2{{{{1, 255}}, {{127, 129}}}}; |
471 | | |
472 | 1 | ArrayView<const Bytes> array1(rawArray1); |
473 | 1 | ArrayView<const Bytes> array2(rawArray2); |
474 | | |
475 | 1 | ASSERT_TRUE(std::equal( |
476 | 1 | rawArray1.begin(), rawArray1.end(), array1.zserioData().begin(), array1.zserioData().end())); |
477 | | |
478 | 1 | constexpr bool isSpan = std::is_same_v<Span<const uint8_t>, decltype(array1.at(0))>; |
479 | 1 | ASSERT_TRUE(isSpan); |
480 | | |
481 | 1 | ASSERT_TRUE(std::equal( |
482 | 1 | rawArray1.at(0).begin(), rawArray1.at(0).end(), array1.at(0).begin(), array1.at(0).end())); |
483 | 1 | ASSERT_TRUE(std::equal( |
484 | 1 | rawArray1.at(1).begin(), rawArray1.at(1).end(), array1.at(1).begin(), array1.at(1).end())); |
485 | | |
486 | 1 | ASSERT_NE(array1, array2); |
487 | 1 | ASSERT_LT(array1, array2); |
488 | | |
489 | 1 | const BitSize bitSize = detail::bitSizeOf<detail::ArrayType::AUTO>(array1); |
490 | 1 | BitBuffer buffer(bitSize); |
491 | 1 | BitStreamWriter writer(buffer); |
492 | 1 | detail::write<detail::ArrayType::AUTO>(writer, array1); |
493 | 1 | ASSERT_EQ(bitSize, writer.getBitPosition()); |
494 | | |
495 | 1 | BitStreamReader reader(buffer); |
496 | 1 | Vector<Bytes> readRawArray; |
497 | 1 | detail::read<detail::ArrayType::AUTO>(reader, readRawArray, rawArray1.size()); |
498 | 1 | ASSERT_EQ(bitSize, reader.getBitPosition()); |
499 | 1 | ASSERT_EQ(rawArray1, readRawArray); |
500 | 1 | } |
501 | | |
502 | | TEST(ArrayViewTest, stringArray) |
503 | 1 | { |
504 | 1 | Vector<std::string> rawArray1 = {"String0", "String1", "String2"}; |
505 | 1 | Vector<std::string> rawArray2 = {"String0", "String1", "String3"}; |
506 | | |
507 | 1 | ArrayView<const std::string> array1(rawArray1); |
508 | 1 | ArrayView<const std::string> array2(rawArray2); |
509 | | |
510 | 1 | constexpr bool isStringView = std::is_same_v<std::string_view, decltype(array1.at(0))>; |
511 | 1 | ASSERT_TRUE(isStringView); |
512 | | |
513 | 1 | ASSERT_EQ(rawArray1.at(0), array1.at(0)); |
514 | 1 | ASSERT_EQ(rawArray1.at(1), array1.at(1)); |
515 | 1 | ASSERT_EQ(rawArray1.at(2), array1.at(2)); |
516 | | |
517 | 1 | ASSERT_NE(array1, array2); |
518 | 1 | ASSERT_LT(array1, array2); |
519 | | |
520 | 1 | const BitSize bitSize = detail::bitSizeOf<detail::ArrayType::AUTO>(array1); |
521 | 1 | BitBuffer buffer(bitSize); |
522 | 1 | BitStreamWriter writer(buffer); |
523 | 1 | detail::write<detail::ArrayType::AUTO>(writer, array1); |
524 | 1 | ASSERT_EQ(bitSize, writer.getBitPosition()); |
525 | | |
526 | 1 | BitStreamReader reader(buffer); |
527 | 1 | Vector<std::string> readRawArray; |
528 | 1 | detail::read<detail::ArrayType::AUTO>(reader, readRawArray, rawArray1.size()); |
529 | 1 | ASSERT_EQ(bitSize, reader.getBitPosition()); |
530 | 1 | ASSERT_EQ(rawArray1, readRawArray); |
531 | 1 | } |
532 | | |
533 | | TEST(ArrayViewTest, testObjectArray) |
534 | 1 | { |
535 | 1 | Vector<TestObject> rawArray1{TestObject{0}, TestObject{13}}; |
536 | 1 | Vector<TestObject> rawArray2{TestObject{0}, TestObject{42}}; |
537 | | |
538 | 1 | ArrayView<const TestObject> array1(rawArray1); |
539 | 1 | ASSERT_EQ(rawArray1.at(0).field, array1.at(0).field()); |
540 | 1 | ASSERT_EQ(rawArray1.at(1).field, array1.at(1).field()); |
541 | | |
542 | 1 | ArrayView<const TestObject> array2(rawArray2); |
543 | | |
544 | 1 | ASSERT_FALSE(array1 == array2); |
545 | 1 | ASSERT_TRUE(array1 != array2); |
546 | 1 | ASSERT_LT(array1, array2); |
547 | | |
548 | 1 | const BitSize bitSize = detail::bitSizeOf<detail::ArrayType::AUTO>(array1); |
549 | 1 | BitBuffer buffer(bitSize); |
550 | 1 | BitStreamWriter writer(buffer); |
551 | 1 | detail::write<detail::ArrayType::AUTO>(writer, array1); |
552 | 1 | ASSERT_EQ(bitSize, writer.getBitPosition()); |
553 | | |
554 | 1 | BitStreamReader reader(buffer); |
555 | 1 | Vector<TestObject> readRawArray; |
556 | 1 | detail::read<detail::ArrayType::AUTO>(reader, readRawArray); |
557 | 1 | ASSERT_EQ(bitSize, reader.getBitPosition()); |
558 | 1 | ASSERT_EQ(rawArray1, readRawArray); |
559 | | |
560 | 1 | ASSERT_FALSE(array1.empty()); |
561 | 1 | ASSERT_EQ(0, array1.front().field()); |
562 | 1 | ASSERT_EQ(13, array1.back().field()); |
563 | | |
564 | 1 | size_t i = 0; |
565 | 1 | for (auto object : array1) |
566 | 2 | { |
567 | 2 | ASSERT_EQ(i++ == 0 ? 0 : 13, object.field()); |
568 | 2 | } |
569 | | |
570 | 1 | TestObject object{13}; |
571 | 1 | zserio::View view(object); |
572 | 1 | ASSERT_EQ(view, *(array1.begin() + 1)); |
573 | 1 | ASSERT_EQ(0, array1.begin()->field()); |
574 | 1 | ASSERT_EQ(view, array1.begin()[1]); |
575 | 1 | ASSERT_EQ(array1.begin(), array1.end() - 2); |
576 | 1 | ASSERT_EQ(*array1.begin(), *(array1.end() - 2)); |
577 | 1 | ASSERT_EQ(array1.size(), array1.end() - array1.begin()); |
578 | | |
579 | 2 | auto foundIt = std::find_if(array1.begin(), array1.end(), [](const zserio::View<TestObject>& element) 1 { |
580 | 2 | return element.field() != 0; |
581 | 2 | }); |
582 | 1 | ASSERT_NE(array1.end(), foundIt); |
583 | 1 | ASSERT_EQ(array1.at(1), *foundIt); |
584 | | |
585 | 2 | auto notFoundIt = std::find_if(array1.begin(), array1.end(), [](const zserio::View<TestObject>& element) 1 { |
586 | 2 | return element.field() > 13; |
587 | 2 | }); |
588 | 1 | ASSERT_EQ(array1.end(), notFoundIt); |
589 | 1 | } |
590 | | |
591 | | TEST(ArrayViewTest, testObjectPackedArray) |
592 | 1 | { |
593 | 1 | Vector<TestObject> rawArray{TestObject{0}, TestObject{2}, TestObject{4}, TestObject{6}, TestObject{8}}; |
594 | 1 | ArrayView<const TestObject> array(rawArray); |
595 | | |
596 | 1 | static_assert(detail::is_packable_v<TestObject>, "shall be packable"); |
597 | 1 | static_assert(detail::is_packable_v<const TestObject>, "shall be packable"); |
598 | | |
599 | | // maxBitNumber == 2 |
600 | | // packingDescriptor 7 + firstElement 32 + 4 * (maxBitNumber 2 + 1) |
601 | 1 | const BitSize packedBitSize = 51; |
602 | 1 | ASSERT_EQ(packedBitSize, detail::bitSizeOfPacked<detail::ArrayType::NORMAL>(array)); |
603 | | |
604 | 1 | BitBuffer buffer(packedBitSize); |
605 | 1 | BitStreamWriter writer(buffer); |
606 | 1 | detail::writePacked<detail::ArrayType::NORMAL>(writer, array); |
607 | 1 | ASSERT_EQ(packedBitSize, writer.getBitPosition()); |
608 | | |
609 | 1 | BitStreamReader reader(buffer); |
610 | 1 | Vector<TestObject> readRawArray; |
611 | 1 | detail::readPacked<detail::ArrayType::NORMAL>(reader, readRawArray, rawArray.size()); |
612 | 1 | ASSERT_EQ(packedBitSize, reader.getBitPosition()); |
613 | 1 | ASSERT_EQ(rawArray, readRawArray); |
614 | 1 | } |
615 | | |
616 | | } // namespace zserio |