test(e2e): a container upstream stub, and the 7 oci remote rows it covers
What this adds
A programmable container upstream stub, a raw container blob reader, and the 7 rows of the OCI catalog's remote group they cover. Catalog coverage goes 112 → 119 on top of the maven branch.
e2e/internal/upstream/ociupstream, mirroringnpmupstream: programmable blob responses, per-method request recording, and the failure modes the rows need — a digest the upstream does not carry, bytes that miss their digest, an unreachable host.- A raw container blob reader on
registry.Client, forGET/HEADwith arbitrary request headers. The only raw container HTTP in the tree wasManifestFraming, which is manifest-only; nothing could send aRangeor readDocker-Content-Digestoff a blob response. - 7 rows:
blob-cold-miss,blob-cold-head,blob-range-on-miss,blob-upstream-missing,blob-upstream-unreachable,blob-digest-mismatch, andwrite-rejected.
A harness defect this fixes
registry.Client.CreateRemoteRepository could not create a container remote at all.
It always sent metadata_cache_validity_hours, which CreateContainerRemoteSettingsRequest
does not declare and refuses under additionalProperties: false, against a server
decoding settings per family with DisallowUnknownFields — a 400 on every OCI and
docker remote create. The body is now picked per family. Nothing depended on the broken
path, so no existing row changes.
Four rows refused, not narrowed
Each is indexed in docs/testing/e2e/limitations.md.
| Row | Why |
|---|---|
blob-cache-hit, blob-range-unsatisfiable |
Each cell specifies a redirect-delivery arm. The rig cannot serve one — its object store is an in-cluster ClusterIP with no ingress — and namespaces.delivery_mode_override has no writer. The proxy arm of each is drivable; a row narrowed to it would read as covering a cell that names two modes. |
credential-never-served |
The container arm sends a stored credential only on the Docker token exchange, and the realm scheme is unconditionally https. The rig terminates no TLS, so no stub realm this suite can serve will be used. |
blob-unhealthy-remote |
Reachable only with a shorter health-sweep interval templated into the rig; at the shipped 5-minute interval and threshold of 3 it takes 15 minutes to mark a remote unhealthy. |
blob-range-unsatisfiable is blocked twice over: its no-download clause has no read at
all, which is its own entry.
delete-artifact is not here, and why
e2e.oci.lifecycle.delete-artifact stays not started. Its referrers clause specifies
that a deleted subject's referrers stop listing it, and they do not —
#1005 has the rig
reproduction. The pull-by-digest and pull-by-tag assertions are real coverage nothing
else has, so they live in e2e/bootstrap/harness/manifest_delete_test.go declaring no
scenario id, alongside the existing "prove the capability the catalog's rows will be
written on" tests in that surface. Its pattern entry is removed, so authorable does
not advertise a row whose next writer would land on the defect.
Reviewable LOC
11 files, +1,575/−38.
| Group | + |
|---|---|
ociupstream and its unit tests |
542 |
e2e/bootstrap/ rows, the harness-surface test and suite.go |
584 |
registry.Client and its tests |
275 |
docs (limitations.md, oci.md) |
102 |
patterns.go |
72 |
Past 500. The stub has no consumer until the rows land and the rows cannot be split from
patterns.go and oci.md without an intermediate commit that fails check, so the
useful cut is the one the commit sequence gives: reader, stub, rows.
Verification
e2e-catalog check: 0 disagreements.go build -tags=e2e ./e2e/...,go test ./e2e/...: pass.golangci-lint --build-tags=e2eat the pinned 2.13.2: 0 issues.check-comment-caps.sh --base origin/main: OK.
The rows are unverified against a live caproni rig. The stub has unit tests; every assertion about Artifact Registry's own responses is unexercised.