14#include "codegen_harness/types.h"
32using namespace esi_system;
41std::array<uint8_t,
sizeof(T)> wireBytes(
const T &value) {
42 std::array<uint8_t,
sizeof(T)> out{};
43 const auto *src =
reinterpret_cast<const uint8_t *
>(&value);
44 for (std::size_t i = 0; i <
sizeof(T); ++i)
49template <
typename T, std::
size_t N>
50void expectBytes(
const T &value,
const std::array<uint8_t, N> &expected,
52 static_assert(
sizeof(T) == N,
"wire-byte assertion size mismatch");
53 auto got = wireBytes(value);
54 for (std::size_t i = 0; i < N; ++i) {
55 if (got[i] != expected[i]) {
57 "%s: byte %zu mismatch: got 0x%02x expected 0x%02x\n", label,
58 i, got[i], expected[i]);
59 std::fprintf(stderr,
" got :");
61 std::fprintf(stderr,
" %02x", b);
62 std::fprintf(stderr,
"\n expected:");
63 for (
auto b : expected)
64 std::fprintf(stderr,
" %02x", b);
65 std::fprintf(stderr,
"\n");
75void testStandardWidthUnsigned() {
77 s.u8(0xAB).u16(0xCAFE).u32(0xDEADBEEFu).u64(0x0123456789ABCDEFull);
81 assert(
s.u64() == 0x0123456789ABCDEFull);
87 std::array<uint8_t, 15>{
114 std::array<uint8_t, 15>{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
118 StdU cons(0xAB, 0xCAFE, 0xDEADBEEFu, 0x0123456789ABCDEFull);
119 assert(wireBytes(cons) == wireBytes(s));
122void testStandardWidthSigned() {
124 s.s8(-7).s16(-1000).s32(-1234567).s64(INT64_MIN);
133 StdS pos(127, 32767, 2147483647, INT64_MAX);
135 assert(pos.s64() == INT64_MAX);
142void testByteAlignedOddWidthUnsigned() {
147 expectBytes(s, std::array<uint8_t, 3>{0xEF, 0xCD, 0xAB},
"OddU");
150void testByteAlignedOddWidthSigned() {
154 expectBytes(s, std::array<uint8_t, 3>{0xFF, 0xFF, 0xFF},
"OddS -1");
158 expectBytes(s, std::array<uint8_t, 3>{0x00, 0x00, 0x80},
"OddS min");
162 expectBytes(s, std::array<uint8_t, 3>{0xFF, 0xFF, 0x7F},
"OddS max");
173void testSubByteUnsigned() {
175 s.u3(0b101).u12(0xABC);
184 expectBytes(s, std::array<uint8_t, 2>{0xBC, 0x5A},
"SubU");
187void testSubByteSigned() {
201 expectBytes(s, std::array<uint8_t, 2>{0xCE, 0x0E},
"SubS");
204void testBoolField() {
206 f.flag(
true).pad(0x5A);
211 expectBytes(f, std::array<uint8_t, 1>{0xDA},
"BoolField true");
214 expectBytes(f, std::array<uint8_t, 1>{0x5A},
"BoolField false");
221void testNestedStruct() {
226 o.label(0xAB).inner(in);
227 assert(o.label() == 0xAB);
228 assert(o.inner().x() == 0x12);
229 assert(o.inner().y() == 0x34);
233 expectBytes(o, std::array<uint8_t, 3>{0x34, 0x12, 0xAB},
"Outer");
240 auto copy = o2.inner();
242 assert(o2.inner().x() == 0x12);
244 assert(o2.inner().x() == 0xFF);
247void testNestedStructMisaligned() {
261 m.tag(0b101).inner(mi);
263 assert(m.inner().x() == 0x12);
264 assert(m.inner().y() == 0x34);
267 expectBytes(m, std::array<uint8_t, 3>{0xA5, 0x91, 0x00},
268 "Misaligned all-set");
273 assert(m.inner().x() == 0x12);
274 assert(m.inner().y() == 0x34);
275 expectBytes(m, std::array<uint8_t, 3>{0xA0, 0x91, 0x00},
276 "Misaligned tag cleared");
284 assert(m.inner().x() == 0xFF);
285 assert(m.inner().y() == 0x00);
293 expectBytes(m, std::array<uint8_t, 3>{0x05, 0xF8, 0x07},
294 "Misaligned inner all-ones");
301void testArrayOfIntegers() {
303 a.r({0x10, 0x20, 0x30, 0x40});
305 assert(r[0] == 0x10 && r[1] == 0x20 && r[2] == 0x30 && r[3] == 0x40);
313 expectBytes(a, std::array<uint8_t, 4>{0x10, 0x20, 0x99, 0x40},
"Arr4");
325void testSubByteUnsignedArray() {
329 a.vals({1, 2, 3, 4, 5, 6, 7, 0});
330 const std::array<uint8_t, 8> expected = {1, 2, 3, 4, 5, 6, 7, 0};
331 auto whole = a.vals();
332 for (std::size_t i = 0; i < 8; ++i) {
333 assert(whole[i] == expected[i]);
334 assert(a.vals(i) == expected[i]);
337 expectBytes(a, std::array<uint8_t, 3>{0xD1, 0x58, 0x1F},
"U3Arr packed");
343 for (std::size_t i = 0; i < 8; ++i)
346 expectBytes(b, std::array<uint8_t, 3>{0xC0, 0x01, 0x00},
"U3Arr cross-byte");
349void testSubByteBoolArray() {
354 const std::array<bool, 8> flags = {
true,
true,
false,
false,
355 true,
false,
true,
true};
357 auto whole = a.flags();
358 for (std::size_t i = 0; i < 8; ++i) {
359 assert(whole[i] == flags[i]);
360 assert(a.flags(i) == flags[i]);
362 expectBytes(a, std::array<uint8_t, 1>{0xD3},
"Bits1Arr");
365void testSubByteSignedArray() {
369 const std::array<int8_t, 4> vals = {-1, -16, 15, 0};
371 auto whole = a.vals();
372 for (std::size_t i = 0; i < 4; ++i) {
373 assert(whole[i] == vals[i]);
374 assert(a.vals(i) == vals[i]);
376 expectBytes(a, std::array<uint8_t, 3>{0x1F, 0x3E, 0x00},
"S5Arr");
379void testOddWidthArray() {
384 const std::array<uint32_t, 2> vals = {0xABCDEFu, 0x123456u};
386 auto whole = a.vals();
387 for (std::size_t i = 0; i < 2; ++i) {
388 assert(whole[i] == vals[i]);
389 assert(a.vals(i) == vals[i]);
391 expectBytes(a, std::array<uint8_t, 6>{0xEF, 0xCD, 0xAB, 0x56, 0x34, 0x12},
395void testSubByteStructArray() {
402 std::array<SbCell, 4> cells;
403 cells[0] = SbCell(1, 0);
404 cells[1] = SbCell(2, 1);
405 cells[2] = SbCell(3, 2);
406 cells[3] = SbCell(7, 3);
409 auto whole = a.cells();
410 for (std::size_t i = 0; i < 4; ++i) {
411 assert(whole[i].hi() == cells[i].hi());
412 assert(whole[i].lo() == cells[i].lo());
413 assert(a.cells(i).hi() == cells[i].hi());
414 assert(a.cells(i).lo() == cells[i].lo());
417 expectBytes(a, std::array<uint8_t, 3>{0x24, 0xB9, 0x0F},
"SbCellArr");
422 b.cells(1, SbCell(7, 3));
423 assert(b.cells(1).hi() == 7);
424 assert(b.cells(1).lo() == 3);
425 for (std::size_t i = 0; i < 4; ++i)
427 assert(b.cells(i).hi() == 0);
428 assert(b.cells(i).lo() == 0);
430 expectBytes(b, std::array<uint8_t, 3>{0xE0, 0x03, 0x00},
431 "SbCellArr cross-byte");
439void testNestedIntArray() {
445 std::array<std::array<uint8_t, 4>, 2> rows = {{{1, 2, 3, 4}, {5, 6, 7, 0}}};
448 auto whole = a.rows();
449 for (std::size_t i = 0; i < 2; ++i)
450 for (std::size_t j = 0; j < 4; ++j) {
451 assert(whole[i][j] == rows[i][j]);
452 assert(a.rows(i)[j] == rows[i][j]);
456 expectBytes(a, std::array<uint8_t, 3>{0xD1, 0x58, 0x1F},
"Nested3");
460 b.rows(1, {5, 6, 7, 0});
461 for (std::size_t j = 0; j < 4; ++j) {
462 assert(b.rows(1)[j] == rows[1][j]);
463 assert(b.rows(0)[j] == 0);
466 expectBytes(b, std::array<uint8_t, 3>{0x00, 0x50, 0x1F},
"Nested3 row1");
469void testNestedStructArray() {
474 std::array<std::array<SbCell, 3>, 2> grid = {{
475 {SbCell(1, 0), SbCell(2, 1), SbCell(3, 2)},
476 {SbCell(4, 3), SbCell(5, 0), SbCell(6, 1)},
480 auto whole = a.grid();
481 for (std::size_t i = 0; i < 2; ++i)
482 for (std::size_t j = 0; j < 3; ++j) {
483 assert(whole[i][j].hi() == grid[i][j].hi());
484 assert(whole[i][j].lo() == grid[i][j].lo());
485 assert(a.grid(i)[j].hi() == grid[i][j].hi());
486 assert(a.grid(i)[j].lo() == grid[i][j].lo());
490 expectBytes(a, std::array<uint8_t, 4>{0x24, 0xB9, 0x49, 0x33},
"NestedCell");
500 assert(u.big() == 0xCAFE);
503 assert(u.small() == 0xCA);
504 expectBytes(u, std::array<uint8_t, 2>{0xFE, 0xCA},
"Union big");
507 assert(u.small() == 0xA5);
510 expectBytes(u, std::array<uint8_t, 2>{0xFE, 0xA5},
"Union small");
517void testWindowList() {
518 std::vector<uint32_t> elements = {0xAAAA0001u, 0xBBBB0002u, 0xCCCC0003u};
519 ListWindow win(0xDEAD, elements);
523 assert(win.tag() == 0xDEAD);
524 assert(win.items_count() == elements.size());
527 auto got = win.items_vector();
528 assert(got.size() == elements.size());
529 for (std::size_t i = 0; i < elements.size(); ++i)
530 assert(got[i] == elements[i]);
534 for (uint32_t v : win.items())
535 assert(v == elements[i++]);
538 assert(win.numSegments() == 3);
539 auto header_seg = win.segment(0);
540 auto data_seg = win.segment(1);
541 auto footer_seg = win.segment(2);
542 assert(data_seg.size == elements.size() *
sizeof(uint32_t));
547 assert(header_seg.size == 4);
548 assert(header_seg.data[0] == (
static_cast<uint8_t
>(elements.size()) & 0xFF));
549 assert(header_seg.data[1] == 0);
550 assert(header_seg.data[2] == 0xAD);
551 assert(header_seg.data[3] == 0xDE);
553 assert(footer_seg.size == 4);
554 assert(footer_seg.data[0] == 0);
555 assert(footer_seg.data[1] == 0);
566void testWindowListMultiBurst() {
569 std::vector<uint32_t> elements = {0x11111111u, 0x22222222u, 0x33333333u,
570 0x44444444u, 0x55555555u, 0x66666666u,
572 SmallListWindow win(0xBEEF, elements);
574 assert(win.tag() == 0xBEEF);
575 assert(win.items_count() == elements.size());
578 assert(win.numSegments() == 2 * 3 + 1);
582 assert(win.segment(0).size == 4);
583 assert(win.segment(1).size == 3 *
sizeof(uint32_t));
584 assert(win.segment(2).size == 4);
585 assert(win.segment(3).size == 3 *
sizeof(uint32_t));
586 assert(win.segment(4).size == 4);
587 assert(win.segment(5).size == 1 *
sizeof(uint32_t));
588 assert(win.segment(6).size == 4);
597 auto headerCount = [](
const auto &
s) ->
unsigned {
598 return (
s.data[1] >> 6) & 0x3;
600 assert(headerCount(win.segment(0)) == 3);
601 assert(headerCount(win.segment(2)) == 3);
602 assert(headerCount(win.segment(4)) == 1);
603 assert(headerCount(win.segment(6)) == 0);
607 assert(win.segment(0).data[0] == 0x00);
608 assert(win.segment(0).data[1] == 0xC0);
609 assert(win.segment(0).data[2] == 0xEF);
610 assert(win.segment(0).data[3] == 0xBE);
612 assert(win.segment(2).data[1] == 0xC0);
613 assert(win.segment(2).data[2] == 0x00);
614 assert(win.segment(2).data[3] == 0x00);
615 assert(win.segment(4).data[1] == 0x40);
617 assert(win.segment(6).data[1] == 0x00);
622 std::unique_ptr<SmallListWindow> decoded;
623 SmallListWindow::TypeDeserializer deser(
624 [&](std::unique_ptr<SmallListWindow> &out) {
625 decoded = std::move(out);
628 std::unique_ptr<esi::SegmentedMessageData> msg =
629 std::make_unique<esi::MessageData>(win.toMessageData());
630 bool pushed = deser.push(msg);
633 assert(decoded->tag() == 0xBEEF);
634 auto reassembled = decoded->items_vector();
635 assert(reassembled.size() == elements.size());
636 for (std::size_t j = 0; j < elements.size(); ++j)
637 assert(reassembled[j] == elements[j]);
649 std::vector<uint8_t> storage(bytes.begin(), bytes.end());
653 std::size_t need = (width + 7) / 8;
654 if (storage.size() < need)
655 storage.resize(need, 0);
659void testWideUnsigned() {
665 auto u96 = bvFromBytes(
667 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01,
668 0xBE, 0xBA, 0xFE, 0xCA,
671 auto u128 = bvFromBytes(
673 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
674 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
678 s.u96(u96).u128(u128);
681 auto got96 =
s.u96();
682 assert(got96.width() == 96);
683 for (std::size_t i = 0; i < 96; ++i)
684 assert(got96.getBit(i) == u96.getBit(i));
685 auto got128 =
s.u128();
686 assert(got128.width() == 128);
687 for (std::size_t i = 0; i < 128; ++i)
688 assert(got128.getBit(i) == u128.getBit(i));
691 std::array<uint8_t, 28> expected{
693 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
694 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
696 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01,
697 0xBE, 0xBA, 0xFE, 0xCA,
699 expectBytes(s, expected,
"WideU");
702 WideU cons(u96, u128);
703 assert(wireBytes(cons) == wireBytes(s));
706void testWideSigned() {
710 auto s96_zero = bvFromBytes({}, 96);
711 auto s128_neg_one = bvFromBytes(
713 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
714 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
717 s.s96(s96_zero).s128(s128_neg_one);
720 for (std::size_t i = 0; i < 128; ++i)
722 auto got96 =
s.s96();
723 for (std::size_t i = 0; i < 96; ++i)
727 std::array<uint8_t, 28> expected{};
728 for (std::size_t i = 0; i < 16; ++i)
730 expectBytes(s, expected,
"WideS s128=-1, s96=0");
733void testBitsField() {
738 auto wide = bvFromBytes(
740 0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE,
741 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
746 auto got_wide = f.wide();
747 assert(got_wide.width() == 128);
748 for (std::size_t i = 0; i < 128; ++i)
749 assert(got_wide.getBit(i) == wide.getBit(i));
752void testWideMisaligned() {
757 auto payload = bvFromBytes(
759 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
760 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00,
763 m.tag(0b101).payload(payload);
766 auto got = m.payload();
767 assert(got.width() == 128);
768 for (std::size_t i = 0; i < 128; ++i)
769 assert(got.getBit(i) == payload.getBit(i));
773 auto got2 = m.payload();
774 for (std::size_t i = 0; i < 128; ++i)
775 assert(got2.getBit(i) == payload.getBit(i));
781 auto narrow = bvFromBytes({0xAA}, 8);
783 auto got3 = m.payload();
785 for (std::size_t i = 0; i < 8; ++i)
786 assert(got3.getBit(i) == ((0xAA >> i) & 1));
787 for (std::size_t i = 8; i < 128; ++i)
804void testArrayOfViewsAligned() {
806 std::array<esi::MutableBitVector, 3> source;
807 for (std::size_t i = 0; i < 3; ++i) {
808 source[i] = bvFromBytes(
810 static_cast<uint8_t
>(0x10 + i),
811 static_cast<uint8_t
>(0x20 + i),
812 static_cast<uint8_t
>(0x30 + i),
813 static_cast<uint8_t
>(0x40 + i),
814 static_cast<uint8_t
>(0x50 + i),
815 static_cast<uint8_t
>(0x60 + i),
816 static_cast<uint8_t
>(0x70 + i),
817 static_cast<uint8_t
>(0x80 + i),
818 static_cast<uint8_t
>(0x91 + i),
819 static_cast<uint8_t
>(0xA2 + i),
820 static_cast<uint8_t
>(0xB3 + i),
821 static_cast<uint8_t
>(0xC4 + i),
822 static_cast<uint8_t
>(0xD5 + i),
823 static_cast<uint8_t
>(0xE6 + i),
824 static_cast<uint8_t
>(0xF7 + i),
825 static_cast<uint8_t
>(0x08 + i),
828 a.items(i, source[i]);
830 for (std::size_t i = 0; i < 3; ++i) {
831 auto got = a.items(i);
832 assert(got.width() == 128);
833 for (std::size_t b = 0; b < 128; ++b)
834 assert(got.getBit(b) == source[i].getBit(b));
838 auto fresh = bvFromBytes({0xAA}, 128);
840 for (std::size_t b = 0; b < 128; ++b) {
841 assert(a.items(0).getBit(b) == source[0].getBit(b));
842 assert(a.items(2).getBit(b) == source[2].getBit(b));
848 auto range = a.items();
849 assert(std::ranges::size(range) == 3);
851 for (
auto view : range) {
852 assert(view.width() == 128);
853 for (std::size_t b = 0; b < 128; ++b)
854 assert(view.getBit(b) == a.items(i).getBit(b));
862 std::array<esi::UIntView, 3> bulk = {
867 ArrViews ctor_built(bulk);
868 for (std::size_t k = 0; k < 3; ++k) {
869 auto got = ctor_built.items(k);
870 for (std::size_t b = 0; b < 128; ++b)
871 assert(got.getBit(b) == source[k].getBit(b));
875 bulk_set.items(bulk);
876 for (std::size_t k = 0; k < 3; ++k) {
877 auto got = bulk_set.items(k);
878 for (std::size_t b = 0; b < 128; ++b)
879 assert(got.getBit(b) == source[k].getBit(b));
883void testArrayOfViewsMisaligned() {
891 std::array<esi::MutableBitVector, 3> source;
892 for (std::size_t i = 0; i < 3; ++i) {
893 source[i] = bvFromBytes(
895 static_cast<uint8_t
>(0xC0 + i),
896 static_cast<uint8_t
>(0xC1 + i),
897 static_cast<uint8_t
>(0xC2 + i),
898 static_cast<uint8_t
>(0xC3 + i),
899 static_cast<uint8_t
>(0xC4 + i),
900 static_cast<uint8_t
>(0xC5 + i),
901 static_cast<uint8_t
>(0xC6 + i),
902 static_cast<uint8_t
>(0xC7 + i),
903 static_cast<uint8_t
>(0xC8 + i),
904 static_cast<uint8_t
>(0xC9 + i),
905 static_cast<uint8_t
>(0xCA + i),
906 static_cast<uint8_t
>(0xCB + i),
907 static_cast<uint8_t
>(0xCC + i),
908 static_cast<uint8_t
>(0xCD + i),
909 static_cast<uint8_t
>(0xCE + i),
910 static_cast<uint8_t
>(0xCF + i),
913 m.items(i, source[i]);
916 for (std::size_t i = 0; i < 3; ++i) {
917 auto got = m.items(i);
918 assert(got.width() == 128);
919 for (std::size_t b = 0; b < 128; ++b)
920 assert(got.getBit(b) == source[i].getBit(b));
927#if defined(_MSC_VER) && defined(_DEBUG)
928 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
929 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
930 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
931 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
932 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
933 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
934 _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
937 testStandardWidthUnsigned();
938 testStandardWidthSigned();
939 testByteAlignedOddWidthUnsigned();
940 testByteAlignedOddWidthSigned();
941 testSubByteUnsigned();
945 testNestedStructMisaligned();
946 testArrayOfIntegers();
947 testSubByteUnsignedArray();
948 testSubByteBoolArray();
949 testSubByteSignedArray();
951 testSubByteStructArray();
952 testNestedIntArray();
953 testNestedStructArray();
956 testWindowListMultiBurst();
960 testWideMisaligned();
961 testArrayOfViewsAligned();
962 testArrayOfViewsMisaligned();
assert(baseType &&"element must be base type")
static InstancePath empty
A mutable bit vector that owns its underlying storage.
Non-owning view of an unsigned bit vector with toUI64() and implicit conversions to unsigned scalar t...