Skip to content

test runner: web runner mutates live application.wheels — replace global swap with request-scoped overlay #3025

Description

@bpamiri

Context

Phase 2 of the subfolder-deployment work (discussion #2887, issue #2968, PR #2985). The runtime subpath setting shipped in #2985; this issue tracks the test-runner half — the reporter's headline pain point ("the application scope hacks break the main application, which a reload=true fixes. They seem to fight each other").

Problem

The web test runner swaps the live application configuration globally, in place, for the duration of a test request:

  • vendor/wheels/tests/runner.cfm:36-38 — backs up application.wheels to application.$$$wheels, then mutates the live application.wheels that every concurrent request reads.
  • vendor/wheels/tests/runner.cfm:286-287 — restores and deletes the backup at end-of-response.
  • vendor/wheels/Global.cfc:4068 $restoreTestRunnerApplicationScope() + the hooks in events/EventMethods.cfc:4,305 and the flag at events/init/views.cfm:41 exist precisely because this swap can be left half-applied (aborts, errors, timeouts) — the recovery hook is an admission of the fragility, not a fix for it.
  • Legacy twin: vendor/wheels/rocketunit_tests/Test.cfc:8,33-34.

Consequences:

  • Any real traffic hitting the app while a test request is in flight executes against test configuration (test datasource, test routes).
  • A failed restore leaves the app broken until ?reload=true — the exact "they fight each other" symptom from Running Wheels 4 in a subfolder - And figuring out tests (broken) #2887.
  • Subfolder deployments don't cause this; they just make it easier to trip over (per-app paths make a stale restore more visible).

Proposed direction

Replace the global swap with a request-scoped overlay: resolve the effective config per request (e.g. a request.wheels.configOverlay consulted by the config readers, or a composed view over the application struct) so test requests see test config while concurrent requests keep seeing live config, and there is nothing to restore — the overlay dies with the request.

Cross-engine cautions (this touches the hottest config-read paths):

  • Config reads happen everywhere; the overlay check must be near-free on the non-test path.
  • No function members on application scope (Adobe), no closures capturing this across scopes — see CLAUDE.md Cross-Engine Invariants.
  • The $restoreTestRunnerApplicationScope() machinery and application.$$$wheels become removable once the overlay lands — delete them in the same PR so the old path can't half-engage.

Acceptance

  • A test request running concurrently with a normal request never changes what the normal request reads.
  • Killing a test request mid-run (abort/timeout) requires no recovery hook and no reload=true.
  • /wheels/app/tests works under a subpath-mounted app (ties back to Running Wheels 4 in a subfolder - And figuring out tests (broken) #2887's setup).
  • The $$$wheels backup/restore and recovery hooks are removed.

Refs #2887. Follow-up to #2985 (phase 1).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    refactorInternal refactor; no user-facing behavior change intended

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions