Skip to content

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

@bpamiri

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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    refactorInternal refactor; no user-facing behavior change intended

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions