Skip to content

test: share the same-answer refusal check and fold the saved repository provisioning cases - #3738

Merged
freeqaz merged 1 commit into
mainfrom
test-deslop-1026d
Oct 26, 2026
Merged

freeqaz merged 1 commit into
mainfrom
test-deslop-1026d

Conversation

@freeqaz

@freeqaz freeqaz commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator

Problem

The finding 2536 slices (#3725, #3732, #3735) and #3726 were written in parallel, and each added its own copy of the same test patterns:

  • Missing versus unreadable: five hand-written loops sent one refused request for an existing ID and a missing one, hid each answer's own ID and compared the answers. Each copy built the comparison slightly differently.
  • Error to answer: protected-source-refusals.mjs and credential-source-occ each had a local function that turns a thrown error into the API's status, code and message. One credential-source-occ check called requestFailure twice for one error, and one returned a bare true/false to assert.rejects, so a failure said nothing about the answer it got.
  • Provisioning fixture: four postgres-agent-provisioning tests built the same repository policy, Kubernetes topology and second fixture by hand (about 25 lines each), and three of them polled the work row for its error the same way. The saved-access test from fix(api): name saved repository, Credential Proxy deploy and protected source refusals #3732 and the older topology-change test (finding 1145) are the same scenario with a different change after admission, and each built a fresh Namespace per case.
  • Pasted sentences: "Agent provisioning could not complete." (6 copies) and the Compute topology refusal (2 copies) were not in refusal-text.mjs.

Change

Test-only. No product file changes and no assertion is weakened.

  • New tests/helpers/refusal-answers.mjs:
    • assertSameAnswer(send, ids, { status, label }) sends one request per ID and requires the first answer to have the expected status (403 by default), so two identical successes or two not-founds cannot pass. Every other answer must match it exactly once each answer's own ID is hidden. It accepts the three response shapes the tests use (error, body.error, or a flat answer).
    • refusedAnswer(work, options) is the shared error-to-answer mapping. It fails when the work succeeds.
  • Converted: 9 assertSameAnswer calls replace the 5 loops in credential-source-occ (update, rotate, delete, create), repository-credentials-admission (PATCH, deploy, Agent create, provisioning), openshell-device-authorization-api and protected-source-refusals. refusedAnswer replaces the fixture's answer, the bare true/false check and the withdrawal loop's inline mapping.
  • Provisioning: repositoryProvisioningFixture, repositoryProvisioningBody and workerFailure replace the hand-built setup in 4 tests. The Compute-without-repositories, withdrawn-policy and topology-change cases are now one table in one test. Each case still admits its own job, makes its own change, and checks the status. The topology case also still checks the retry answer. They share one Namespace and fixture, and each case restores the Drivers first. Composed fixtures go from 6 to 2 and Namespace bootstraps from 3 to 1. The topology case also gains the status-endpoint check that the other two had.
  • Refusal text: COMPUTE_TOPOLOGY_REPOSITORY_UNSUPPORTED and PROVISIONING_NOT_COMPLETED are added at the end of refusal-text.mjs. They replace 8 pasted copies in the two files this PR touches.

Left alone on purpose:

  • The unused-source withdrawal check exists both in credential-source-occ (Gateway source, controller) and in protected-source-refusals (Proxy-owned source, HTTP). Those are different setups.
  • The two cross-Namespace Secret checks reach different product sites: prepared issuer and Proxy create.
  • The broker-proxy tables cover Agent save and provisioning separately.
  • The older same-answer checks in occ-api and configuration-controller compare whole error objects or successes, which the helper does not model.

Diff: 8 files, +249/−309 (51 of the added lines are the new helper).

Verification

  • Pins on a remote test VM:
    • credential-source-occ, repository-credentials-admission, openshell-device-authorization-api and protected-source-refusals passed 20/20 at 2 CPUs, 99 tests per run.
    • postgres-agent-provisioning passed 20/20 at 2 CPUs, with a fresh database per run (57 tests).
  • Mutants: 7 of 7 killed.
    • The helper fails when a site leaks:
      • Echo: an existing credential source's denial names the Secret it binds. This fails the update check.
      • Lookup first: the device-login Secret, the credential-free Agent, and Agent create's Namespace are each read before the caller's grant. This fails the device-login, protected-source and Agent-create checks, which cover all three response shapes.
    • Each folded provisioning case still fails on its own:
      • The Compute refusal is no longer named in the status.
      • The saved-selection refusal is no longer named.
      • The topology refusal's text passes through to the status.
  • Static checks: run-tests.mjs audit, eslint, prettier and tsc --build pass.
  • Timing: the folded provisioning test takes 0.72 s, where the two tests it replaces took 1.19 s (0.81 s + 0.38 s, one run each on the remote VM). The worker test (0.92 s versus 1.06 s) and the Sandbox test (0.40 s versus 0.41 s) are unchanged.

Risks

Low; tests only. The folded provisioning cases share a Namespace. Each admits a separate job, and failed jobs are permanent, so no case can pick up another's work. A restore that leaked between cases would fail a later case; it would not hide a failure.

…ry provisioning cases

assertSameAnswer replaces five hand-written missing-versus-unreadable comparisons, and
refusedAnswer replaces two local copies of the error-to-answer mapping. The three saved
repository access provisioning cases share one fixture, body and worker-failure helper.
@freeqaz
freeqaz requested a review from a team as a code owner October 26, 2026 08:57
@clawsweeper

clawsweeper Bot commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

@freeqaz
freeqaz merged commit 7ff4f6f into main Oct 26, 2026
38 checks passed
@freeqaz
freeqaz deleted the test-deslop-1026d branch October 26, 2026 09:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant