CIRCT 23.0.0git
Loading...
Searching...
No Matches
ESIRuntimeTest.cpp
Go to the documentation of this file.
1//===- ESIRuntimeTest.cpp - ESI Runtime Type System Tests ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "esi/Types.h"
10#include "esi/Values.h"
11#include "gtest/gtest.h"
12#include <any>
13#include <cstdint>
14#include <map>
15#include <vector>
16
17using namespace esi;
18
19namespace {
20
21// Test VoidType serialization and deserialization
22TEST(ESITypesTest, VoidTypeSerialization) {
23 VoidType voidType("void");
24
25 // Test valid void value (empty std::any)
26 std::any voidValue;
27 EXPECT_NO_THROW(voidType.ensureValid(voidValue));
28
29 // Test valid void value (nullptr)
30 std::any nullptrValue = std::any(nullptr);
31 EXPECT_NO_THROW(voidType.ensureValid(nullptrValue));
32
33 // Test invalid void value
34 std::any invalidValue = std::any(42);
35 EXPECT_THROW(voidType.ensureValid(invalidValue), std::runtime_error);
36
37 // Test serialization
38 MessageData serialized(voidType.serialize(voidValue).getSpan());
39 EXPECT_EQ(serialized.getSize(), 1UL)
40 << "VoidType serialization should produce exactly 1 byte";
41 EXPECT_EQ(serialized.getData()[0], 0)
42 << "VoidType serialization should produce a zero byte";
43
44 // Test deserialization
45 BitVector v(serialized.getData());
46 auto deserialized = voidType.deserialize(v);
47 EXPECT_FALSE(deserialized.has_value())
48 << "VoidType deserialization should not have a value";
49 EXPECT_EQ(v.width(), 0UL)
50 << "VoidType deserialization should consume all data";
51}
52
53// Test BitsType serialization and deserialization
54TEST(ESITypesTest, BitsTypeSerialization) {
55 BitsType bitsType("bits8", 8);
56
57 // Test valid bits value
58 std::vector<uint8_t> bitsValue = {0xAB};
59 std::any validBits = std::any(bitsValue);
60 EXPECT_NO_THROW(bitsType.ensureValid(validBits));
61
62 // Test invalid size
63 std::vector<uint8_t> wrongSize = {0xAB, 0xCD};
64 std::any invalidBits = std::any(wrongSize);
65 EXPECT_THROW(bitsType.ensureValid(invalidBits), std::runtime_error);
66
67 // Test serialization
68 MessageData serialized(bitsType.serialize(validBits).takeStorage());
69 EXPECT_EQ(serialized.getSize(), 1UL)
70 << "BitsType(8) serialization should produce exactly 1 byte";
71 EXPECT_EQ(serialized.getData()[0], 0xAB)
72 << "BitsType serialization should preserve the input byte value";
73
74 // Test deserialization
75 BitVector serializedBits(serialized.getData());
76 auto deserialized = bitsType.deserialize(serializedBits);
77 auto deserializedBits = std::any_cast<std::vector<uint8_t>>(deserialized);
78 EXPECT_EQ(deserializedBits.size(), 1UL)
79 << "BitsType(8) deserialization should produce 1 byte";
80 EXPECT_EQ(deserializedBits[0], 0xAB)
81 << "BitsType deserialization should preserve the original value";
82 EXPECT_EQ(serializedBits.size(), 0UL)
83 << "BitsType deserialization should consume all data";
84}
85
86// Test UIntType serialization and deserialization
87TEST(ESITypesTest, UIntTypeSerialization) {
88 UIntType uintType("uint16", 16);
89
90 // Test valid uint value
91 uint64_t uintValue = 0x1234;
92 std::any validUInt = std::any(uintValue);
93 EXPECT_NO_THROW(uintType.ensureValid(validUInt));
94
95 // Test out of range value
96 uint64_t outOfRange = 0x10000; // Too big for 16-bit
97 std::any invalidUInt = std::any(outOfRange);
98 EXPECT_THROW(uintType.ensureValid(invalidUInt), std::runtime_error);
99
100 // Test serialization (little-endian)
101 MessageData serialized(uintType.serialize(validUInt).takeStorage());
102 EXPECT_EQ(serialized.getSize(), 2UL)
103 << "UIntType(16) serialization should produce exactly 2 bytes";
104 EXPECT_EQ(serialized.getData()[0], 0x34)
105 << "UIntType serialization low byte should be 0x34 (little-endian)";
106 EXPECT_EQ(serialized.getData()[1], 0x12)
107 << "UIntType serialization high byte should be 0x12 (little-endian)";
108
109 // Test deserialization
110 BitVector serializedBits(serialized.getData());
111 auto deserialized = uintType.deserialize(serializedBits);
112 auto deserializedUInt =
113 static_cast<uint16_t>(std::any_cast<UInt>(deserialized));
114 EXPECT_EQ(deserializedUInt, 0x1234)
115 << "UIntType deserialization should reconstruct original value 0x1234";
116 EXPECT_EQ(serializedBits.size(), 0UL)
117 << "UIntType deserialization should consume all data";
118
119 // Test that different input types work (uint8_t, uint16_t, uint32_t)
120 uint8_t smallVal = 42;
121 uint16_t mediumVal = 1000;
122 uint32_t largeVal = 50000;
123
124 EXPECT_NO_THROW(uintType.ensureValid(std::any(smallVal)));
125 EXPECT_NO_THROW(uintType.ensureValid(std::any(mediumVal)));
126 EXPECT_NO_THROW(uintType.ensureValid(std::any(largeVal)));
127}
128
129// Test SIntType serialization and deserialization
130TEST(ESITypesTest, SIntTypeSerialization) {
131 SIntType sintType("sint16", 16);
132
133 // Test valid positive sint value
134 int64_t positiveValue = 0x1234;
135 std::any validSInt = std::any(positiveValue);
136 EXPECT_NO_THROW(sintType.ensureValid(validSInt));
137
138 // Test valid negative sint value
139 int64_t negativeValue = -1000;
140 std::any validNegSInt = std::any(negativeValue);
141 EXPECT_NO_THROW(sintType.ensureValid(validNegSInt));
142
143 // Test serialization of positive value
144 MessageData serialized(sintType.serialize(validSInt).takeStorage());
145 EXPECT_EQ(serialized.getSize(), 2UL)
146 << "SIntType(16) serialization should produce exactly 2 bytes";
147 EXPECT_EQ(serialized.getData()[0], 0x34)
148 << "SIntType serialization low byte should be 0x34 (little-endian)";
149 EXPECT_EQ(serialized.getData()[1], 0x12)
150 << "SIntType serialization high byte should be 0x12 (little-endian)";
151
152 // Test deserialization
153 BitVector serializedBits(serialized.getData());
154 auto deserialized = sintType.deserialize(serializedBits);
155 auto deserializedSInt =
156 static_cast<int16_t>(std::any_cast<Int>(deserialized));
157 EXPECT_EQ(deserializedSInt, 0x1234)
158 << "SIntType deserialization should reconstruct original positive value";
159 EXPECT_EQ(serializedBits.size(), 0UL)
160 << "SIntType deserialization should consume all data";
161
162 // Test negative value serialization/deserialization
163 MessageData negSerialized(sintType.serialize(validNegSInt).takeStorage());
164 EXPECT_EQ(negSerialized.getSize(), 2UL)
165 << "SIntType(16) negative value should serialize to 2 bytes";
166 // -1000 in 16-bit two's complement: 0xFC18
167 EXPECT_EQ(negSerialized.getData()[0], 0x18)
168 << "SIntType negative serialization low byte should be 0x18 "
169 "(little-endian)";
170 EXPECT_EQ(negSerialized.getData()[1], 0xFC)
171 << "SIntType negative serialization high byte should be 0xFC "
172 "(little-endian)";
173
174 BitVector negSerializedBits(negSerialized.getData());
175 auto negDeserialized = sintType.deserialize(negSerializedBits);
176 auto deserializedNegSInt =
177 static_cast<int16_t>(std::any_cast<Int>(negDeserialized));
178 EXPECT_EQ(deserializedNegSInt, -1000)
179 << "SIntType deserialization should reconstruct original negative value "
180 "(-1000)";
181
182 // Test that different input types work (int8_t, int16_t, int32_t)
183 int8_t smallVal = -42;
184 int16_t mediumVal = -1000;
185 int32_t largeVal = -30000;
186
187 EXPECT_NO_THROW(sintType.ensureValid(std::any(smallVal)));
188 EXPECT_NO_THROW(sintType.ensureValid(std::any(mediumVal)));
189 EXPECT_NO_THROW(sintType.ensureValid(std::any(largeVal)));
190}
191
192// Test SIntType sign extension logic comprehensively
193TEST(ESITypesTest, SIntTypeSignExtension) {
194 // Test 8-bit signed integers
195 SIntType sint8("sint8", 8);
196
197 // Test -1 (all bits set in 8-bit: 0xFF)
198 int64_t minusOne = -1;
199 MessageData serializedMinusOne(
200 sint8.serialize(std::any(minusOne)).takeStorage());
201 EXPECT_EQ(serializedMinusOne.getSize(), 1UL)
202 << "SIntType(8) serialization of -1 should produce 1 byte";
203 EXPECT_EQ(serializedMinusOne.getData()[0], 0xFF)
204 << "SIntType(8) serialization of -1 should be 0xFF (all bits set)";
205
206 BitVector serializedMinusOneBits(serializedMinusOne.getData());
207 auto deserializedMinusOne = sint8.deserialize(serializedMinusOneBits);
208 auto resultMinusOne =
209 static_cast<int8_t>(std::any_cast<Int>(deserializedMinusOne));
210 EXPECT_EQ(resultMinusOne, -1)
211 << "SIntType(8) deserialization of 0xFF should reconstruct -1";
212
213 // Test maximum negative value for 8-bit (-128 = 0x80)
214 int64_t maxNeg8 = -128;
215 MessageData serializedMaxNeg(
216 sint8.serialize(std::any(maxNeg8)).takeStorage());
217 EXPECT_EQ(serializedMaxNeg.getSize(), 1UL)
218 << "SIntType(8) serialization of -128 should produce 1 byte";
219 EXPECT_EQ(serializedMaxNeg.getData()[0], 0x80)
220 << "SIntType(8) serialization of -128 should be 0x80";
221
222 BitVector serializedMaxNegBits(serializedMaxNeg.getData());
223 auto deserializedMaxNeg = sint8.deserialize(serializedMaxNegBits);
224 auto resultMaxNeg =
225 static_cast<int8_t>(std::any_cast<Int>(deserializedMaxNeg));
226 EXPECT_EQ(resultMaxNeg, -128) << "SIntType(8) deserialization should "
227 "reconstruct maximum negative value (-128)";
228
229 // Test maximum positive value for 8-bit (127 = 0x7F)
230 int64_t maxPos8 = 127;
231 MessageData serializedMaxPos(
232 sint8.serialize(std::any(maxPos8)).takeStorage());
233 EXPECT_EQ(serializedMaxPos.getSize(), 1UL)
234 << "SIntType(8) serialization of 127 should produce 1 byte";
235 EXPECT_EQ(serializedMaxPos.getData()[0], 0x7F)
236 << "SIntType(8) serialization of 127 should be 0x7F";
237
238 BitVector serializedMaxPosBits(serializedMaxPos.getData());
239 auto deserializedMaxPos = sint8.deserialize(serializedMaxPosBits);
240 auto resultMaxPos =
241 static_cast<int8_t>(std::any_cast<Int>(deserializedMaxPos));
242 EXPECT_EQ(resultMaxPos, 127) << "SIntType(8) deserialization should "
243 "reconstruct maximum positive value (127)";
244
245 // Test 4-bit signed integers (edge case for smaller widths)
246 SIntType sint4("sint4", 4);
247
248 // Test -1 in 4-bit (0x0F in the lower nibble, should sign extend to all 1s)
249 int64_t minus1w4bit = -1;
250 MessageData serialized4bit(
251 sint4.serialize(std::any(minus1w4bit)).takeStorage());
252 EXPECT_EQ(serialized4bit.getSize(), 1UL)
253 << "SIntType(4) serialization should produce 1 byte";
254 EXPECT_EQ(serialized4bit.getData()[0] & 0x0F, 0x0F)
255 << "SIntType(4) serialization of -1 should have lower 4 bits set to "
256 "1111";
257
258 BitVector serialized4bitBits(serialized4bit.getData());
259 auto deserialized4bit = sint4.deserialize(serialized4bitBits);
260 auto result4bit = static_cast<int8_t>(std::any_cast<Int>(deserialized4bit));
261 EXPECT_EQ(result4bit, -1)
262 << "SIntType(4) deserialization should sign-extend -1 correctly";
263
264 // Test maximum negative for 4-bit (-8 = 0x8 in 4 bits)
265 int64_t maxNeg4 = -8;
266 MessageData serializedMaxNeg4(
267 sint4.serialize(std::any(maxNeg4)).takeStorage());
268 BitVector serializedMaxNeg4Bits(serializedMaxNeg4.getData());
269 auto deserializedMaxNeg4 = sint4.deserialize(serializedMaxNeg4Bits);
270 auto resultMaxNeg4 =
271 static_cast<int8_t>(std::any_cast<Int>(deserializedMaxNeg4));
272 EXPECT_EQ(resultMaxNeg4, -8)
273 << "SIntType(4) should handle maximum negative value (-8) correctly";
274
275 // Test maximum positive for 4-bit (7 = 0x7 in 4 bits)
276 int64_t maxPos4 = 7;
277 MessageData serializedMaxPos4(
278 sint4.serialize(std::any(maxPos4)).takeStorage());
279 BitVector serializedMaxPos4Bits(serializedMaxPos4.getData());
280 auto deserializedMaxPos4 = sint4.deserialize(serializedMaxPos4Bits);
281 auto resultMaxPos4 =
282 static_cast<int8_t>(std::any_cast<Int>(deserializedMaxPos4));
283 EXPECT_EQ(resultMaxPos4, 7)
284 << "SIntType(4) should handle maximum positive value (7) correctly";
285
286 // Test 12-bit signed integers (non-byte-aligned case)
287 SIntType sint12("sint12", 12);
288
289 // Test -1 in 12-bit (should be 0xFFF in lower 12 bits)
290 int64_t minus1w12bit = -1;
291 MessageData serialized12bit(
292 sint12.serialize(std::any(minus1w12bit)).takeStorage());
293 EXPECT_EQ(serialized12bit.getSize(), 2UL)
294 << "SIntType(12) serialization should produce 2 bytes (12 bits = 2 "
295 "bytes)";
296 EXPECT_EQ(serialized12bit.getData()[0], 0xFF)
297 << "SIntType(12) serialization of -1 should have lower byte 0xFF";
298 EXPECT_EQ(serialized12bit.getData()[1] & 0x0F, 0x0F)
299 << "SIntType(12) serialization of -1 should have upper nibble 0x0F";
300
301 BitVector serialized12bitBits(serialized12bit.getData());
302 auto deserialized12bit = sint12.deserialize(serialized12bitBits);
303 auto result12bit =
304 static_cast<int16_t>(std::any_cast<Int>(deserialized12bit));
305 EXPECT_EQ(result12bit, -1)
306 << "SIntType(12) deserialization should sign-extend -1 correctly";
307
308 // Test a value that requires sign extension: -100 in 12-bit
309 int64_t neg100w12bit = -100;
310 MessageData serializedNeg100(
311 sint12.serialize(std::any(neg100w12bit)).takeStorage());
312 BitVector serializedNeg100Bits(serializedNeg100.getData());
313 auto deserializedNeg100 = sint12.deserialize(serializedNeg100Bits);
314 auto resultNeg100 =
315 static_cast<int16_t>(std::any_cast<Int>(deserializedNeg100));
316 EXPECT_EQ(resultNeg100, -100)
317 << "SIntType(12) should correctly handle sign extension for -100";
318}
319
320// Test boundary conditions for sign extension
321TEST(ESITypesTest, SIntTypeSignExtensionBoundaries) {
322 // Test various bit widths to ensure sign extension works correctly
323 for (int width = 1; width <= 16; ++width) {
324 SIntType sintType("sint" + std::to_string(width), width);
325
326 // Calculate the range for this bit width
327 int64_t maxVal = (width == 64) ? INT64_MAX : ((1LL << (width - 1)) - 1);
328 int64_t minVal = (width == 64) ? INT64_MIN : (-(1LL << (width - 1)));
329
330 // Test maximum positive value
331 MessageData serializedMax(
332 sintType.serialize(std::any(maxVal)).takeStorage());
333 BitVector serializedMaxBits(serializedMax.getData());
334 auto deserializedMax = sintType.deserialize(serializedMaxBits);
335
336 // Cast to appropriate type based on width
337 if (width <= 8) {
338 auto resultMax = static_cast<int8_t>(std::any_cast<Int>(deserializedMax));
339 EXPECT_EQ(resultMax, static_cast<int8_t>(maxVal))
340 << "Failed for width " << width << " max value";
341 } else if (width <= 16) {
342 auto resultMax =
343 static_cast<int16_t>(std::any_cast<Int>(deserializedMax));
344 EXPECT_EQ(resultMax, static_cast<int16_t>(maxVal))
345 << "Failed for width " << width << " max value";
346 } else if (width <= 32) {
347 auto resultMax =
348 static_cast<int32_t>(std::any_cast<Int>(deserializedMax));
349 EXPECT_EQ(resultMax, static_cast<int32_t>(maxVal))
350 << "Failed for width " << width << " max value";
351 } else {
352 auto resultMax =
353 static_cast<int64_t>(std::any_cast<Int>(deserializedMax));
354 EXPECT_EQ(resultMax, maxVal)
355 << "Failed for width " << width << " max value";
356 }
357
358 // Test maximum negative value
359 MessageData serializedMin(
360 sintType.serialize(std::any(minVal)).takeStorage());
361 BitVector serializedMinBits(serializedMin.getData());
362 auto deserializedMin = sintType.deserialize(serializedMinBits);
363
364 if (width <= 8) {
365 auto resultMin = static_cast<int8_t>(std::any_cast<Int>(deserializedMin));
366 EXPECT_EQ(resultMin, static_cast<int8_t>(minVal))
367 << "Failed for width " << width << " min value";
368 } else if (width <= 16) {
369 auto resultMin =
370 static_cast<int16_t>(std::any_cast<Int>(deserializedMin));
371 EXPECT_EQ(resultMin, static_cast<int16_t>(minVal))
372 << "Failed for width " << width << " min value";
373 } else if (width <= 32) {
374 auto resultMin =
375 static_cast<int32_t>(std::any_cast<Int>(deserializedMin));
376 EXPECT_EQ(resultMin, static_cast<int32_t>(minVal))
377 << "Failed for width " << width << " min value";
378 } else {
379 auto resultMin =
380 static_cast<int64_t>(std::any_cast<Int>(deserializedMin));
381 EXPECT_EQ(resultMin, minVal)
382 << "Failed for width " << width << " min value";
383 }
384
385 // Test -1 (all bits set case)
386 MessageData serializedMinusOne(
387 sintType.serialize(std::any(static_cast<int64_t>(-1))).takeStorage());
388 BitVector serializedMinusOneBits(serializedMinusOne.getData());
389 auto deserializedMinusOne = sintType.deserialize(serializedMinusOneBits);
390
391 if (width <= 8) {
392 auto resultMinusOne =
393 static_cast<int8_t>(std::any_cast<Int>(deserializedMinusOne));
394 EXPECT_EQ(resultMinusOne, -1)
395 << "Failed for width " << width << " value -1";
396 } else if (width <= 16) {
397 auto resultMinusOne =
398 static_cast<int16_t>(std::any_cast<Int>(deserializedMinusOne));
399 EXPECT_EQ(resultMinusOne, -1)
400 << "Failed for width " << width << " value -1";
401 } else if (width <= 32) {
402 auto resultMinusOne =
403 static_cast<int32_t>(std::any_cast<Int>(deserializedMinusOne));
404 EXPECT_EQ(resultMinusOne, -1)
405 << "Failed for width " << width << " value -1";
406 } else {
407 auto resultMinusOne =
408 static_cast<int64_t>(std::any_cast<Int>(deserializedMinusOne));
409 EXPECT_EQ(resultMinusOne, -1)
410 << "Failed for width " << width << " value -1";
411 }
412 }
413}
414
415// Test wide UIntType serialization and deserialization (>64 bits)
416TEST(ESITypesTest, WideUIntTypeSerialization) {
417 // Test 128-bit unsigned integer
418 UIntType uint128("uint128", 128);
419
420 // Test a specific 128-bit value: 0x123456789ABCDEF0FEDCBA9876543210
421 // This will be represented as a BitVector and serialized/deserialized
422 uint64_t lowPart = 0xFEDCBA9876543210ULL;
423 uint64_t highPart = 0x123456789ABCDEF0ULL;
424
425 // Construct the 128-bit value by creating bytes in little-endian order
426 std::vector<uint8_t> bytes(16, 0);
427 for (size_t i = 0; i < 8; ++i) {
428 bytes[i] = static_cast<uint8_t>((lowPart >> (8 * i)) & 0xFF);
429 bytes[i + 8] = static_cast<uint8_t>((highPart >> (8 * i)) & 0xFF);
430 }
431
432 // Create a UInt from the bytes.
433 std::any uint128Value = std::any(UInt(std::move(bytes)));
434
435 // Test validation
436 EXPECT_NO_THROW(uint128.ensureValid(uint128Value));
437
438 // Test serialization
439 MessageData serialized(uint128.serialize(uint128Value).takeStorage());
440 EXPECT_EQ(serialized.getSize(), 16UL)
441 << "UIntType(128) serialization should produce exactly 16 bytes";
442
443 // Verify byte values in little-endian order
444 for (size_t i = 0; i < 8; ++i) {
445 EXPECT_EQ(serialized.getData()[i],
446 static_cast<uint8_t>((lowPart >> (8 * i)) & 0xFF))
447 << "Low part byte " << i << " mismatch";
448 EXPECT_EQ(serialized.getData()[i + 8],
449 static_cast<uint8_t>((highPart >> (8 * i)) & 0xFF))
450 << "High part byte " << i << " mismatch";
451 }
452
453 // Test deserialization
454 BitVector serializedBits(serialized.getData());
455 auto deserialized = uint128.deserialize(serializedBits);
456 auto deserializedUInt = std::any_cast<UInt>(deserialized);
457 EXPECT_EQ(deserializedUInt.width(), 128u)
458 << "Deserialized UInt(128) should have width 128";
459 EXPECT_EQ(serializedBits.size(), 0UL)
460 << "UIntType(128) deserialization should consume all data";
461
462 // Test 80-bit value (non-power-of-2)
463 UIntType uint80("uint80", 80);
464 std::vector<uint8_t> bytes80(10, 0);
465 uint64_t val80 = 0x123456789ABCDEFULL;
466 for (size_t i = 0; i < 10; ++i) {
467 bytes80[i] = static_cast<uint8_t>((val80 >> (8 * i)) & 0xFF);
468 }
469
470 std::any uint80Value = std::any(UInt(std::move(bytes80), 80));
471
472 EXPECT_NO_THROW(uint80.ensureValid(uint80Value));
473
474 MessageData serialized80(uint80.serialize(uint80Value).takeStorage());
475 EXPECT_EQ(serialized80.getSize(), 10UL)
476 << "UIntType(80) serialization should produce exactly 10 bytes";
477
478 BitVector serialized80Bits(serialized80.getData());
479 auto deserialized80 = uint80.deserialize(serialized80Bits);
480 auto deserializedUInt80 = std::any_cast<UInt>(deserialized80);
481 EXPECT_EQ(deserializedUInt80.width(), 80u)
482 << "Deserialized UInt(80) should have width 80";
483 EXPECT_EQ(serialized80Bits.size(), 0UL)
484 << "UIntType(80) deserialization should consume all data";
485}
486
487// Test wide SIntType serialization and deserialization (>64 bits)
488TEST(ESITypesTest, WideSIntTypeSerialization) {
489 // Test 128-bit signed integer with positive value
490 SIntType sint128("sint128", 128);
491
492 // Create a positive 128-bit value: 0x123456789ABCDEF0 (upper bits 0)
493 std::vector<uint8_t> bytes(16, 0);
494 uint64_t val = 0x123456789ABCDEF0ULL;
495 for (size_t i = 0; i < 8; ++i) {
496 bytes[i] = static_cast<uint8_t>((val >> (8 * i)) & 0xFF);
497 }
498
499 std::any sint128Value = std::any(Int(std::move(bytes), 128));
500
501 // Test validation
502 EXPECT_NO_THROW(sint128.ensureValid(sint128Value));
503
504 // Test serialization
505 MessageData serialized(sint128.serialize(sint128Value).takeStorage());
506 EXPECT_EQ(serialized.getSize(), 16UL)
507 << "SIntType(128) serialization should produce exactly 16 bytes";
508
509 // Test deserialization
510 BitVector serializedBits(serialized.getData());
511 auto deserialized = sint128.deserialize(serializedBits);
512 auto deserializedSInt = std::any_cast<Int>(deserialized);
513 EXPECT_EQ(deserializedSInt.width(), 128u)
514 << "Deserialized SInt(128) should have width 128";
515 EXPECT_EQ(serializedBits.size(), 0UL)
516 << "SIntType(128) deserialization should consume all data";
517
518 // Test 128-bit signed integer with negative value: -1 (all bits set)
519 std::vector<uint8_t> bytesNegOne(16, 0xFF);
520 std::any sint128NegOne = std::any(Int(std::move(bytesNegOne), 128));
521
522 EXPECT_NO_THROW(sint128.ensureValid(sint128NegOne));
523
524 MessageData serializedNegOne(sint128.serialize(sint128NegOne).takeStorage());
525 EXPECT_EQ(serializedNegOne.getSize(), 16UL)
526 << "SIntType(128) serialization of -1 should produce 16 bytes";
527
528 // Verify all bytes are 0xFF
529 for (size_t i = 0; i < 16; ++i) {
530 EXPECT_EQ(serializedNegOne.getData()[i], 0xFF)
531 << "All bytes in -1 should be 0xFF";
532 }
533
534 // Test deserialization of -1
535 BitVector serializedNegOneBits(serializedNegOne.getData());
536 auto deserializedNegOne = sint128.deserialize(serializedNegOneBits);
537 auto deserializedSIntNegOne = std::any_cast<Int>(deserializedNegOne);
538 EXPECT_EQ(deserializedSIntNegOne.width(), 128u)
539 << "Deserialized SInt(128) of -1 should have width 128";
540
541 // Test 192-bit signed integer (3 bytes x 8 bits = 24 bytes x 8 bits)
542 SIntType sint192("sint192", 192);
543 std::vector<uint8_t> bytes192(24, 0);
544 // Set a pattern in the lower 16 bytes
545 uint64_t val192Low = 0xDEADBEEFCAFEBABEULL;
546 uint64_t val192Mid = 0x0123456789ABCDEFULL;
547 for (size_t i = 0; i < 8; ++i) {
548 bytes192[i] = static_cast<uint8_t>((val192Low >> (8 * i)) & 0xFF);
549 bytes192[i + 8] = static_cast<uint8_t>((val192Mid >> (8 * i)) & 0xFF);
550 }
551
552 std::any sint192Value = std::any(Int(std::move(bytes192), 192));
553
554 EXPECT_NO_THROW(sint192.ensureValid(sint192Value));
555
556 MessageData serialized192(sint192.serialize(sint192Value).takeStorage());
557 EXPECT_EQ(serialized192.getSize(), 24UL)
558 << "SIntType(192) serialization should produce exactly 24 bytes";
559
560 BitVector serialized192Bits(serialized192.getData());
561 auto deserialized192 = sint192.deserialize(serialized192Bits);
562 auto deserializedSInt192 = std::any_cast<Int>(deserialized192);
563 EXPECT_EQ(deserializedSInt192.width(), 192u)
564 << "Deserialized SInt(192) should have width 192";
565 EXPECT_EQ(serialized192Bits.size(), 0UL)
566 << "SIntType(192) deserialization should consume all data";
567
568 // Test 72-bit signed integer (non-byte-aligned, non-power-of-2)
569 SIntType sint72("sint72", 72);
570 std::vector<uint8_t> bytes72(9, 0);
571 uint64_t val72 = 0x0123456789ABCDEFULL;
572 for (size_t i = 0; i < 8; ++i) {
573 bytes72[i] = static_cast<uint8_t>((val72 >> (8 * i)) & 0xFF);
574 }
575 bytes72[8] = 0x01; // High byte with bit 72 representing sign bit position
576
577 std::any sint72Value = std::any(Int(std::move(bytes72), 72));
578
579 EXPECT_NO_THROW(sint72.ensureValid(sint72Value));
580
581 MessageData serialized72(sint72.serialize(sint72Value).takeStorage());
582 EXPECT_EQ(serialized72.getSize(), 9UL)
583 << "SIntType(72) serialization should produce exactly 9 bytes";
584
585 BitVector serialized72Bits(serialized72.getData());
586 auto deserialized72 = sint72.deserialize(serialized72Bits);
587 auto deserializedSInt72 = std::any_cast<Int>(deserialized72);
588 EXPECT_EQ(deserializedSInt72.width(), 72u)
589 << "Deserialized SInt(72) should have width 72";
590 EXPECT_EQ(serialized72Bits.size(), 0UL)
591 << "SIntType(72) deserialization should consume all data";
592}
593
594// Test StructType serialization and deserialization
595TEST(ESITypesTest, StructTypeSerialization) {
596 // Create field types
597 auto uintType = std::make_unique<UIntType>("uint8", 8);
598 auto sintType = std::make_unique<SIntType>("sint8", 8);
599
600 // Create struct type with fields
601 StructType::FieldVector fields = {{"field1", uintType.get()},
602 {"field2", sintType.get()}};
603 StructType structType("testStruct", fields);
604
605 // Test valid struct value
606 std::map<std::string, std::any> structValue = {
607 {"field1", std::any(static_cast<uint64_t>(42))},
608 {"field2", std::any(static_cast<int64_t>(-10))}};
609 std::any validStruct = std::any(structValue);
610 EXPECT_NO_THROW(structType.ensureValid(validStruct));
611
612 // Test missing field
613 std::map<std::string, std::any> incompleteStruct = {
614 {"field1", std::any(static_cast<uint64_t>(42))}};
615 std::any invalidStruct = std::any(incompleteStruct);
616 EXPECT_THROW(structType.ensureValid(invalidStruct), std::runtime_error);
617
618 // Test field not in type.
619 std::map<std::string, std::any> incompatibleStruct = {
620 {"UnknownField", std::any(static_cast<uint64_t>(0xdeadbeef))}};
621 std::any incompatibleStructAny = std::any(incompatibleStruct);
622 EXPECT_THROW(structType.ensureValid(incompatibleStructAny),
623 std::runtime_error);
624
625 // Test serialization
626 MessageData serialized(structType.serialize(validStruct).takeStorage());
627 EXPECT_EQ(serialized.getSize(), 2UL)
628 << "StructType with uint8 + sint8 fields should serialize to 2 bytes";
629
630 // Test deserialization
631 BitVector serializedBits(serialized.getData());
632 auto deserialized = structType.deserialize(serializedBits);
633 auto deserializedStruct =
634 std::any_cast<std::map<std::string, std::any>>(deserialized);
635 EXPECT_EQ(deserializedStruct.size(), 2UL)
636 << "Deserialized struct should contain exactly 2 fields";
637 EXPECT_TRUE(deserializedStruct.find("field1") != deserializedStruct.end())
638 << "Deserialized struct should contain field1";
639 EXPECT_TRUE(deserializedStruct.find("field2") != deserializedStruct.end())
640 << "Deserialized struct should contain field2";
641 EXPECT_EQ(serializedBits.size(), 0UL)
642 << "StructType deserialization should consume all data";
643
644 // Verify field values
645 auto field1Val =
646 static_cast<uint8_t>(std::any_cast<UInt>(deserializedStruct["field1"]));
647 auto field2Val =
648 static_cast<int8_t>(std::any_cast<Int>(deserializedStruct["field2"]));
649 EXPECT_EQ(field1Val, 42) << "Deserialized field1 should have value 42";
650 EXPECT_EQ(field2Val, -10) << "Deserialized field2 should have value -10";
651
652 // Test struct with non-byte aligned field. Should succeed.
653 auto oddUintType = std::make_unique<UIntType>("uint6", 6);
654 auto boolType = std::make_unique<BitsType>("bool", 1);
655 StructType::FieldVector oddFields = {{"field1", uintType.get()},
656 {"bool1", boolType.get()},
657 {"field2", oddUintType.get()},
658 {"bool2", boolType.get()}};
659 StructType oddStruct("oddStruct", oddFields);
660
661 std::map<std::string, std::any> oddStructValue = {
662 {"field1", std::any(static_cast<uint64_t>(1))},
663 {"bool1", std::any(std::vector<uint8_t>{1})},
664 {"field2", std::any(static_cast<uint64_t>(2))},
665 {"bool2", std::any(std::vector<uint8_t>{0})},
666 };
667
668 std::any validOddStruct = std::any(oddStructValue);
669 EXPECT_NO_THROW(oddStruct.ensureValid(validOddStruct));
670 MessageData oddSerialized(oddStruct.serialize(validOddStruct).takeStorage());
671 // Expect 2 bytes (round up from 14 bits)
672 EXPECT_EQ(oddSerialized.size(), 2UL);
673
674 BitVector oddSerializedBits(oddSerialized.getData());
675 auto oddDeserialized = oddStruct.deserialize(oddSerializedBits);
676 auto deserializedOddStruct =
677 std::any_cast<std::map<std::string, std::any>>(oddDeserialized);
678 EXPECT_EQ(deserializedOddStruct.size(), 4UL)
679 << "Deserialized odd struct should contain exactly 4 fields";
680 EXPECT_EQ(oddSerializedBits.size(), 0UL)
681 << "Odd StructType deserialization should consume all data";
682 // Verify field values
683 auto oddField1Val = static_cast<uint8_t>(
684 std::any_cast<UInt>(deserializedOddStruct["field1"]));
685 auto bool1Val =
686 std::any_cast<std::vector<uint8_t>>(deserializedOddStruct["bool1"]);
687 auto oddField2Val = static_cast<uint8_t>(
688 std::any_cast<UInt>(deserializedOddStruct["field2"]));
689 auto bool2Val =
690 std::any_cast<std::vector<uint8_t>>(deserializedOddStruct["bool2"]);
691
692 EXPECT_EQ(oddField1Val, 1) << "Deserialized odd field1 should have value 1";
693 EXPECT_EQ(bool1Val.size(), 1ULL)
694 << "Deserialized odd bool1 should have size 1";
695 EXPECT_EQ(bool1Val[0], 1) << "Deserialized odd bool1 should have value true";
696 EXPECT_EQ(oddField2Val, 2) << "Deserialized odd field2 should have value 2";
697 EXPECT_EQ(bool2Val.size(), 1ULL)
698 << "Deserialized odd bool2 should have size 1";
699 EXPECT_EQ(bool2Val[0], 0) << "Deserialized odd bool2 should have value false";
700}
701
702// Test ArrayType serialization and deserialization
703TEST(ESITypesTest, ArrayTypeSerialization) {
704 // Create element type
705 auto uintType = std::make_unique<UIntType>("uint8", 8);
706
707 // Create array type
708 ArrayType arrayType("uint8Array", uintType.get(), 3);
709
710 // Test valid array value
711 std::vector<std::any> arrayValue = {std::any(static_cast<uint64_t>(10)),
712 std::any(static_cast<uint64_t>(20)),
713 std::any(static_cast<uint64_t>(30))};
714 std::any validArray = std::any(arrayValue);
715 EXPECT_NO_THROW(arrayType.ensureValid(validArray));
716
717 // Test wrong size array
718 std::vector<std::any> wrongSizeArray = {std::any(static_cast<uint64_t>(10)),
719 std::any(static_cast<uint64_t>(20))};
720 std::any invalidArray = std::any(wrongSizeArray);
721 EXPECT_THROW(arrayType.ensureValid(invalidArray), std::runtime_error);
722
723 // Test serialization
724 MessageData serialized(arrayType.serialize(validArray).takeStorage());
725 EXPECT_EQ(serialized.getSize(), 3UL)
726 << "ArrayType of 3 uint8 elements should serialize to 3 bytes";
727 EXPECT_EQ(serialized.getData()[0], 30)
728 << "First array element should serialize to 30 but got "
729 << static_cast<uint32_t>(serialized.getData()[0]);
730 EXPECT_EQ(serialized.getData()[1], 20)
731 << "Second array element should serialize to 20 but got "
732 << static_cast<uint32_t>(serialized.getData()[1]);
733 EXPECT_EQ(serialized.getData()[2], 10)
734 << "Third array element should serialize to 10 but got "
735 << static_cast<uint32_t>(serialized.getData()[2]);
736
737 // Test deserialization
738 BitVector serializedBits(serialized.getData());
739 auto deserialized = arrayType.deserialize(serializedBits);
740 auto deserializedArray = std::any_cast<std::vector<std::any>>(deserialized);
741 EXPECT_EQ(deserializedArray.size(), 3UL)
742 << "Deserialized array should contain exactly 3 elements";
743 EXPECT_EQ(serializedBits.size(), 0UL)
744 << "ArrayType deserialization should consume all data";
745
746 // Verify element values
747 auto elem0 = static_cast<uint8_t>(std::any_cast<UInt>(deserializedArray[0]));
748 auto elem1 = static_cast<uint8_t>(std::any_cast<UInt>(deserializedArray[1]));
749 auto elem2 = static_cast<uint8_t>(std::any_cast<UInt>(deserializedArray[2]));
750 EXPECT_EQ(elem0, 10) << "First array element should have value 10";
751 EXPECT_EQ(elem1, 20) << "Second array element should have value 20";
752 EXPECT_EQ(elem2, 30) << "Third array element should have value 30";
753}
754
755// Test bit width calculations
756TEST(ESITypesTest, BitWidthCalculations) {
757 VoidType voidType("void");
758 EXPECT_EQ(voidType.getBitWidth(), 1) << "VoidType should have bit width of 1";
759
760 BitsType bitsType("bits16", 16);
761 EXPECT_EQ(bitsType.getBitWidth(), 16)
762 << "BitsType(16) should have bit width of 16";
763
764 UIntType uintType("uint32", 32);
765 EXPECT_EQ(uintType.getBitWidth(), 32)
766 << "UIntType(32) should have bit width of 32";
767
768 SIntType sintType("sint64", 64);
769 EXPECT_EQ(sintType.getBitWidth(), 64)
770 << "SIntType(64) should have bit width of 64";
771
772 // Test struct bit width
773 auto uintType8 = std::make_unique<UIntType>("uint8", 8);
774 auto sintType16 = std::make_unique<SIntType>("sint16", 16);
775 StructType::FieldVector fields = {{"field1", uintType8.get()},
776 {"field2", sintType16.get()}};
777 StructType structType("testStruct", fields);
778 EXPECT_EQ(structType.getBitWidth(), 24)
779 << "StructType with uint8 + sint16 should have bit width of 24 (8 + "
780 "16)";
781
782 // Test array bit width
783 ArrayType arrayType("uint8Array", uintType8.get(), 5);
784 EXPECT_EQ(arrayType.getBitWidth(), 40)
785 << "ArrayType of 5 uint8 elements should have bit width of 40 (8 * 5)";
786}
787} // namespace
Arrays have a compile time specified (static) size and an element type.
Definition Types.h:276
A lightweight, non-owning bit vector view backed by a byte array span.
Definition Values.h:42
Bits are just an array of bits.
Definition Types.h:199
A logical chunk of data representing serialized data.
Definition Common.h:113
Signed integer.
Definition Types.h:217
Structs are an ordered collection of fields, each with a name and a type.
Definition Types.h:239
std::vector< std::pair< std::string, const Type * > > FieldVector
Definition Types.h:241
Unsigned integer.
Definition Types.h:228
The "void" type is a special type which can be used to represent no type.
Definition Types.h:136
Definition esi.py:1