package proxy import ( "context" "net/http" "net/http/httptest" "sync/atomic" "testing" _ "git.unkin.net/unkin/artifactapi/internal/provider/rpm" "git.unkin.net/unkin/artifactapi/pkg/models" ) // changingUpstream serves every path with the current revision, as a mirror // does after a sync replaces its repodata. func changingUpstream(t *testing.T) (*httptest.Server, *atomic.Value) { t.Helper() var rev atomic.Value rev.Store("rev1") srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { v := rev.Load().(string) w.Header().Set("ETag", `"`+v+`"`) _, _ = w.Write([]byte(v + ":" + r.URL.Path)) })) t.Cleanup(srv.Close) return srv, &rev } func fetchBody(t *testing.T, r models.Remote, path string) string { t.Helper() res, err := testEngine.Fetch(context.Background(), r, path, prov(t, models.PackageRPM)) if err != nil { t.Fatalf("fetch %s: %v", path, err) } return readAll(t, res) } func rpmRemote(t *testing.T, name, baseURL string) models.Remote { return seed(t, models.Remote{Name: name, PackageType: models.PackageRPM, RepoType: models.RepoTypeRemote, BaseURL: baseURL, MutableTTL: 7200, CheckMutable: true}) } func TestEvictMutableIndexRefetches(t *testing.T) { requireStack(t) srv, rev := changingUpstream(t) r := rpmRemote(t, "evict-idx", srv.URL) const path = "8/Everything/x86_64/repodata/repomd.xml" if got := fetchBody(t, r, path); got != "rev1:/"+path { t.Fatalf("initial fetch = %q", got) } rev.Store("rev2") if got := fetchBody(t, r, path); got != "rev1:/"+path { t.Fatalf("within TTL = %q, want cached rev1", got) } if err := testEngine.Evict(context.Background(), r.Name, path); err != nil { t.Fatalf("evict: %v", err) } if got := fetchBody(t, r, path); got != "rev2:/"+path { t.Fatalf("after evict = %q, want rev2", got) } } func TestEvictWildcardClearsPrefixOnly(t *testing.T) { requireStack(t) srv, rev := changingUpstream(t) r := rpmRemote(t, "evict-wild", srv.URL) const ( repomd = "8/Everything/x86_64/repodata/repomd.xml" rpm = "8/Everything/x86_64/Packages/a/a-1.0-1.el8.x86_64.rpm" other = "9/Everything/x86_64/repodata/repomd.xml" ) for _, p := range []string{repomd, rpm, other} { fetchBody(t, r, p) } rev.Store("rev2") if err := testEngine.Evict(context.Background(), r.Name, "8/Everything/x86_64/*"); err != nil { t.Fatalf("evict: %v", err) } if got := fetchBody(t, r, repomd); got != "rev2:/"+repomd { t.Errorf("index under prefix = %q, want rev2", got) } if got := fetchBody(t, r, rpm); got != "rev2:/"+rpm { t.Errorf("artifact under prefix = %q, want rev2", got) } if got := fetchBody(t, r, other); got != "rev1:/"+other { t.Errorf("path outside prefix = %q, want cached rev1", got) } }