Watch
1
0
Fork
You've already forked pkg-proxy
1
mirror of https://github.com/git-pkgs/proxy.git synced 2026-11-09 15:49:16 -05:00
pkg-proxy/internal/handler/metadata_not_modified_test.go

112 lines
3.7 KiB
Go
Raw Permalink Normal View History

package handler
import (
"context"
"database/sql"
"net/http"
"net/http/httptest"
"sync/atomic"
"testing"
"time"
"github.com/git-pkgs/proxy/internal/database"
)
// TestMetadataNotModifiedKeepsStoredDocument checks that a 304 from upstream
// refreshes the cache row without writing the unchanged document to storage
// again, and still serves it.
func TestMetadataNotModifiedKeepsStoredDocument(t *testing.T) {
const body = `{"v":1}`
var notModified atomic.Int32
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set(headerETag, `"v1"`)
if r.Header.Get("If-None-Match") == `"v1"` {
notModified.Add(1)
w.WriteHeader(http.StatusNotModified)
return
}
w.Header().Set(headerContentType, contentTypeJSON)
_, _ = w.Write([]byte(body))
}))
t.Cleanup(upstream.Close)
proxy, db, store, _ := setupTestProxy(t)
proxy.CacheMetadata = true
proxy.MetadataTTL = time.Nanosecond // revalidate on every request
proxy.HTTPClient = upstream.Client()
ctx := context.Background()
first := proxy.fetchMetadataDocument(ctx, "test", "pkg", upstream.URL+"/pkg", contentTypeJSON, nil)
if first.err != nil {
t.Fatal(first.err)
}
stored, err := db.GetMetadataCache("test", "pkg")
if err != nil || stored == nil {
t.Fatalf("cache row after first fetch: %v, %v", stored, err)
}
for range 2 {
res := proxy.fetchMetadataDocument(ctx, "test", "pkg", upstream.URL+"/pkg", contentTypeJSON, nil)
if res.err != nil || string(res.body) != body || res.digest != first.digest {
t.Fatalf("revalidated fetch = %q, digest %q, err %v; want %q, digest %q", res.body, res.digest, res.err, body, first.digest)
}
}
if n := notModified.Load(); n != 2 {
t.Fatalf("upstream answered 304 %d times, want 2", n)
}
if store.stores != 1 {
t.Errorf("document stored %d times, want once", store.stores)
}
refreshed, err := db.GetMetadataCache("test", "pkg")
if err != nil {
t.Fatal(err)
}
if !refreshed.FetchedAt.Time.After(stored.FetchedAt.Time) {
t.Errorf("fetched_at = %v, want later than %v", refreshed.FetchedAt.Time, stored.FetchedAt.Time)
}
if refreshed.ContentDigest != stored.ContentDigest || refreshed.ETag != stored.ETag {
t.Errorf("row validators changed: %+v, want %+v", refreshed, stored)
}
}
// TestMetadataNotModifiedStoresRowWithoutDigest checks that a 304 for a row
// written before digests were recorded stores the document as before, so the
// row gains its digest.
func TestMetadataNotModifiedStoresRowWithoutDigest(t *testing.T) {
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("If-None-Match") == `"v1"` {
w.WriteHeader(http.StatusNotModified)
return
}
t.Errorf("unconditional upstream request")
}))
t.Cleanup(upstream.Close)
proxy, db, store, _ := setupTestProxy(t)
proxy.CacheMetadata = true
proxy.MetadataTTL = time.Nanosecond
proxy.HTTPClient = upstream.Client()
path := metadataStoragePath("test", "pkg")
store.files[path] = []byte(`{"v":1}`)
if err := db.UpsertMetadataCache(&database.MetadataCacheEntry{
Ecosystem: "test",
Name: "pkg",
StoragePath: path,
ETag: sql.NullString{String: `"v1"`, Valid: true},
FetchedAt: sql.NullTime{Time: time.Now().Add(-time.Hour), Valid: true},
}); err != nil {
t.Fatal(err)
}
res := proxy.fetchMetadataDocument(context.Background(), "test", "pkg", upstream.URL+"/pkg", contentTypeJSON, nil)
if res.err != nil || string(res.body) != `{"v":1}` {
t.Fatalf("fetch = %q, %v", res.body, res.err)
}
if want := "sha256:" + sha256Hex(`{"v":1}`); res.digest != want {
t.Errorf("digest = %q, want %q", res.digest, want)
}
if store.stores != 1 {
t.Errorf("document stored %d times, want once", store.stores)
}
}