v3.21.0: the test-runner tolerance batch + the proactive cleanup action
Five reported issues, plus the action that makes an explicit drain possible: - on_fail is honoured by every step failure: an expectation with no pending command (or a FETCH that returns nothing) fails as a Command/Fetch check at the step's level instead of raising past it; the default still stops the run, on_fail "warning" continues (the tolerant consume-if-pending form). - the run cleanup answers ok (0x00) and keeps draining while the TR answers 91XX (bounded); a cancel is only sent when a script asks for it - it tells the card the user aborted the session and pushes assertive applets onto an error path. - new `proactive` action: STATUS rounds consume every announced command (respond/first TERMINAL RESPONSE results, attempts/interval_ms bound) until the card answers 9000; an optional require asserts at least one drained command (an empty drain fails it), the final SW is the step's SW check and a still-pending command is handed to the next step. PWA editor + summary + validation, EN/RU help, docs, action-kind drift test. - the PoR response form follows the command's TAR: _tar_is_rm (preset role entries + the TS 101 220 Annex D ISD/RFM allocations) decides; a non-RM TAR's reply is always raw (TS 102 226 4) - no fabricated status word even when the bytes happen to parse (01 00 0B 91 ... used to read as SW 000B). - a secured data too short for the compact structure (a 2-byte applet reply) is recovered by _por_header_parse (the decode minus the compact parse; a malformed packet or a failed RC/CC/DS check still yields no por) and reported raw, so short applet replies are assertable via por.data. Docs: test-scripts.md, api.md, help EN/RU, repo AGENTS. sw cache simple-v396. Tests: 825 frontend + 755 Python green.
This commit is contained in:
+32
-11
@@ -592,12 +592,16 @@ response carries them too, plus an `error`).
|
||||
fetched via a proactive command (FETCH). The response contains the
|
||||
same `por` structure if decoding succeeds.
|
||||
|
||||
When the secured data cannot be the TS 102 226 compact remote response (its
|
||||
command count exceeds the command script that was sent - a third-party
|
||||
applet's own TAR answers with application bytes), `por.response_type` is
|
||||
`raw`, the whole secured data is reported as `decoded.last_response_data`
|
||||
and no status word is decoded; `secured_data` carries the response bytes in
|
||||
every case.
|
||||
The response form follows the command's TAR (v3.21.0): a remote-management
|
||||
TAR (the preset's role entries and the standard ISD/RFM allocations of
|
||||
TS 101 220 Annex D) is decoded as an RM response; any other TAR's secured
|
||||
data is the receiving application's own (TS 102 226 4) and is reported with
|
||||
`por.response_type` `raw` - the whole secured data in
|
||||
`decoded.last_response_data` and no status word (`secured_data` carries the
|
||||
response bytes in every case). The same `raw` classification covers a
|
||||
secured data that cannot be the compact structure (its command count exceeds
|
||||
the command script that was sent, or it is too short for Table 5.1), while a
|
||||
genuinely malformed packet or a failed RC/CC/DS check still yields no `por`.
|
||||
|
||||
The SPI2 `por_in_submit` bit (0x20) selects submit-mode PoR.
|
||||
|
||||
@@ -722,20 +726,29 @@ number 1-15), `tar`/`spi1`/`spi2` overrides and `format` (`compact` default /
|
||||
`expanded` / `expanded-ae` - the TS 102 226 5.2.1 Command Scripting template
|
||||
around the C-APDU) - KIc/KID and the counter always
|
||||
come from the resolved preset, which must match the equipped card and be
|
||||
complete) or `status`
|
||||
complete), `status`
|
||||
(`attempts`, `interval_ms` - when `attempts > 1` the default SW check is the
|
||||
mask `91??`, i.e. poll until the card announces a command).
|
||||
mask `91??`, i.e. poll until the card announces a command) or `proactive`
|
||||
(the proactive cleanup: poll STATUS and consume every announced command -
|
||||
`respond`/`first` TERMINAL RESPONSE results, `attempts`/`interval_ms` bound,
|
||||
optional `require` `{command, qualifier?}` asserting at least one drained
|
||||
command; the final SW is the step's `check.sw`, so a still-pending card fails
|
||||
and hands the command to the next step - an empty drain passes unless
|
||||
`require` was given).
|
||||
|
||||
`check` is `{"sw": ..., "data": ...}` (exact or `{"mode": "mask", "value":
|
||||
"91??"}`, `?` = per-nibble wildcard) plus `"por"` for SCP80 -
|
||||
`"none"`/`"ok"`/`"any"` or an object `{"status"?, "sw"?, "data"?}` asserting
|
||||
the decoded PoR of this exchange (inline or SEND SHORT MESSAGE; at least one
|
||||
field). `on_fail` is `error` (terminates the script) or `warning` (continues).
|
||||
field). `on_fail` is `error` (terminates the script) or `warning` (continues)
|
||||
and applies to every step failure - including an expectation that finds no
|
||||
pending command (v3.21.0; `warning` is the tolerant consume-if-pending form).
|
||||
|
||||
**Expectation steps** (`type: "expect"`) require a command pending from the
|
||||
previous step (`91XX`); they never poll - a `9000` response means no command
|
||||
and is an error (TS 102 221 7.4.2.1 / TS 102 223 6.3; add a `status` action
|
||||
if the card delivers on poll). `command` is a name or type code; `checks`
|
||||
and fails the step at its `on_fail` level (TS 102 221 7.4.2.1 / TS 102 223
|
||||
6.3; a `status` action with `attempts > 1` polls when the card delivers on
|
||||
poll). `command` is a name or type code; `checks`
|
||||
may be `text` (contains/exact), `alpha` (the command's Alpha identifier
|
||||
`05`/`85`, contains/exact - distinct from the `8D` text string), `item`
|
||||
(`id`/`text` for SELECT ITEM / SET UP MENU), `raw` (mask), `por` (a SEND
|
||||
@@ -756,6 +769,14 @@ The response is the initial state (`running: true`), the final counter
|
||||
(`scp80_counter`) and the step list; poll `/api/test/status`. The PWA writes
|
||||
`scp80_counter` back to the card preset after the run.
|
||||
|
||||
A run that ends (an error, a stop, an unexpected pending command) with a
|
||||
command still announced **drains it with `ok` (0x00)** - fetching while the
|
||||
TERMINAL RESPONSE answers `91XX` (bounded); a cancel is never sent
|
||||
automatically (it tells the card the user aborted the session and can push
|
||||
assertive applications onto an error path). The cleanup is reported as a
|
||||
`cleanup` step; a script that wants the refusal path answers explicitly (an
|
||||
expectation's `respond`, or the `proactive` action's `first`).
|
||||
|
||||
### `GET /api/test/scripts` and the script store
|
||||
|
||||
Test scripts live in a server-side store (`~/.pysim-simple-server/test_scripts.json`,
|
||||
|
||||
Reference in New Issue
Block a user