Skip to content

test runner silently falls back to the FULL suite when directory= fails the allowlist (and reports green 0-bundle runs for single-file values) #3083

Description

@bpamiri

Summary

Both test-runner endpoints accept directory= and validate it against an allowlist regex (core: ^(wheels\.tests|vendor\.<pkg>\.tests)(\.\w+)*$ in vendor/wheels/tests/runner.cfm:122-135; the app runner has an equivalent ^tests(\.\w+)*$ shape). When the value fails the regex, the runner silently substitutes the default root and runs the entire suite. When the value passes but names a spec FILE, TestBox discovers 0 bundles and reports green.

Repro (Lucee 7 + SQLite core endpoint, develop)

  • GET /wheels/core/tests?db=sqlite&format=json&directory=tests.specs.model → 314 bundles / 4420 passes (full core suite) with no indication anything was rejected — this exact example appears in testing/index.mdx, where the reader asked for "just the model specs" and got a multi-minute full run that looks like a green model run.
  • Correct value directory=wheels.tests.specs.model → 48 bundles / 893 passes.
  • directory=wheels.tests.specs.model.callbacksSpec (single file) → 0 bundles, 0 specs, green — the inverse trap. testBundles= is the working single-file filter (→ 43 passes, just that bundle).

The CLI already works around the first trap client-side ($normalizeTestFilter, whose comment notes the runners "silently fall back to the default scope, running the entire suite"), but anyone driving the URL directly — which the docs recommend for the inner loop — gets no signal.

Proposed direction

When url.directory is present but rejected by the allowlist, or accepted but discovers 0 bundles:

  1. include directoryRequested / directoryResolved / bundlesDiscovered fields in the JSON payload, and
  2. either respond 400, or at minimum emit a warnings array entry — so humans and CI scripts can detect the mismatch instead of trusting a green total from the wrong scope.

Defense-in-depth allowlisting stays unchanged; this only adds visibility. Docs-side example fixes (correct directory= shapes; testBundles= for single files) ride the guide-audit docs wave.

Acceptance

  • A rejected directory= is detectable from the response (status or explicit fields/warnings) on both core and app runners.
  • A 0-bundle discovery is distinguishable from a passing run.
  • Specs cover both shapes.

Not a duplicate of #3025 (application-scope mutation) — this is request-scoped input handling.

Reported by the guide-behavioral-audit P1 batch 2 (work item p1-15-testing, claims IDX-07/RUN-06; live on the Lucee 7 docker harness).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions