Commit Graph

5 Commits

Author SHA1 Message Date
catarrh abc9ea2751 v3.15.0: test-script fixes for applet testing - preset id, kvn, PoR and file-list checks
Three gaps blocked SCP80 applet testing from the PWA:

- testRunPreset() still marshalled the pre-v3.8 flat preset fields
  (kic/kid/keys/counter/tar/spi1/spi2, all empty on a stored preset), so
  every SCP80 run failed with "SCP80 preset is incomplete: no keyset is
  defined".  The PWA sends the matched preset's id now and the server
  resolves it from the store (_test_run_preset_from_body; the inline
  `preset` body stays for API callers), so a run always uses the stored
  keysets, TARs and counters.  Regression tests on both sides.
- testscript._normalise_params dropped the scp80 step's `kvn` (the editor
  exposed it and the runner and validation consumed it, so scripts
  silently used the preset's first keyset).  kvn is validated (1-15) and
  passed through; the client-side problem check bounds it too.
- The PoR delivered as a SEND SHORT MESSAGE (PoR-in-submit, SPI2 bit 0x20)
  is decoded for the expect step that fetches it: the new `por` content
  check asserts the response status / R-APDU SW / response data, decoded
  with the preceding scp80 step's context (concatenated SMS accumulate
  across expectations).  The inline transport stays on the action
  (check.por / check.data).
- The new `files` content check asserts the File List of a REFRESH
  (TS 102 223 8.18, tag 12/92) - e.g. qualifier 00 = NAA initialization
  with full file change notification - as an order-insensitive set of FID
  paths.

The step editor exposes both checks; help EN/RU, docs/api.md and the new
authoring reference docs/test-scripts.md document the format.  Tests: 803
frontend + 680 Python; sw cache simple-v378.
2026-10-04 17:09:06 +03:00
catarrh 6360dc5bae v3.10.0: preset TAR table with per-TAR MSL; derive the SPI1 from the TAR
Presets drop the card-wide SPI1/SPI2 and the fixed tar/uiccTar/usimTar
fields: a preset now carries `tars` - the three mandatory role entries
(isd/uiccRfm/usimRfm, spec defaults pre-settled) plus free TARs with an
optional description, each with its MSL (Minimum SPI1, TS 102 226
8.2.1.3.2.4).  v3.9.1 presets convert on load/import (the spi1 seeds all
three MSLs); duplicate TARs and empty TAR/MSL values are refused; the
store schema version is 3.

Operations derive a packet's SPI1 from its TAR's MSL (_spi1_for_tar): the
RAM ops, the test runner (per-step overrides still win), the counter probe
and each TAR-probe row; the plain send keeps an explicit SPI1 with a
`warning` when it is below the MSL, and a TAR outside the preset without an
explicit SPI1 is refused with a hint.  The TAR probe resolves per checked
TAR before sending and reports the effective spi1 per row.  The secured
packet form's SPI2 default is 00 (the RAM/probe operations pin their own).

PWA: the Cards form edits the TAR table (role rows with MSL inputs plus
Add/Remove free rows with a description), the list shows a TARs (MSL)
column, the SCP80 TAR field suggests the preset's entries (datalist) and a
preset apply seeds the SPI1 from the operation TAR's MSL with an amber
warning below it; the preset-wide SPI1/SPI2 fields and the header marker's
SPI requirement are gone (completeness = a keyset + the three role entries
with their MSLs).  Help EN/RU, docs/api.md and AGENTS updated; sw cache
simple-v358.

Live: TAR probe 000000 at its MSL 16 (registered, por_ok, counter
advanced); a send without spi1 derived 16 (por_ok, counter advanced); a
send with spi1 0A returned the warning and the card refused it (6200, no
counter consumed); an unknown TAR without spi1 was refused with the hint.
2026-10-02 08:28:46 +03:00
catarrh 2d2a40a73c fix: follow-up test-script review findings (v3.5.14)
- The SCP80 counter write-back resolves the preset by NAME first (the run
  snapshot prefers the name) and only falls back to an ICCID-looking
  value: presets with digits in their names are found after a page reload
  (the previous fallback ran cardsNormIccid on the name and gave up).
