Files
ui/_docs/02_document/tests/resource-limit-tests.md
T
Oleksandr Bezdieniezhnykh 510df68bcf [AZ-447] autodev Steps 1-4 baseline: docs, tests, refactor specs
Captures the full output of autodev existing-code Phase A through
Step 4 (Code Testability Revision) for the Azaion UI workspace:

- Step 1 Document: _docs/02_document/ (FINAL_report, architecture,
  glossary, components/, modules/, diagrams/, system-flows,
  module-layout) plus _docs/00_problem/ + _docs/01_solution/ +
  _docs/legacy/ + _docs/how_to_test + README.
- Step 2 Architecture Baseline: architecture_compliance_baseline.md.
- Step 3 Test Spec: _docs/02_document/tests/ (environment,
  test-data, blackbox/performance/resilience/security/
  resource-limit tests, traceability-matrix), enum_spec_snapshot,
  expected_results/results_report.md (98 rows), plus the
  run-tests.sh + run-performance-tests.sh runners.
- Step 4 Code Testability Revision: 01-testability-refactoring/
  run dir (list-of-changes C01-C07, deferred_to_refactor,
  analysis/research_findings + refactoring_roadmap) and the 7
  child task specs AZ-448..AZ-454 under _docs/02_tasks/todo/
  plus _dependencies_table.md.
- _docs/_autodev_state.md pins the cursor at Step 4 / refactor
  Phase 4 entry so /autodev resumes cleanly.

Epic AZ-447 (UI testability gates) tracks the 7 child tasks that
will land in subsequent commits.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 00:38:49 +03:00

7.1 KiB

Resource Limit Tests

The SPA's resource constraints are bundle size (initial JS), upload size cap (server), runtime image footprint (nginx:alpine only), and exclusion of the unbundled mission-planner/ from production output. Long-session memory / CPU behavior is also covered here at a documentary level — no AC binds a hard runtime memory budget today.

NFT-RES-LIM-01: Initial JS bundle ≤ 2 MB gzipped

Traces to: AC-11, O13

Preconditions:

  • bun run build has produced dist/.

