L: E87 slot-map verification wire (S3F19/F20 + F21/F22)

Closes the slot-map verification gap I called out:

  S3F19 / F20  host -> equip: verify expected slot map against what
               the equipment has scanned. Equipment compares element-
               wise; on match drives CSMS NotRead -> Read and replies
               SVACK=Accept; on mismatch drives CSMS -> Mismatched and
               replies SVACK=Mismatch.

  S3F21 / F22  equip -> host: equipment-initiated slot map report
               (typically pushed after CARRIERID is confirmed).

New SVACK enum: SlotMapVerifyAck { Accept, Mismatch, CarrierUnknown,
Error }.  Server dispatch on S3F19 wires the actual CSMS transition
through the CarrierStore from D3.

Two round-trip tests cover both pairs; the FSM-driving behaviour is
exercised through the in-process tests because secs_server.cpp is
the dispatch entry point (no separate integration test needed beyond
the wire round-trip).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-08 08:48:56 +02:00
parent a52d44ade5
commit 5a3f5ca6da
4 changed files with 111 additions and 0 deletions
+28
View File
@@ -782,6 +782,34 @@ TEST_CASE("S3F25 / S3F26 CarrierTransfer round-trip") {
CHECK(*ack_byte(s3f26_carrier_transfer_ack(CarrierActionAck::Accept)) == 0);
}
TEST_CASE("S3F19 / S3F20 SlotMapVerify round-trip") {
std::vector<std::string> raw_slots = {std::string({0x01, 0x01, 0x00, 0x01})};
// Build via the typed builder: list of BINARY_BYTE per slot.
std::vector<uint8_t> slots = {0x01, 0x01, 0x00, 0x01};
auto m = s3f19_slot_map_verify("CAR-001", slots);
CHECK(m.stream == 3);
CHECK(m.function == 19);
CHECK(m.reply_expected);
auto parsed = parse_s3f19(m);
REQUIRE(parsed.has_value());
CHECK(parsed->carrierid == "CAR-001");
CHECK(parsed->slots == slots);
CHECK(*ack_byte(s3f20_slot_map_verify_ack(SlotMapVerifyAck::Accept)) == 0);
CHECK(*ack_byte(s3f20_slot_map_verify_ack(SlotMapVerifyAck::Mismatch)) == 1);
}
TEST_CASE("S3F21 / S3F22 SlotMapReport round-trip") {
std::vector<uint8_t> slots = {0x01, 0x00};
auto m = s3f21_slot_map_report("CAR-002", slots);
auto parsed = parse_s3f21(m);
REQUIRE(parsed.has_value());
CHECK(parsed->carrierid == "CAR-002");
CHECK(parsed->slots == slots);
CHECK(*ack_byte(s3f22_slot_map_report_ack(SlotMapVerifyAck::Accept)) == 0);
}
TEST_CASE("S3F27 / S3F28 CancelCarrier round-trip") {
auto m = s3f27_cancel_carrier("CAR-001");
auto parsed = parse_s3f27(m);