From df6060a9e9de53be63cf395d0e137d5b236bab87 Mon Sep 17 00:00:00 2001 From: Raphael Maenle Date: Tue, 9 Jun 2026 01:04:36 +0200 Subject: [PATCH] test: round-trip S6F8 + S12F14/F16/F18 reply shapes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes the test gap for messages I added but whose reply parsers were only generated, never exercised: * S6F8 — full nested DATAID/CEID/DS/DV structure. * S12F14 — row-format map reply (RSINF tuples). * S12F16 — array-format map reply. * S12F18 — coordinate-format map reply. Suite: 295 cases / 1545 assertions. Co-Authored-By: Claude Opus 4.7 --- tests/test_messages.cpp | 69 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/tests/test_messages.cpp b/tests/test_messages.cpp index d8a39f7..4a277fe 100644 --- a/tests/test_messages.cpp +++ b/tests/test_messages.cpp @@ -526,6 +526,32 @@ TEST_CASE("S6F7 round-trip carries DATAID") { CHECK(*parsed == 7); } +TEST_CASE("S6F8 data transfer send carries nested DS/DV structure") { + // [DATAID, CEID, [[DSID, [[DVNAME, DVVAL], ...]], ...]] + DataTransferSend src; + src.dataid = 7; + src.ceid = 300; + src.data_sets.push_back({1, + {NamedValue{"DVNAME-A", s2::Item::u4(uint32_t{42})}, + NamedValue{"DVNAME-B", s2::Item::ascii("ok")}}}); + src.data_sets.push_back({2, {NamedValue{"DVNAME-C", s2::Item::boolean(true)}}}); + auto m = s6f8_data_transfer_send(src); + CHECK(m.stream == 6); + CHECK(m.function == 8); + + auto parsed = parse_s6f8(m); + REQUIRE(parsed.has_value()); + CHECK(parsed->dataid == 7); + CHECK(parsed->ceid == 300); + REQUIRE(parsed->data_sets.size() == 2); + CHECK(parsed->data_sets[0].dsid == 1); + REQUIRE(parsed->data_sets[0].values.size() == 2); + CHECK(parsed->data_sets[0].values[0].dvname == "DVNAME-A"); + CHECK(parsed->data_sets[0].values[1].dvval == s2::Item::ascii("ok")); + CHECK(parsed->data_sets[1].dsid == 2); + CHECK(parsed->data_sets[1].values[0].dvname == "DVNAME-C"); +} + TEST_CASE("S6F15 / S6F16 event report request/data round-trip") { auto req = s6f15_event_report_request(300); auto parsed = parse_s6f15(req); @@ -601,6 +627,49 @@ TEST_CASE("S12F13/F14 + F15/F16 + F17/F18 request shapes round-trip") { CHECK(parsed_cr->sdbin == 0xFF); } +TEST_CASE("S12F14 map-data send-row reply round-trip") { + // Reply to F13: [MID, IDTYP, [[RSINF, BINLT], ...]]. + MapDataRowReply src{"WAFER-1", 0x01, + {{{0, 0, 1}, std::string("\x00\x01", 2)}, + {{0, 1, 1}, std::string("\x02\x03", 2)}}}; + auto m = s12f14_map_data_send_row_reply(src); + auto parsed = parse_s12f14(m); + REQUIRE(parsed.has_value()); + CHECK(parsed->mid == "WAFER-1"); + CHECK(parsed->idtyp == 0x01); + REQUIRE(parsed->rows.size() == 2); + CHECK(parsed->rows[0].rsinf.x == 0); + CHECK(parsed->rows[0].rsinf.y == 0); + CHECK(parsed->rows[0].rsinf.direction == 1); + CHECK(parsed->rows[0].binlt.size() == 2); + CHECK(parsed->rows[1].rsinf.y == 1); +} + +TEST_CASE("S12F16 map-data send-array reply round-trip") { + // Reply to F15: [MID, IDTYP, STRP, BINLT] — same shape as F9. + MapDataArray src{"WAFER-1", 0x01, ReferencePoint{-5, 5}, std::string("\xAA\xBB\xCC", 3)}; + auto m = s12f16_map_data_send_array_reply(src); + auto parsed = parse_s12f16(m); + REQUIRE(parsed.has_value()); + CHECK(parsed->mid == "WAFER-1"); + CHECK(parsed->strp.x == -5); + CHECK(parsed->strp.y == 5); + CHECK(parsed->binlt.size() == 3); +} + +TEST_CASE("S12F18 map-data send-coord reply round-trip") { + // Reply to F17: [MID, IDTYP, [[XYPOS, BINLT], ...]] — same shape as F11. + MapDataCoord src{"WAFER-1", 0x01, + {{ReferencePoint{1, 2}, std::string("\x07", 1)}, + {ReferencePoint{3, 4}, std::string("\x08", 1)}}}; + auto m = s12f18_map_data_send_coord_reply(src); + auto parsed = parse_s12f18(m); + REQUIRE(parsed.has_value()); + REQUIRE(parsed->entries.size() == 2); + CHECK(parsed->entries[0].xypos.x == 1); + CHECK(parsed->entries[1].xypos.y == 4); +} + TEST_CASE("S7F17 / S7F18 delete PP round-trip") { auto m = s7f17_delete_pp_send({"R1", "R2", "R3"}); auto parsed = parse_s7f17(m);