From 0845149e71f89c81b4a0573fa03d05843cd4434f Mon Sep 17 00:00:00 2001 From: "devsy-app[bot]" <277138668+devsy-app[bot]@users.noreply.github.com> Date: Thu, 13 Aug 2026 11:05:41 +0000 Subject: [PATCH 1/3] test(image): cover isACRRegistry + ACR helper edges Add edge-case tests for pkg/image ACR credential handling. isACRRegistry was at 0% coverage; cover its regex (all 4 azure TLDs, mcr.microsoft.com), port-suffixed hosts, apex/wrong-TLD/lookalike rejections, and empty input. Also assert the ACR cred helper rejects non-ACR registries locally (no network), and that Add/Delete/List report unimplemented. Package coverage 17.7% -> 23.4%. --- pkg/image/acr_test.go | 80 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 pkg/image/acr_test.go diff --git a/pkg/image/acr_test.go b/pkg/image/acr_test.go new file mode 100644 index 000000000..44fcbee19 --- /dev/null +++ b/pkg/image/acr_test.go @@ -0,0 +1,80 @@ +package image + +import ( + "strings" + "testing" + + "github.com/docker/docker-credential-helpers/credentials" +) + +func TestIsACRRegistry(t *testing.T) { + tests := []struct { + name string + input string + want bool + }{ + {"azurecr.io suffix", "myacr.azurecr.io", true}, + {"azurecr.cn suffix", "myacr.azurecr.cn", true}, + {"azurecr.de suffix", "myacr.azurecr.de", true}, + {"azurecr.us suffix", "myacr.azurecr.us", true}, + {"mcr microsoft", "mcr.microsoft.com", true}, + {"with port", "foo.azurecr.io:443", true}, + {"docker hub", "docker.io", false}, + {"ghcr", "ghcr.io", false}, + {"bare azurecr.io apex", "azurecr.io", false}, + {"wrong tld", "myacr.azurecr.com", false}, + {"lookalike suffix", "notazurecr.io", false}, + {"empty", "", false}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + if got := isACRRegistry(tc.input); got != tc.want { + t.Errorf("isACRRegistry(%q) = %v, want %v", tc.input, got, tc.want) + } + }) + } +} + +// Get must reject non-ACR registries without touching the network or Azure +// credentials, so a misrouted server URL surfaces a clear local error. +func TestACRCredHelper_GetRejectsNonACRRegistry(t *testing.T) { + helper := newACRCredentialsHelper() + user, pass, err := helper.Get("docker.io") + if err == nil { + t.Fatal("expected error for non-ACR registry, got nil") + } + if !strings.Contains(err.Error(), "Azure Container Registry") { + t.Errorf("expected error to mention Azure Container Registry, got: %v", err) + } + if user != "" || pass != "" { + t.Errorf("expected empty credentials, got user=%q pass=%q", user, pass) + } +} + +// Add/Delete/List are read-only-store operations ACR exchange auth does not +// support; they must report unimplemented rather than silently succeeding. +func TestACRCredHelper_UnimplementedMutations(t *testing.T) { + helper := newACRCredentialsHelper() + + if err := helper.Add(&credentials.Credentials{}); err == nil { + t.Fatal("expected error from unimplemented Add, got nil") + } + if err := helper.Delete("myacr.azurecr.io"); err == nil { + t.Fatal("expected error from unimplemented Delete, got nil") + } + got, err := helper.List() + if err == nil { + t.Fatal("expected error from unimplemented List, got nil") + } + if got != nil { + t.Errorf("expected nil map from List, got %v", got) + } +} + +// newACRCredentialsHelper returns a value satisfying credentials.Helper. +func TestNewACRCredentialsHelperSatisfiesInterface(t *testing.T) { + var helper credentials.Helper = newACRCredentialsHelper() + if helper == nil { + t.Fatal("expected non-nil credentials.Helper") + } +} From 5663899233e1c8fd07e8c90decb2aa261123d16d Mon Sep 17 00:00:00 2001 From: "devsy-app[bot]" <277138668+devsy-app[bot]@users.noreply.github.com> Date: Thu, 13 Aug 2026 16:36:06 +0000 Subject: [PATCH 2/3] style(image): drop redundant type in test decl Use a short variable declaration in TestNewACRCredentialsHelperSatisfiesInterface; newACRCredentialsHelper already returns credentials.Helper, so the explicit type is redundant (staticcheck ST1023). Lint fix only; no behavior change. This commit was created by an AI agent (OpenHands) on behalf of the user. --- pkg/image/acr_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/image/acr_test.go b/pkg/image/acr_test.go index 44fcbee19..aa3f798b2 100644 --- a/pkg/image/acr_test.go +++ b/pkg/image/acr_test.go @@ -73,7 +73,7 @@ func TestACRCredHelper_UnimplementedMutations(t *testing.T) { // newACRCredentialsHelper returns a value satisfying credentials.Helper. func TestNewACRCredentialsHelperSatisfiesInterface(t *testing.T) { - var helper credentials.Helper = newACRCredentialsHelper() + helper := newACRCredentialsHelper() if helper == nil { t.Fatal("expected non-nil credentials.Helper") } From e2c1e468bf3c973089ed8eecc71e71b87773ca91 Mon Sep 17 00:00:00 2001 From: Samuel K Date: Thu, 13 Aug 2026 21:32:00 -0500 Subject: [PATCH 3/3] chore: cleanup comments --- pkg/image/acr_test.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pkg/image/acr_test.go b/pkg/image/acr_test.go index aa3f798b2..41cb8b7e1 100644 --- a/pkg/image/acr_test.go +++ b/pkg/image/acr_test.go @@ -35,8 +35,6 @@ func TestIsACRRegistry(t *testing.T) { } } -// Get must reject non-ACR registries without touching the network or Azure -// credentials, so a misrouted server URL surfaces a clear local error. func TestACRCredHelper_GetRejectsNonACRRegistry(t *testing.T) { helper := newACRCredentialsHelper() user, pass, err := helper.Get("docker.io") @@ -51,8 +49,6 @@ func TestACRCredHelper_GetRejectsNonACRRegistry(t *testing.T) { } } -// Add/Delete/List are read-only-store operations ACR exchange auth does not -// support; they must report unimplemented rather than silently succeeding. func TestACRCredHelper_UnimplementedMutations(t *testing.T) { helper := newACRCredentialsHelper() @@ -71,7 +67,6 @@ func TestACRCredHelper_UnimplementedMutations(t *testing.T) { } } -// newACRCredentialsHelper returns a value satisfying credentials.Helper. func TestNewACRCredentialsHelperSatisfiesInterface(t *testing.T) { helper := newACRCredentialsHelper() if helper == nil {