test(e2e): assert the counters a remote container fill moves
Adds the namespace-statistics client method the suite was missing, and asserts
every clause of e2e.oci.remote.fill-storage-counters that the rig can reach.
The row stays not started on purpose. Read the next section before the
diff — a test that lands without flipping its Status looks like an oversight and
is not one.
Why the Status does not move
Two of the row's six clause groups cannot be reached, so a test bearing the
scenario's exact name would make the catalog claim coverage it does not have.
README defines implemented as "the suite
contains a test with the scenario's exact name", so the way to assert real
substance without that claim is to declare no scenario id — the same shape
e2e/bootstrap/harness/npm_counters_test.go already uses.
| Clause group | Reachable | Why |
|---|---|---|
repository size_bytes, artifacts_count |
yes | lands on the counter drain, lowered to 2s in the rig, inside AwaitCounters' 30s bound |
namespace deduplicated_size_bytes, components_count |
yes, once this method exists | getNamespaceStatistics is live and wired |
| "a reconciliation pass then moves no counter" | no | 1h interval, the rig does not lower it, no RunOnStart, no API trigger. Recorded in #1282 (closed) |
| the re-tag clause | no | needs a cached tag to go stale, and cache_validity_hours is an integer with minimum: 0 where 0 means never revalidate — so the smallest revalidating window is one hour |
That last one is a new finding: it is the cache-age floor, a different limitation from the reconciliation one, and neither #1282 (closed) nor the investigation that preceded this MR identified it as reaching this row.
Narrowing the cell to drop both clauses would let the Status move, and narrowing a cell is an operator decision rather than this MR's to take. If that decision lands, flipping is a one-commit change from here.
What this adds
| File | Change |
|---|---|
e2e/internal/registry/registry.go |
NamespaceStatistics type, wire struct, and Client.NamespaceStatistics |
e2e/internal/registry/registry_test.go |
four unit tests for it |
e2e/bootstrap/counters.go |
repository and namespace read/await/hold pairs over an awaitCounters and a countersAfterHold generic, which the pre-existing helpers now delegate to as well |
e2e/bootstrap/oci/remote_counters_test.go |
the test |
Neither deduplicated_size_bytes nor components_count appeared anywhere under
e2e/ before this, so the namespace half of every counter row was unreadable.
Field names and shapes were confirmed against api/openapi/v1.yaml.
The row's counter arithmetic was re-derived clause by clause against
internal/format/oci/remote_fill_emit.go rather than taken from the row text,
because the row asserts which counts move and which do not, and a wrong
"moves neither" passes vacuously.
Why namespace assertions are sound here
Harness.NewFixture derives a slug per test from names.For(testName) and
seeds its own namespace ((*Harness).NewFixture in
e2e/internal/hosted/hosted.go — the target merge moved it there out of
e2e/bootstrap/harness.go, which now aliases bootstrap.Fixture to
hosted.Fixture), so the bootstrap
profile does not share one namespace. That is the opposite of the authz
profile, where DefaultOrganizationStrategy is SharedOrganization and a
namespace-scoped assertion would see another test's writes.
The test lives in e2e/bootstrap/oci/ rather than harness/ — the usual home
for no-scenario-id tests — because the mirror machinery it needs
(manifestMirror, readManifest, readBlob) lives in oci_test, and copying
it would violate the warning in counters.go's own header about two copies
drifting.
One inconsistency left out of scope
api/openapi/v1.yaml's endpoint-level prose says the stored namespace figures
"follow that pass rather than the live count", while the schema says the drain
writes them and reconciliation only corrects a lag. The schema is what the code
does; the endpoint prose is misleading. Fixing it is not this MR's job.
Verification
| Gate | Result |
|---|---|
e2e-catalog generate -check |
exit 0 |
e2e-catalog check |
disagreements 0; 211 / 185 / 154 and authorable 0, all unchanged by design |
go vet -tags=e2e ./e2e/... |
exit 0 (the compile gate; go build skips _test.go) |
go test -tags=e2e -run XXX -exec /bin/true ./e2e/... |
exit 0, builds and links |
go test ./e2e/internal/registry/... |
ok |
golangci-lint run --build-tags=e2e (pinned 2.13) |
0 issues. |
scripts/ci/check-comment-caps.sh |
OK |
No Markdown is touched, so no vale or markdownlint run applies.
What a rig run still has to prove
No rig was available. The four counter deltas, the refetch hold, and the per-tick pairing assumption are unverified against a live drain. Compilation, linking, linting and the unit tests all pass.