test(image): cover ACR referrer discovery at the regctl boundary - #84
test(image): cover ACR referrer discovery at the regctl boundary#84johnsonshi wants to merge 3 commits into
Conversation
Follow-up to the review on kvcache-ai#58, which noted that coverage started at `parse_overlaybd_referrer`, leaving the referrer *query* unverified: reintroducing `--filter-artifact-type` to `regctl artifact list` would pin discovery to a single artifactType and silently drop ACR streaming referrers while every parse-level test stayed green. Add a fake `regctl` that records its argv and replays a canned response, then assert `discover_overlaybd_referrer` lists referrers unfiltered and returns the ACR referrer. Confirmed by mutation: reintroducing the filter flag leaves all seven `parse_overlaybd_referrer` tests green and fails only the new test. Also cover the regctl failure path, which had no test: a registry error must surface as an error rather than `Ok(None)`, which would silently downgrade to a local pull-and-convert. Use literal artifactType wire values in the fixtures instead of the implementation constants, so an unintended edit to a constant is caught instead of being mirrored into the fixture, and pin both constants and their preference order in a dedicated test. Add a multi-arch case taken from a real ACR response: ACR attaches one streaming referrer per platform, all sharing the same artifactType, so several matches is the normal case for a multi-arch subject rather than an oddity.
|
✅ OpenCodeReview: No comments generated. Looks good to me. |
| assert_eq!( | ||
| parse_overlaybd_referrer(&body.to_string()).expect("parse"), | ||
| Some(( | ||
| "sha256:1bdbcce5b02202d0c4c204da05e6ffbb8605bb178f441ff2990b9924c046a69f" | ||
| .to_string(), | ||
| "application/vnd.azure.artifact.streaming.v1" | ||
| )) | ||
| ); |
There was a problem hiding this comment.
[bug · medium]
This test codifies manifest-order selection even though the descriptors identify different platforms. try_resolve_overlaybd_referrer already has the requested arch, but discovery/parsing does not receive it, and the selected referrer manifest is not subsequently checked against its streaming.platform.* annotations. If ACR returns these descriptors in the opposite order, an arm64 resolve can use the amd64 artifact (or vice versa). Pass the target platform into discovery/parsing and prefer the descriptor whose streaming.platform.os/streaming.platform.arch match it; add a test where the matching descriptor is not first.
| write!( | ||
| file, | ||
| "#!/bin/sh\nprintf '%s\\n' \"$@\" > '{argv}'\ncat '{stdout}'\ncat '{stderr}' >&2\nexit {exit_code}\n", | ||
| argv = argv_path.display(), | ||
| stdout = stdout_path.display(), | ||
| stderr = stderr_path.display(), | ||
| ) |
There was a problem hiding this comment.
[security · low]
These paths are inserted directly into single-quoted shell literals. A TMPDIR containing an apostrophe will break the generated script and can cause unintended shell interpretation, so the tests are fragile under a valid test environment configuration. Avoid interpolating paths into shell source: have the script derive its directory from $0 and access argv, stdout, and stderr relative to that directory (with normal double-quoted shell expansions), or use a helper that performs proper shell escaping.
…viour The per-platform fixture comment claimed the multi-referrer path is the normal case. Verifying against a live ACR registry shows otherwise: referrers queried on a multi-arch tag return one per platform, but `resolve_fetched_manifest` never passes a tag or index. It hands `FetchedManifest::selected_image_ref` to discovery, which oci_image pins to the platform-resolved manifest digest, and that subject carries exactly one referrer. Reword the comment so it documents the fixture as a defensive lock on first-match selection rather than the common path. No behaviour or assertion changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 78ecb58e-c794-4a64-acd3-e00d8e81cbea
| write!( | ||
| file, | ||
| "#!/bin/sh\nprintf '%s\\n' \"$@\" > '{argv}'\ncat '{stdout}'\ncat '{stderr}' >&2\nexit {exit_code}\n", | ||
| argv = argv_path.display(), | ||
| stdout = stdout_path.display(), | ||
| stderr = stderr_path.display(), | ||
| ) |
There was a problem hiding this comment.
[security · medium]
The fixture paths are inserted directly into single-quoted shell literals. TempDir is created beneath an externally controlled temporary directory, so a valid TMPDIR containing ' (or a newline) can break the generated script and potentially inject shell commands. Avoid embedding filesystem paths: have the script derive its directory from $0 and access the adjacent fixture files through quoted shell variables, as the existing shared fake-regctl fixture does.
Suggestion:
| write!( | |
| file, | |
| "#!/bin/sh\nprintf '%s\\n' \"$@\" > '{argv}'\ncat '{stdout}'\ncat '{stderr}' >&2\nexit {exit_code}\n", | |
| argv = argv_path.display(), | |
| stdout = stdout_path.display(), | |
| stderr = stderr_path.display(), | |
| ) | |
| write!( | |
| file, | |
| "#!/bin/sh\ndir=\"$(cd \"$(dirname \"$0\")\" && pwd)\"\nprintf '%s\\n' \"$@\" > \"$dir/argv\"\ncat \"$dir/stdout\"\ncat \"$dir/stderr\" >&2\nexit {exit_code}\n", | |
| ) |
The fake regctl script interpolated absolute fixture paths into single-quoted shell literals. TempDir is created beneath TMPDIR, so a TMPDIR containing an apostrophe or newline would break the generated script rather than fail cleanly. Derive the fixture directory from $0 inside the script and access argv, stdout and stderr through a quoted shell variable, so no filesystem path is embedded in shell source. This matches the fully static fake-helper script already used in the ACR client tests. Verified by running the resolver tests under TMPDIR="/tmp/it's a dir". Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 78ecb58e-c794-4a64-acd3-e00d8e81cbea
Summary
Follow-up for code quality on the review feedback in
#58 (review).
Both non-blocking suggestions from that review are addressed here. This PR changes no
production code — it is test-only.
1. Coverage now starts at the regctl boundary, not at the parser
The review noted that coverage started at
parse_overlaybd_referrer, so reintroducing--filter-artifact-typeto theregctl artifact listcommand would leave tests green whilebreaking ACR discovery.
discover_overlaybd_referrer_lists_referrers_unfiltered_and_finds_acr_streaminginstalls a fakeregctlthat records its argv and replays a canned referrers index, then asserts the listing isunfiltered and that the ACR referrer is returned.
I verified the test actually closes the gap by mutation — reintroducing the flag:
.arg("list") + .arg("--filter-artifact-type") + .arg(OVERLAYBD_NATIVE_ARTIFACT_TYPE) .arg("--format")All seven parse-level tests stay green; only the new test fails. That is exactly the regression
the review described.
The same fake-regctl harness also covers the failure path, which previously had no test: a
registry error must surface as an error rather than
Ok(None), sinceOk(None)would silentlydowngrade to a local pull-and-convert.
2. Fixtures use literal wire values
Fixtures now use the literal artifactType strings rather than the implementation constants, so an
unintended edit to a constant is caught instead of being mirrored into the fixture.
overlaybd_referrer_artifact_types_match_published_wire_valuesadditionally pins both constantsand their preference order, so a typo fails with a readable diff rather than only surfacing as a
missed referrer.
3. Fake regctl fixtures are located relative to
$0The fake
regctlscript originally interpolated absolute fixture paths into single-quoted shellliterals.
TempDiris created beneathTMPDIR, so aTMPDIRcontaining an apostrophe or newlinewould break the generated script rather than fail cleanly.
The script now derives its own directory from
$0and reachesargv,stdoutandstderrthrough a quoted shell variable, so no filesystem path is embedded in shell source. This matches
the fully static fake-helper script already used in the ACR client tests
(
snapshot::repository::backends::common::acr::client). Verified by running the resolver testsunder
TMPDIR="/tmp/it's a dir".Wire format verified against a real registry
Rather than trusting the fixture, I re-derived it from a live ACR registry with the same command
the code issues:
{ "schemaVersion": 2, "mediaType": "application/vnd.oci.image.index.v1+json", "manifests": [ { "digest": "sha256:1bdbcce5...", "artifactType": "application/vnd.azure.artifact.streaming.v1", "annotations": { "streaming.format": "overlaybd", "streaming.version": "v1", "streaming.platform.os": "linux", "streaming.platform.arch": "amd64" } }, { "digest": "sha256:3a5ae954...", "artifactType": "application/vnd.azure.artifact.streaming.v1", "annotations": { "streaming.format": "overlaybd", "streaming.version": "v1", "streaming.platform.os": "linux", "streaming.platform.arch": "arm64" } } ] }The artifactType literal matches byte-for-byte, so the fixture is faithful.
On platform selection, measured against the same registry:
regctl artifact liststreamtest:v1— multi-arch tag, resolves to an indexamd64+arm64streamtest@sha256:c4116d4d…— thelinux/amd64childamd64onlyresolve_fetched_manifestpassesfetched.selected_image_refinto discovery, andoci_imagepins that to the platform-resolved manifest digest via
image_ref_with_digest(¤t_ref, &manifest_digest). Discovery therefore never receives anindex, and the subject it does receive carries exactly one referrer, for the right architecture.
parse_overlaybd_referrer_selects_first_of_acr_per_platform_referrerskeeps the two-referrerpayload as a defensive lock on first-match selection.
The discovery path these tests cover was also exercised end to end against a live Premium ACR
registry and an AKS cluster, where a sandbox booted from an ACR artifact-streaming image — though
that exercises the production change from #58 rather than anything in this test-only PR.
Test results
cargo fmt --checkclean,cargo clippy --all-targets -- -D warningsclean.origin/main(8174bd9)The 3 failures are pre-existing and identical on unmodified
main(snapshot::p2p::tests::local_overlaybd_layers_*and
…::acr::source_image::tests::plans_descriptorless_sparse_overlaybd_delta_for_dense_export);they appear environment-specific to my aarch64 container and are unrelated to this change. Net
+4tests, no regressions.