From 8d39904d2c463d79683dbff54016a35535adeea4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D1=82=D0=BE=D0=BD=20=D0=A2=D1=80=D0=BE=D1=88?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Sun, 11 Oct 2026 14:02:29 +0300 Subject: [PATCH] v3.25.3: the card's BIP commands during test runs The runner's three FETCH/TR sites (the proactive-drain action, the expectation, the cleanup drain) built every TERMINAL RESPONSE from the script, so a card-announced OPEN CHANNEL during a run was answered "performed successfully" without opening a channel - SEND DATA was dropped and RECEIVE DATA returned nothing (silent data loss, broken applet state). _test_step_tr now routes 0x40-0x44 through _handle_bip_command: the terminal answers for real, so the card's channels work inside a run. The script keeps an escape hatch - a respond with `raw` TLVs or a non-ok result wins (the applet error-path tests). The BIP events flow during a run again for the channels the card itself opened: _bip_data_available and _bip_flush_channel_events no longer stop at the run guard (a channel only exists because the card opened it) and the runner flushes the link events after each TR, so an applet's own HTTP/BIP conversation completes inside a scripted run. BIP control stays blocked (409). Tests: the drain/expect/cleanup routing, the raw and non-ok-result overrides, the run-time data-available and link events. 883 frontend + 873 Python; sw cache simple-v427. --- docs/test-scripts.md | 23 ++++++++++ frontend/help-ru.html | 2 +- frontend/help.html | 2 +- frontend/index.html | 2 +- frontend/sw.js | 2 +- pyproject.toml | 2 +- pysim_simple_server/server.py | 52 +++++++++++++++++------ tests/test_poll.py | 29 ++++++++++++- tests/test_testscript.py | 79 +++++++++++++++++++++++++++++++++++ 9 files changed, 173 insertions(+), 20 deletions(-) diff --git a/docs/test-scripts.md b/docs/test-scripts.md index 841f4b6..9c16e63 100644 --- a/docs/test-scripts.md +++ b/docs/test-scripts.md @@ -525,6 +525,29 @@ The `proactive-drain` action's `respond`/`first` use the same shape (the command type varies per drained command, so `text`/`item_id` apply where the command carries them). +### BIP commands in scripts + +The card's own BIP commands (`OPEN CHANNEL` 0x40, `CLOSE CHANNEL` 0x41, +`RECEIVE DATA` 0x42, `SEND DATA` 0x43, `GET CHANNEL STATUS` 0x44) are answered +by the **terminal**, not by the script: during a run the channels really open, +the data really flows to/from the configured BIP target, and the BIP events +(Data available, Channel status) flow for the channels the card itself opened - +so an applet's own HTTP/BIP conversation completes inside a scripted run. The +BIP **control** API stays blocked while a run is active (409), like the +terminal's other automatic actions (polling, timers, menu). + +A step's `respond` overrides the terminal when it carries `raw` TLVs or a +**non-ok result** - the way to script an applet error path: + +```json +{"type": "expect", "command": "OPEN CHANNEL", + "respond": {"result": "refused"}} +``` + +A plain `{"result": "ok"}` (or no `respond`) leaves the BIP answer to the +terminal; the step log names it (`BIP: the terminal answered OPEN CHANNEL +(0x40)`). + ## The two PoR transports (SPI2) 1. **Inline** - the card answers the ENVELOPE `9000` with the PoR in the diff --git a/frontend/help-ru.html b/frontend/help-ru.html index 383308b..c83835c 100644 --- a/frontend/help-ru.html +++ b/frontend/help-ru.html @@ -565,7 +565,7 @@

8.9 Тест-скрипт

-

