From af00932acae62de7e701714614bf20dcfb793d9a 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 12:23:12 +0300 Subject: [PATCH] v3.25.1: the run-ownership fix for the proactive auto-handling A card that re-queues a command immediately after each accepted TR (live 2026-10-11: the EP BAP card re-issued the same PROVIDE LOCAL INFORMATION 1100 times) turned the background poll's FETCH/TR chain into an unbounded loop that held _CARD_LOCK forever - every card operation, a test run's start included, blocked behind it. The chain now yields: - _handle_proactive_chain aborts before the next FETCH while a test run owns the card (_TEST_RUNNING) - the pending command stays for the script - and takes max_rounds; the background poll passes _POLL_CHAIN_MAX = 10, so a chatty card cannot hold the lock. - _do_status_poll re-arms on its run skip (a heartbeat that never fetches); _timer_expired and the BIP Data-available event wait during a run; _bip_flush_channel_events stays quiet too. - _sim_resume_poll() resumes polling at every run end - the two worker bodies, their exception paths and the spawn failure. Also the TR command-details qualifier echo (TS 102 223 6.8.1: the object shall be identical to the command's): _build_tr, testscript.build_tr and the interactive _menu_send_response echoed a hardcoded 00 - harmless for the loop's qual-00 PLI, wrong for any other qualifier. The menu pendings now carry cmd_qual (parsed in the on_fetch handler). Tests: the chain bound/abort (a fake card re-queueing a command), the poll/timer guards, the resume wiring, the qualifier echo in both builders. 883 frontend + 865 Python; sw cache simple-v425. --- 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 | 95 +- pysim_simple_server/testscript.py | 10 +- simple_lastrun_fetch_loop.log | 4546 +++++++++++++++++++++++++++++ tests/test_ota_helpers.py | 23 +- tests/test_poll.py | 91 + 10 files changed, 4743 insertions(+), 32 deletions(-) create mode 100644 simple_lastrun_fetch_loop.log diff --git a/frontend/help-ru.html b/frontend/help-ru.html index 114293b..383308b 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 и автоматическая обработка проактивных команд приостанавливаются — объявленная картой команда остаётся ожидающей для скрипта, и оба механизма возобновляются по завершении запуска; отчёт о запуске хранится в памяти (в том числе после перезагрузки страницы) до нажатия Очистить отчёт. Скрипты хранятся в хранилище на сервере (~/.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»).