Monitoring:

  • Sum of gzipped initial-route JS chunk sizes (computed from Vite's manifest.json).

Duration: ≤ 60 s (build + measurement). Pass criteria: total gzipped initial JS ≤ 2 097 152 bytes (results_report.md row 40). Documentary today; CI gate target. Expected result source: results_report.md row 40.


NFT-RES-LIM-02: nginx client_max_body_size 500M

Traces to: AC-10, E9

Preconditions:

  • nginx.conf present in the repo (and in the built image's /etc/nginx/).

Monitoring:

  • Read the value of client_max_body_size from nginx.conf.

Duration: ≤ 5 s. Pass criteria: value equals 500M (results_report.md row 38). Expected result source: results_report.md row 38.


NFT-RES-LIM-03: Production image is nginx:alpine and carries no Node.js

Traces to: AC-33, S5, O11

Preconditions:

  • Built image azaion/ui:<tag> available locally.

Monitoring:

  • docker inspect azaion/ui:<tag> for the final stage's base image.
  • Filesystem scan inside the image for a node binary.

Duration: ≤ 30 s. Pass criteria: base image is nginx:alpine; no node binary present (results_report.md row 42). Expected result source: results_report.md row 42.


NFT-RES-LIM-04: mission-planner/ is excluded from production bundle

Traces to: AC-31, O12, ADR-009

Preconditions:

  • bun run build has produced dist/.

Monitoring:

  • Vite's build report / manifest for chunk origins.
  • Static-import graph analysis starting from src/main.tsx — verify no edges into mission-planner/.

Duration: ≤ 30 s. Pass criteria: no dist/** file originates from mission-planner/**; the import graph from src/main.tsx does NOT reach mission-planner/ (results_report.md row 41). Expected result source: results_report.md row 41.


NFT-RES-LIM-05: SPA memory stable across a 30-minute annotation session

Traces to: H2 (edge deploy), AC-09 (SSE) Status: documentary — no AC binds a hard runtime memory budget today

Preconditions:

  • E2E profile; user logged in on /annotations; annotation-status SSE open.

Monitoring:

  • Headless Chromium performance.memory.usedJSHeapSize sampled every 60 s for 30 min.

Duration: 30 min. Pass criteria: usedJSHeapSize does not grow by more than 50 % over the session under steady-state interaction (open/close media, page through dataset). A documentary baseline; if Phase 3 deems it un-anchored to an AC, it is downgraded to a metric-only run.


NFT-RES-LIM-06: Live-GPS SSE 1-hour soak — no listener leak, no memory creep

Traces to: AC-08 Status: documentary

Preconditions:

  • E2E profile; flight selected; live-GPS simulator emits at 1 Hz.

Monitoring:

  • EventSource instance count sampled every 60 s — must stay at exactly 1.
  • usedJSHeapSize sampled every 60 s.

Duration: 60 min. Pass criteria: EventSource count stays at 1 throughout; heap grows by ≤ 30 % (documentary).


NFT-RES-LIM-07: 100 sequential flight selections — no leaked SSEs, no leaked Contexts

Traces to: AC-08, P4 Status: documentary

Preconditions:

  • E2E profile; ≥ 5 flights in seed.

Monitoring:

  • Total EventSource instances created over the loop.
  • Final open EventSource count (after deselect-then-reselect cycles end at "deselected").

Duration: ≤ 5 min. Pass criteria: after the loop, open EventSource count is ≤ 1 (only the currently-selected stream if any). No more than 100 + 1 EventSources were created in total (one extra for any pre-test state). Documentary; Phase 3 to confirm or downgrade.


NFT-RES-LIM-08: Edge-host RAM profile of the UI image at steady state

Traces to: H2 Status: documentary; hardware-assessment phase will pin the exact numbers

Preconditions:

  • Production image running on the target edge profile (2 vCPU, 4 GB RAM).

Monitoring:

  • docker stats azaion-ui sampled every 10 s for 5 min while a user is actively on /annotations with one open SSE.

Duration: 5 min. Pass criteria: RSS of the nginx process under sustained traffic stays under 200 MB (documentary baseline; will be tightened or relaxed at hardware-assessment time).


NFT-RES-LIM-09: nginx routes — exactly 9 location blocks for the suite services

Traces to: AC-34, E2

Preconditions:

  • nginx.conf present.

Monitoring:

  • Parse nginx.conf for location blocks under the main server.

Duration: ≤ 5 s. Pass criteria: location block set equals {/api/admin/, /api/flights/, /api/annotations/, /api/detect/, /api/loader/, /api/gps-denied-desktop/, /api/gps-denied-onboard/, /api/autopilot/, /api/resource/} (results_report.md row 43). Expected result source: results_report.md row 43.


NFT-RES-LIM-10: nginx — each route strips its /api/<service>/ prefix

Traces to: AC-34, E2

Preconditions:

  • nginx.conf present.

Monitoring:

  • Per location block, inspect the proxy_pass / rewrite directive shape — verify the prefix is stripped before forwarding upstream.

Duration: ≤ 5 s. Pass criteria: every block satisfies the strip-prefix regex (per-block check, results_report.md row 44). Expected result source: results_report.md row 44.


NFT-RES-LIM-11: CI image tag scheme is ${branch}-arm

Traces to: AC-32, E7

Preconditions:

  • .woodpecker/build-arm.yml present.

Monitoring:

  • Parse the push step's tag field for branches dev, stage, main.

Duration: ≤ 5 s. Pass criteria: pushed tag for branch main matches ^main-arm$ (results_report.md row 70). Same regex shape for dev and stage (derived). Expected result source: results_report.md row 70.


NFT-RES-LIM-12: OCI labels present on the pushed image

Traces to: AC-32, E6

Preconditions:

  • .woodpecker/build-arm.yml present.

Monitoring:

  • Parse the push step's label declarations — count and presence.

Duration: ≤ 5 s. Pass criteria: labels org.opencontainers.image.revision, org.opencontainers.image.created, org.opencontainers.image.source are all declared and non-empty; total label count == 3 (results_report.md row 71). Expected result source: results_report.md row 71.


NFT-RES-LIM-13: Revision label equals $CI_COMMIT_SHA

Traces to: AC-32, E5

Preconditions:

  • .woodpecker/build-arm.yml present.

Monitoring:

  • Parse the label value template for org.opencontainers.image.revision.

Duration: ≤ 5 s. Pass criteria: label value template equals $CI_COMMIT_SHA (or the pipeline's documented equivalent) (results_report.md row 72). Expected result source: results_report.md row 72.