Watch
1
0
Fork
You've already forked pkg-proxy
1
mirror of https://github.com/git-pkgs/proxy.git synced 2026-11-09 07:39:19 -05:00
pkg-proxy/internal/mirror/image_test.go

190 lines
6.1 KiB
Go

package mirror
import (
"context"
"errors"
"reflect"
"strings"
"sync"
"testing"
"github.com/git-pkgs/proxy/internal/denylist"
"github.com/git-pkgs/proxy/internal/handler"
)
func TestImageRefFromPURL(t *testing.T) {
const digest = "sha256:1111111111111111111111111111111111111111111111111111111111111111"
tests := []struct {
purl string
platforms []string
wantRef handler.ImageRef
wantPlatforms []handler.Platform
wantErr string
}{
{
purl: "pkg:docker/library/alpine@3.20",
wantRef: handler.ImageRef{Name: "library/alpine", References: []string{"3.20"}},
},
{
purl: "pkg:docker/ghcr.io/team/app@1.0",
wantRef: handler.ImageRef{Registry: "ghcr.io", Name: "team/app", References: []string{"1.0"}},
},
{
purl: "pkg:docker/registry.example:5000/team/app@" + digest,
wantRef: handler.ImageRef{Registry: "registry.example:5000", Name: "team/app", References: []string{digest}},
},
{
purl: "pkg:docker/localhost/app@1.0",
wantRef: handler.ImageRef{Registry: "localhost", Name: "app", References: []string{"1.0"}},
},
{
purl: "pkg:docker/localhost:5000/team/app@1.0",
wantRef: handler.ImageRef{Registry: "localhost:5000", Name: "team/app", References: []string{"1.0"}},
},
{
purl: "pkg:docker/alpine@3.20?repository_url=ghcr.io",
platforms: []string{"linux/arm64/v8"},
wantRef: handler.ImageRef{Registry: "ghcr.io", Name: "alpine", References: []string{"3.20"}},
wantPlatforms: []handler.Platform{{OS: "linux", Architecture: "arm64", Variant: "v8"}},
},
{
purl: "pkg:docker/app@1.0?repository_url=https://registry.example/team",
wantRef: handler.ImageRef{Registry: "registry.example", Name: "team/app", References: []string{"1.0"}},
},
{
purl: "pkg:oci/debian@" + digest + "?repository_url=docker.io/library/debian&tag=bookworm&arch=arm64",
wantRef: handler.ImageRef{Registry: "docker.io", Name: "library/debian", References: []string{digest, "bookworm"}},
wantPlatforms: []handler.Platform{{Architecture: "arm64"}},
},
{
purl: "pkg:oci/debian@" + digest + "?repository_url=docker.io/library/debian&arch=arm64",
platforms: []string{"linux/amd64"},
wantRef: handler.ImageRef{Registry: "docker.io", Name: "library/debian", References: []string{digest}},
wantPlatforms: []handler.Platform{{OS: "linux", Architecture: "amd64"}},
},
{
purl: "pkg:oci/debian@" + digest,
wantErr: "repository_url",
},
}
for _, tt := range tests {
t.Run(tt.purl, func(t *testing.T) {
var items []PackageVersion
source := &PURLSource{PURLs: []string{tt.purl}, Platforms: tt.platforms}
if err := source.Enumerate(context.Background(), func(pv PackageVersion) error {
items = append(items, pv)
return nil
}); err != nil {
t.Fatalf("Enumerate: %v", err)
}
if len(items) != 1 {
t.Fatalf("items = %d, want 1", len(items))
}
ref, platforms, err := imageRef(items[0])
if tt.wantErr != "" {
if err == nil || !strings.Contains(err.Error(), tt.wantErr) {
t.Fatalf("err = %v, want %q", err, tt.wantErr)
}
return
}
if err != nil {
t.Fatalf("imageRef: %v", err)
}
if !reflect.DeepEqual(ref, tt.wantRef) {
t.Errorf("ref = %+v, want %+v", ref, tt.wantRef)
}
if !reflect.DeepEqual(platforms, tt.wantPlatforms) {
t.Errorf("platforms = %+v, want %+v", platforms, tt.wantPlatforms)
}
})
}
}
func TestUnversionedImagePURLIsNotExpanded(t *testing.T) {
var items []PackageVersion
source := &PURLSource{PURLs: []string{"pkg:docker/library/alpine"}}
if err := source.Enumerate(context.Background(), func(pv PackageVersion) error {
items = append(items, pv)
return nil
}); err != nil {
t.Fatalf("Enumerate: %v", err)
}
if len(items) != 1 || items[0].Version != "" {
t.Fatalf("items = %+v, want one unversioned item", items)
}
}
type fakeImages struct {
mu sync.Mutex
refs []handler.ImageRef
result handler.ImageResult
err error
}
func (f *fakeImages) MirrorImage(_ context.Context, ref handler.ImageRef, _ []handler.Platform) (handler.ImageResult, error) {
f.mu.Lock()
defer f.mu.Unlock()
f.refs = append(f.refs, ref)
return f.result, f.err
}
func TestMirrorRunCountsImages(t *testing.T) {
tests := []struct {
name string
result handler.ImageResult
err error
wantCompleted int64
wantSkipped int64
wantFailed int64
}{
{name: "fetched", result: handler.ImageResult{Fetched: 3, Bytes: 42}, wantCompleted: 1},
{name: "cached", result: handler.ImageResult{}, wantSkipped: 1},
{name: "failed", err: errors.New("boom"), wantFailed: 1},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
m := setupTestMirror(t, 1)
images := &fakeImages{result: tt.result, err: tt.err}
m.Images = images
progress, err := m.Run(context.Background(), &PURLSource{PURLs: []string{"pkg:docker/library/alpine@3.20"}})
if err != nil {
t.Fatalf("Run: %v", err)
}
if progress.Completed != tt.wantCompleted || progress.Skipped != tt.wantSkipped || progress.Failed != tt.wantFailed {
t.Errorf("progress = %+v", progress)
}
if progress.Bytes != tt.result.Bytes {
t.Errorf("bytes = %d, want %d", progress.Bytes, tt.result.Bytes)
}
if len(images.refs) != 1 || images.refs[0].Name != "library/alpine" {
t.Errorf("refs = %+v", images.refs)
}
})
}
}
func TestMirrorRunDeniedImage(t *testing.T) {
m := setupTestMirror(t, 1)
policy, err := denylist.New([]string{"pkg:docker/library/alpine@3.20"})
if err != nil {
t.Fatal(err)
}
m.proxy.Denylist = policy
images := &fakeImages{}
m.Images = images
progress, err := m.Run(context.Background(), &PURLSource{PURLs: []string{"pkg:docker/library/alpine@3.20"}})
if err != nil {
t.Fatalf("Run: %v", err)
}
if progress.Failed != 1 || len(images.refs) != 0 {
t.Errorf("denied image: failed = %d, mirror calls = %d", progress.Failed, len(images.refs))
}
}
func TestJobRequestRejectsInvalidPlatform(t *testing.T) {
js := &JobStore{}
if _, err := js.sourceFromRequest(JobRequest{PURLs: []string{"pkg:docker/library/alpine@3.20"}, Platforms: []string{"linux"}}); err == nil {
t.Error("invalid platform was accepted")
}
}