- testScriptProblem validates the *selected* SCP80 source (like the form
  and the server), so source=apdu with only sp filled is caught locally
  instead of failing with a server 400.
- _test_run_start cleans up (_TEST_RUNNING=False, run state error) when
  the worker thread cannot be created/started, and the endpoint answers
  500 with a clear error instead of leaving the card blocked behind a run
  that never started.
- The 5 s poll writes the counter back whenever a run is finished
  (idempotent), so a reloaded page saves it without visiting the pill.
- Mask wildcards ('?') are stripped from the hex fields that cannot carry
  a mask (APDU, secured packet, event/file data, TAR/SPI overrides, DCS,
  extra TLVs); check values keep them.

Tests: frontend +3 (write-back by name / by ICCID, mask-free fields,
source-aware script check), Python +1 (failed thread start unblocks).
586 frontend / 471 Python green; version 3.5.14; sw simple-v267.
2026-09-27 01:52:03 +03:00
catarrh d1eb88d4d7 fix: test-script review findings (v3.5.13)
PWA:
- The SCP80 "Source" switch sticks: the choice is stored in
  `params.source`, switching keeps both values (the server honors the
  explicit source when both are present, and the form validates only the
  selected one).
- The SW check field is empty by default (placeholder "default: 9000
  (91?? when polling)"), so the server defaults apply - previously the
  pre-filled 9000 defeated the polling STATUS default and a card that
  announced a command made the step fail with "expected 9000".
- Item text checks offer contains/exact only (the mask mode was rejected
  by the server validation).
- The SCP80 counter is written back to the preset even when the run is
  observed after a page reload or was started elsewhere (resolved by
  ICCID or preset name from the run snapshot).

Server:
- Step-entry mutations happen under `_TEST_LOCK`
  (`_test_entry_update`/`_test_finish_entry`): the status endpoint
  serializes the state with json.dumps, so entries must not change while
  it iterates them.
- The pending-command drains (unexpected command, error, stop) hold
  `_CARD_LOCK` like every other card conversation.
- `_int` accepts plain decimals with leading zeros and 0x hex.
- The scripted TERMINAL RESPONSE text string uses the CR-set tag `8D`
  (consistent with the other TR TLVs; both are legal).
- A script-driven menu selection mirrors `server.menu_active`.

Tests: frontend +4 (source switch/round-trip, status SW default, render
checks, item modes), Python +3 (integer parsing, menu_active, source
selection).  Help/docs unaffected beyond api.md's `source` note.

583 frontend / 470 Python green.
2026-09-27 01:48:12 +03:00
catarrh 3a4a098f1a feat: test script engine and server-side runner (phase 1)
A test script drives a deterministic dialogue with the card: action steps
(ENVELOPE event / Menu Selection, raw APDU, SCP80 secured packet with a
card-preset, file update/read, STATUS) with SW/data/PoR checks, and
proactive-command expectations that fetch, check (command type, qualifier,
text/item/raw) and answer with a scripted TERMINAL RESPONSE.

- pysim_simple_server/testscript.py: pure engine (validation, exact/mask
  matchers with '?' nibble wildcards, item/text checks, TERMINAL RESPONSE
  building).
- server.py: worker thread + state, /api/test/run|status|stop|clear, the
  card-endpoint guard (409 while running), background STATUS polling
  suspended, 'error terminates / warning continues', a pending command is
  drained with a cancel TR on stop/error, no-drain modes for the ENVELOPE
  and SCP80 senders (the pending command belongs to the next expectation).
- Expectations never poll: a command must be pending (91XX) from the
  previous step, otherwise it is an error (TS 102 221 7.4.2.1 / TS 102 223
  6.3); scripts add an explicit `status` action (attempts/interval) when
  the card delivers on poll.
- SCP80 steps require a complete card preset, may override TAR/SPI1/SPI2
  only, and the counter is advanced per send and reported
  (`scp80_counter`) for the PWA to write back.
- tests/test_testscript.py (26 tests: engine, matchers, TR building, the
  STK menu dialogue, error/warning termination, status polling,
  unexpected-command drain, SCP80 preset/counter, file actions, guards).
- docs/api.md endpoint reference.

467 Python / 573 frontend green.
2026-09-27 00:59:53 +03:00