M: S16F7/F8 PRJobMonitor + S16F15/F16 PRJobCreateMultiple
Closes the two E40 bulk/control gaps the COMPLIANCE doc had flagged
as out-of-scope:
S16F7 / F8 PRJobMonitor — host enables/disables S16F9 alerts
per PJ. PRALERT bit 7 is the enable flag (matches the
ALED convention from S5F3). Server dispatches into the
existing set_alert() store API.
S16F15 / F16 PRJobCreateMultiple — bulk create variant. Host posts
a list of (PRJOBID, PPID, MTRLOUTSPEC) entries; the
equipment processes them in order and returns a
per-PJ HCACK list so the host can identify which
subset failed. Same validators as S16F11.
Catalog now has three new structs: PRJobMonitorEntry,
PRJobCreateEntry, PRJobCreateMultiResult. Two round-trip tests cover
the new wire shapes; server-side correctness is exercised through the
existing PJ store invariants (dedup, validator) which both new paths
delegate to.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -649,6 +649,48 @@ TEST_CASE("S16F9 PRJobAlert round-trip with typed state byte") {
|
||||
CHECK(parsed->prjobstate == ProcessJobState::Processing);
|
||||
}
|
||||
|
||||
TEST_CASE("S16F7 / S16F8 PRJobMonitor round-trip") {
|
||||
std::vector<PRJobMonitorEntry> entries{
|
||||
{"PJ-1", 0x80}, // enable
|
||||
{"PJ-2", 0x00}, // disable
|
||||
};
|
||||
auto m = s16f7_pr_job_monitor(entries);
|
||||
CHECK(m.stream == 16);
|
||||
CHECK(m.function == 7);
|
||||
CHECK(m.reply_expected);
|
||||
|
||||
auto parsed = parse_s16f7(m);
|
||||
REQUIRE(parsed.has_value());
|
||||
REQUIRE(parsed->entries.size() == 2);
|
||||
CHECK(parsed->entries[0].prjobid == "PJ-1");
|
||||
CHECK(parsed->entries[0].pralert == 0x80);
|
||||
|
||||
CHECK(*ack_byte(s16f8_pr_job_monitor_ack(HostCmdAck::Accept)) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("S16F15 / S16F16 PRJobCreateMultiple round-trip") {
|
||||
std::vector<PRJobCreateEntry> jobs{
|
||||
{"PJ-A", "RECIPE-1", {"W1"}},
|
||||
{"PJ-B", "RECIPE-2", {"W2", "W3"}},
|
||||
};
|
||||
auto m = s16f15_pr_job_create_multi(jobs);
|
||||
auto parsed = parse_s16f15(m);
|
||||
REQUIRE(parsed.has_value());
|
||||
REQUIRE(parsed->jobs.size() == 2);
|
||||
CHECK(parsed->jobs[0].prjobid == "PJ-A");
|
||||
CHECK(parsed->jobs[1].mtrloutspec.size() == 2);
|
||||
|
||||
std::vector<PRJobCreateMultiResult> results{
|
||||
{"PJ-A", HostCmdAck::Accept},
|
||||
{"PJ-B", HostCmdAck::Rejected},
|
||||
};
|
||||
auto ackmsg = s16f16_pr_job_create_multi_ack(results);
|
||||
auto pack = parse_s16f16(ackmsg);
|
||||
REQUIRE(pack.has_value());
|
||||
REQUIRE(pack->results.size() == 2);
|
||||
CHECK(pack->results[1].ack == HostCmdAck::Rejected);
|
||||
}
|
||||
|
||||
TEST_CASE("S16F27 / S16F28 CJobCommand round-trip") {
|
||||
auto req = s16f27_cj_command("CJ-1", "CJSTART");
|
||||
auto parsed = parse_s16f27(req);
|
||||
|
||||
Reference in New Issue
Block a user