From 8ebcfd8af4bd5d0d164441a2eca52373baeb60c9 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: Sat, 24 Oct 2026 11:58:51 +0300 Subject: [PATCH] load tests: show elapsed, average and ETA in the live stats The script-run head and the suite summary now display, while a load run repeats: the elapsed time so far, the average per completed iteration and the estimated time left (testLoadTiming / testDurationText / testIterAvgText), recomputed on every 2 s status poll. A finished run keeps the server's final elapsed_ms/avg_ms (no estimate), and before the first completed iteration only the elapsed time is shown - no bogus average or ETA. The timing is client-side over the existing load block (started, done, iterations), so it works with the running server as well; no server change is needed. Tests: the timing math and the two formatters, the script head render and the suite summary render (3 new). 1061 Python + 1074 frontend. sw cache simple-v480; CHANGELOG [3.38.0], help EN/RU, docs/test-scripts.md and the AGENTS notes. --- CHANGELOG.md | 6 ++++ docs/test-scripts.md | 5 ++- frontend/help-ru.html | 2 +- frontend/help.html | 2 +- frontend/index.html | 57 +++++++++++++++++++++++++++++++ frontend/sw.js | 2 +- frontend/tests/test_load.test.js | 58 +++++++++++++++++++++++++++++++- 7 files changed, 127 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9584d80..a3c8b5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,12 @@ every change carries a descriptive commit message. a target); the text field stays authoritative, so a name path or a file the lists do not carry can still be typed, and the picker preselects the current path when it is known. +- The **live load-test stats** now include the timing: while a script or suite + run repeats, the status line shows the **elapsed time**, the **average per + completed iteration** and the **estimated time left**, recomputed on every + status poll (`testLoadTiming`; the final report keeps the server's + `elapsed_ms`/`avg_ms`). No completed iteration yet means no bogus + average/estimate - only the elapsed time. ### Changed diff --git a/docs/test-scripts.md b/docs/test-scripts.md index 28ef78d..6c22eaf 100644 --- a/docs/test-scripts.md +++ b/docs/test-scripts.md @@ -242,7 +242,10 @@ between iterations is an error. The SCP80 counter state is shared across iterations, so packets continue from what the previous iteration consumed. The iteration count is a run parameter - the stored script/suite is unchanged. The accepted range is **1 to 1,000,000,000** (the PWA clamps, the server -answers 400 above it). +answers 400 above it). While the run repeats, the status line shows the +elapsed time, the average per completed iteration and the estimated time +left, recomputed on every poll; the final report keeps the server's +`elapsed_ms`/`avg_ms`. ## A card that stops answering diff --git a/frontend/help-ru.html b/frontend/help-ru.html index a1cbfc0..a680420 100644 --- a/frontend/help-ru.html +++ b/frontend/help-ru.html @@ -573,7 +573,7 @@

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

Тест-скрипт — упорядоченный список действий и ожиданий проактивных команд, выполняемый на подключённой карте на стороне сервера. Пока запуск активен, карта принадлежит скрипту: остальные операции с картой отклоняются (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 импортируется как есть). Карта, переставшая отвечать, не подвешивает запуск молча: через 30 с без прогресса сторожевой таймер помечает запуск как ошибку с указанием шага, ставит флаг остановки и пытается прервать зависший обмен, разрывая связь PC/SC в фоновом потоке (связь помечается устаревшей, так что следующий Equip пересоздаёт её). Драйвер с собственным тайм-аутом карты завершает шаг обычным путём.

У вкладки четыре представления: список наборов (по умолчанию; Добавить набор / Редактировать / Запустить / Экспорт / Удалить), редактор набора (скрипты набора в порядке выполнения — необязательный 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»).

-

Прогон можно повторить: поле «Итерации» рядом с Start / Run suite выполняет скрипт или весь набор указанное число раз — это нагрузочный тест. Успешные итерации не сохраняются: в статусе видны только счётчик (итерация k / N) и время, журнал шагов остаётся пустым, а память не растёт при любом числе итераций. Первая итерация, завершившаяся ошибкой, останавливает цикл и сохраняет свой полный отчёт (шаги, неудачные проверки, фрагмент журнала, отчёт по скриптам набора); Остановить завершает работу после текущей итерации, а смена карты между итерациями считается ошибкой (следующая карта никогда не запускается со скриптом другой карты). Число итераций — параметр прогона, сохранённый скрипт/набор не меняется; счётчики SCP80 продолжаются с того значения, которое израсходовала предыдущая итерация. Поле принимает от 1 до 1 000 000 000 итераций (практический предел — длительность прогона).

+

Прогон можно повторить: поле «Итерации» рядом с Start / Run suite выполняет скрипт или весь набор указанное число раз — это нагрузочный тест. Успешные итерации не сохраняются: в статусе видны только счётчик (итерация k / N) и время, журнал шагов остаётся пустым, а память не растёт при любом числе итераций. Первая итерация, завершившаяся ошибкой, останавливает цикл и сохраняет свой полный отчёт (шаги, неудачные проверки, фрагмент журнала, отчёт по скриптам набора); Остановить завершает работу после текущей итерации, а смена карты между итерациями считается ошибкой (следующая карта никогда не запускается со скриптом другой карты). Число итераций — параметр прогона, сохранённый скрипт/набор не меняется; счётчики SCP80 продолжаются с того значения, которое израсходовала предыдущая итерация. Поле принимает от 1 до 1 000 000 000 итераций (практический предел — длительность прогона). Пока прогон идёт, строка статуса также показывает прошедшее время, среднее время итерации и оставшееся время.