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);
501 assert(u.small() == 0xFE);
502 expectBytes(u, std::array<uint8_t, 2>{0xFE, 0xCA},
"Union big");
505 assert(u.small() == 0xA5);
507 expectBytes(u, std::array<uint8_t, 2>{0xA5, 0xCA},
"Union small");
511 expectBytes(narrow, std::array<uint8_t, 2>{0xA5, 0},
"Union padding");
516 assert(sub.signed_small() == -4);
517 assert(sub.cell().hi() == 7);
518 assert(sub.cell().lo() == 0);
520 assert(sub.big() == 0xABD);
521 sub.signed_small(-7);
522 assert(sub.big() == 0xAB9);
523 sub.cell(SbCell(2, 1));
524 assert(sub.big() == 0xAA9);
525 expectBytes(sub, std::array<uint8_t, 2>{0xA9, 0x0A},
"Sub-byte union");
532void testWindowList() {
533 std::vector<uint32_t> elements = {0xAAAA0001u, 0xBBBB0002u, 0xCCCC0003u};
534 ListWindow win(0xDEAD, elements);
538 assert(win.tag() == 0xDEAD);
539 assert(win.items_count() == elements.size());
542 auto got = win.items_vector();
543 assert(got.size() == elements.size());
544 for (std::size_t i = 0; i < elements.size(); ++i)
545 assert(got[i] == elements[i]);
549 for (uint32_t v : win.items())
550 assert(v == elements[i++]);
553 assert(win.numSegments() == 3);
554 auto header_seg = win.segment(0);
555 auto data_seg = win.segment(1);
556 auto footer_seg = win.segment(2);
557 assert(data_seg.size == elements.size() *
sizeof(uint32_t));
559 assert(header_seg.size == 4);
560 assert(header_seg.data[0] == (
static_cast<uint8_t
>(elements.size()) & 0xFF));
561 assert(header_seg.data[1] == 0);
562 assert(header_seg.data[2] == 0xAD);
563 assert(header_seg.data[3] == 0xDE);
565 assert(footer_seg.size == 4);
566 assert(footer_seg.data[0] == 0);
567 assert(footer_seg.data[1] == 0);
578void testWindowListMultiBurst() {
581 std::vector<uint32_t> elements = {0x11111111u, 0x22222222u, 0x33333333u,
582 0x44444444u, 0x55555555u, 0x66666666u,
584 SmallListWindow win(0xBEEF, elements);
586 assert(win.tag() == 0xBEEF);
587 assert(win.items_count() == elements.size());
590 assert(win.numSegments() == 2 * 3 + 1);
594 assert(win.segment(0).size == 4);
595 assert(win.segment(1).size == 3 *
sizeof(uint32_t));
596 assert(win.segment(2).size == 4);
597 assert(win.segment(3).size == 3 *
sizeof(uint32_t));
598 assert(win.segment(4).size == 4);
599 assert(win.segment(5).size == 1 *
sizeof(uint32_t));
600 assert(win.segment(6).size == 4);
604 auto headerCount = [](
const auto &
s) ->
unsigned {
return s.data[0] & 0x3; };
605 assert(headerCount(win.segment(0)) == 3);
606 assert(headerCount(win.segment(2)) == 3);
607 assert(headerCount(win.segment(4)) == 1);
608 assert(headerCount(win.segment(6)) == 0);
609 assert(win.segment(0).data[0] == 0xBF);
610 assert(win.segment(0).data[1] == 0xFB);
611 assert(win.segment(0).data[2] == 0x02);
612 assert(win.segment(0).data[3] == 0x00);
613 assert(win.segment(2).data[0] == 0x03);
614 assert(win.segment(2).data[1] == 0x00);
615 assert(win.segment(2).data[2] == 0x00);
616 assert(win.segment(2).data[3] == 0x00);
617 assert(win.segment(4).data[0] == 0x01);
619 assert(win.segment(6).data[0] == 0x00);
624 std::unique_ptr<SmallListWindow> decoded;
625 SmallListWindow::TypeDeserializer deser(
626 [&](std::unique_ptr<SmallListWindow> &out) {
627 decoded = std::move(out);
630 std::unique_ptr<esi::SegmentedMessageData> msg =
631 std::make_unique<esi::MessageData>(win.toMessageData());
632 bool pushed = deser.push(msg);
635 assert(decoded->tag() == 0xBEEF);
636 auto reassembled = decoded->items_vector();
637 assert(reassembled.size() == elements.size());
638 for (std::size_t j = 0; j < elements.size(); ++j)
639 assert(reassembled[j] == elements[j]);
642void testWindowNarrowData() {
643 std::vector<uint8_t> elements{0x35, 0x6A};
644 NarrowDataWindow win(0xBEEF, elements);
645 assert(win.tag() == 0xBEEF);
646 assert(win.items_vector() == elements);
650 const std::vector<uint8_t> expected{0xBE, 0xFB, 0x02, 0x35, 0, 0,
651 0x6A, 0, 0, 0, 0, 0};
652 auto message = win.toMessageData();
653 assert(message.getSize() == expected.size());
654 for (std::size_t i = 0; i < expected.size(); ++i)
655 assert(message.getData()[i] == expected[i]);
657 std::unique_ptr<NarrowDataWindow> decoded;
658 NarrowDataWindow::TypeDeserializer deser(
659 [&](std::unique_ptr<NarrowDataWindow> &out) {
660 decoded = std::move(out);
663 std::unique_ptr<esi::SegmentedMessageData> msg =
664 std::make_unique<esi::MessageData>(message);
667 assert(decoded->tag() == 0xBEEF);
668 assert(decoded->items_vector() == elements);
680 std::vector<uint8_t> storage(bytes.begin(), bytes.end());
684 std::size_t need = (width + 7) / 8;
685 if (storage.size() < need)
686 storage.resize(need, 0);
690void testWideUnsigned() {
696 auto u96 = bvFromBytes(
698 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01,
699 0xBE, 0xBA, 0xFE, 0xCA,
702 auto u128 = bvFromBytes(
704 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
705 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
709 s.u96(u96).u128(u128);
712 auto got96 =
s.u96();
713 assert(got96.width() == 96);
714 for (std::size_t i = 0; i < 96; ++i)
715 assert(got96.getBit(i) == u96.getBit(i));
716 auto got128 =
s.u128();
717 assert(got128.width() == 128);
718 for (std::size_t i = 0; i < 128; ++i)
719 assert(got128.getBit(i) == u128.getBit(i));
722 std::array<uint8_t, 28> expected{
724 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
725 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
727 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01,
728 0xBE, 0xBA, 0xFE, 0xCA,
730 expectBytes(s, expected,
"WideU");
733 WideU cons(u96, u128);
734 assert(wireBytes(cons) == wireBytes(s));
737void testWideSigned() {
741 auto s96_zero = bvFromBytes({}, 96);
742 auto s128_neg_one = bvFromBytes(
744 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
745 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
748 s.s96(s96_zero).s128(s128_neg_one);
751 for (std::size_t i = 0; i < 128; ++i)
753 auto got96 =
s.s96();
754 for (std::size_t i = 0; i < 96; ++i)
758 std::array<uint8_t, 28> expected{};
759 for (std::size_t i = 0; i < 16; ++i)
761 expectBytes(s, expected,
"WideS s128=-1, s96=0");
764void testBitsField() {
769 auto wide = bvFromBytes(
771 0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE,
772 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
777 auto got_wide = f.wide();
778 assert(got_wide.width() == 128);
779 for (std::size_t i = 0; i < 128; ++i)
780 assert(got_wide.getBit(i) == wide.getBit(i));
783void testWideMisaligned() {
788 auto payload = bvFromBytes(
790 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
791 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00,
794 m.tag(0b101).payload(payload);
797 auto got = m.payload();
798 assert(got.width() == 128);
799 for (std::size_t i = 0; i < 128; ++i)
800 assert(got.getBit(i) == payload.getBit(i));
804 auto got2 = m.payload();
805 for (std::size_t i = 0; i < 128; ++i)
806 assert(got2.getBit(i) == payload.getBit(i));
812 auto narrow = bvFromBytes({0xAA}, 8);
814 auto got3 = m.payload();
816 for (std::size_t i = 0; i < 8; ++i)
817 assert(got3.getBit(i) == ((0xAA >> i) & 1));
818 for (std::size_t i = 8; i < 128; ++i)
835void testArrayOfViewsAligned() {
837 std::array<esi::MutableBitVector, 3> source;
838 for (std::size_t i = 0; i < 3; ++i) {
839 source[i] = bvFromBytes(
841 static_cast<uint8_t
>(0x10 + i),
842 static_cast<uint8_t
>(0x20 + i),
843 static_cast<uint8_t
>(0x30 + i),
844 static_cast<uint8_t
>(0x40 + i),
845 static_cast<uint8_t
>(0x50 + i),
846 static_cast<uint8_t
>(0x60 + i),
847 static_cast<uint8_t
>(0x70 + i),
848 static_cast<uint8_t
>(0x80 + i),
849 static_cast<uint8_t
>(0x91 + i),
850 static_cast<uint8_t
>(0xA2 + i),
851 static_cast<uint8_t
>(0xB3 + i),
852 static_cast<uint8_t
>(0xC4 + i),
853 static_cast<uint8_t
>(0xD5 + i),
854 static_cast<uint8_t
>(0xE6 + i),
855 static_cast<uint8_t
>(0xF7 + i),
856 static_cast<uint8_t
>(0x08 + i),
859 a.items(i, source[i]);
861 for (std::size_t i = 0; i < 3; ++i) {
862 auto got = a.items(i);
863 assert(got.width() == 128);
864 for (std::size_t b = 0; b < 128; ++b)
865 assert(got.getBit(b) == source[i].getBit(b));
869 auto fresh = bvFromBytes({0xAA}, 128);
871 for (std::size_t b = 0; b < 128; ++b) {
872 assert(a.items(0).getBit(b) == source[0].getBit(b));
873 assert(a.items(2).getBit(b) == source[2].getBit(b));
879 auto range = a.items();
880 assert(std::ranges::size(range) == 3);
882 for (
auto view : range) {
883 assert(view.width() == 128);
884 for (std::size_t b = 0; b < 128; ++b)
885 assert(view.getBit(b) == a.items(i).getBit(b));
893 std::array<esi::UIntView, 3> bulk = {
898 ArrViews ctor_built(bulk);
899 for (std::size_t k = 0; k < 3; ++k) {
900 auto got = ctor_built.items(k);
901 for (std::size_t b = 0; b < 128; ++b)
902 assert(got.getBit(b) == source[k].getBit(b));
906 bulk_set.items(bulk);
907 for (std::size_t k = 0; k < 3; ++k) {
908 auto got = bulk_set.items(k);
909 for (std::size_t b = 0; b < 128; ++b)
910 assert(got.getBit(b) == source[k].getBit(b));
914void testArrayOfViewsMisaligned() {
922 std::array<esi::MutableBitVector, 3> source;
923 for (std::size_t i = 0; i < 3; ++i) {
924 source[i] = bvFromBytes(
926 static_cast<uint8_t
>(0xC0 + i),
927 static_cast<uint8_t
>(0xC1 + i),
928 static_cast<uint8_t
>(0xC2 + i),
929 static_cast<uint8_t
>(0xC3 + i),
930 static_cast<uint8_t
>(0xC4 + i),
931 static_cast<uint8_t
>(0xC5 + i),
932 static_cast<uint8_t
>(0xC6 + i),
933 static_cast<uint8_t
>(0xC7 + i),
934 static_cast<uint8_t
>(0xC8 + i),
935 static_cast<uint8_t
>(0xC9 + i),
936 static_cast<uint8_t
>(0xCA + i),
937 static_cast<uint8_t
>(0xCB + i),
938 static_cast<uint8_t
>(0xCC + i),
939 static_cast<uint8_t
>(0xCD + i),
940 static_cast<uint8_t
>(0xCE + i),
941 static_cast<uint8_t
>(0xCF + i),
944 m.items(i, source[i]);
947 for (std::size_t i = 0; i < 3; ++i) {
948 auto got = m.items(i);
949 assert(got.width() == 128);
950 for (std::size_t b = 0; b < 128; ++b)
951 assert(got.getBit(b) == source[i].getBit(b));
958#if defined(_MSC_VER) && defined(_DEBUG)
959 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
960 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
961 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
962 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
963 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
964 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
965 _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
968 testStandardWidthUnsigned();
969 testStandardWidthSigned();
970 testByteAlignedOddWidthUnsigned();
971 testByteAlignedOddWidthSigned();
972 testSubByteUnsigned();
976 testNestedStructMisaligned();
977 testArrayOfIntegers();
978 testSubByteUnsignedArray();
979 testSubByteBoolArray();
980 testSubByteSignedArray();
982 testSubByteStructArray();
983 testNestedIntArray();
984 testNestedStructArray();
987 testWindowListMultiBurst();
988 testWindowNarrowData();
992 testWideMisaligned();
993 testArrayOfViewsAligned();
994 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...