Тест-скрипт — упорядоченный список действий и ожиданий проактивных команд, выполняемый на подключённой карте на стороне сервера. Пока запуск активен, карта принадлежит скрипту: остальные операции с картой отклоняются (HTTP 409), фоновый опрос STATUS и автоматическая обработка проактивных команд приостанавливаются — объявленная картой команда остаётся ожидающей для скрипта, и оба механизма возобновляются по завершении запуска; отчёт о запуске хранится в памяти (в том числе после перезагрузки страницы) до нажатия Очистить отчёт. Скрипты хранятся в хранилище на сервере (~/.pysim-simple-server/test_scripts.json, --test-scripts), поэтому все браузеры работают с одним набором; изменения записываются в хранилище по мере правки (кнопки «Сохранить» нет — черновик без валидного шага остаётся локальным); экспорт/импорт JSON остаётся для резервных копий и переноса скриптов между стендами (старый экспорт из localStorage импортируется как есть).

+

Тест-скрипт — упорядоченный список действий и ожиданий проактивных команд, выполняемый на подключённой карте на стороне сервера. Пока запуск активен, карта принадлежит скрипту: остальные операции с картой отклоняются (HTTP 409), фоновый опрос STATUS и автоматическая обработка проактивных команд приостанавливаются — объявленная картой команда остаётся ожидающей для скрипта, и оба механизма возобновляются по завершении запуска. Собственные BIP-команды карты (OPEN/SEND/RECEIVE/CLOSE CHANNEL, GET CHANNEL STATUS) — исключение: терминал отвечает на них по-настоящему: каналы продолжают работать во время запуска, а BIP-события приходят для каналов, открытых самой картой (управление BIP остаётся заблокированным) — если только respond шага не переопределяет ответ через raw TLV или результат, отличный от ok; отчёт о запуске хранится в памяти (в том числе после перезагрузки страницы) до нажатия Очистить отчёт. Скрипты хранятся в хранилище на сервере (~/.pysim-simple-server/test_scripts.json, --test-scripts), поэтому все браузеры работают с одним набором; изменения записываются в хранилище по мере правки (кнопки «Сохранить» нет — черновик без валидного шага остаётся локальным); экспорт/импорт JSON остаётся для резервных копий и переноса скриптов между стендами (старый экспорт из localStorage импортируется как есть).

У вкладки четыре представления: список наборов (по умолчанию; Добавить набор / Редактировать / Запустить / Экспорт / Удалить), редактор набора (скрипты набора в порядке выполнения — необязательный setup первым и teardown последним, с пометками ролей; у каждого скрипта Запустить/Редактировать/Переместить/Скопировать/Удалить, политика при ошибке остановить (по умолчанию) / продолжить и Требуется ADM), редактор скрипта (список шагов; кнопка Старт выполняет только этот скрипт и показывает результат под шагами — он не сохраняется) и отчёт набора (после запуска набора: статус каждого скрипта, таблица шагов с ожидаемым/фактическим, примечание об ошибке и выдержка из журнала запуска; сводка с успешно/предупреждения/ошибки/пропущено, время выполнения, счётчики SCP80 до → после по каждому keyset, пресет и предупреждение о смене сессии карты; экспорт в JSON или Markdown). Запуск набора выполняет его скрипты по порядку в одной сессии карты, без сбросов и без продолжения с места остановки; при ошибке решает, остановится ли набор на этом скрипте или запустится следующий, teardown выполняется всегда при остановке или ошибке (пока карта в ридере), чтобы следующий тест начался с чистого состояния, а сброс карты останавливает набор и отмечается в отчёте. Начать со сброса карты сбрасывает карту и выполняет полную переинициализацию перед запуском набора (скрипты затем работают со свежеинициализированной картой); пресет должен по-прежнему совпадать с ICCID карты, а требуемый ADM проверяется заново для новой сессии карты. Инициализация поглощает начальные proactive-команды карты, поэтому скрипт не поймает первую команду после сброса (они остаются в журнале proactive). Требуется ADM (у набора или скрипта) проверяет ключ ADM из подобранного пресета один раз перед запуском — ошибка отклоняет запуск (проверьте вручную через значок ADM; автоматических повторов нет). Скрипты хранятся в хранилище наборов (~/.pysim-simple-server/test_suites.json, --test-suites); каждый скрипт принадлежит ровно одному набору, и скрипт можно переместить или скопировать в другой набор (экспорт набора — это пакет с набором и его скриптами; старый экспорт только скриптов импортируется в автоматически созданный набор «Imported scripts»).