package oci import ( "encoding/json" "net/http" "net/http/httptest" "testing" ) func TestCatalog(t *testing.T) { fdb := newFakeDB() fdb.addRepo("alpha/lib", 1) fdb.addRepo("bravo/svc", 2) fdb.addRepo("charlie/app", 3) h := NewHandler(fdb, newFakeBlobs(), allowAll(), nil, nil) router := testRouter(h) req := authedRequest("GET", "/v2/_catalog", nil) rr := httptest.NewRecorder() router.ServeHTTP(rr, req) if rr.Code != http.StatusOK { t.Fatalf("status: got %d, want %d", rr.Code, http.StatusOK) } var body catalogResponse if err := json.NewDecoder(rr.Body).Decode(&body); err != nil { t.Fatalf("decode body: %v", err) } want := []string{"alpha/lib", "bravo/svc", "charlie/app"} if len(body.Repositories) != len(want) { t.Fatalf("repos count: got %d, want %d", len(body.Repositories), len(want)) } for i, r := range body.Repositories { if r != want[i] { t.Fatalf("repos[%d]: got %q, want %q", i, r, want[i]) } } } func TestCatalogPagination(t *testing.T) { fdb := newFakeDB() fdb.addRepo("alpha/lib", 1) fdb.addRepo("bravo/svc", 2) fdb.addRepo("charlie/app", 3) h := NewHandler(fdb, newFakeBlobs(), allowAll(), nil, nil) router := testRouter(h) // First page: n=2. req := authedRequest("GET", "/v2/_catalog?n=2", nil) rr := httptest.NewRecorder() router.ServeHTTP(rr, req) if rr.Code != http.StatusOK { t.Fatalf("status: got %d, want %d", rr.Code, http.StatusOK) } var body catalogResponse if err := json.NewDecoder(rr.Body).Decode(&body); err != nil { t.Fatalf("decode body: %v", err) } if len(body.Repositories) != 2 { t.Fatalf("page 1 count: got %d, want 2", len(body.Repositories)) } if body.Repositories[0] != "alpha/lib" || body.Repositories[1] != "bravo/svc" { t.Fatalf("page 1: got %v", body.Repositories) } // Check Link header. link := rr.Header().Get("Link") if link == "" { t.Fatal("expected Link header for pagination") } // Second page: n=2, last=bravo/svc. req = authedRequest("GET", "/v2/_catalog?n=2&last=bravo/svc", nil) rr = httptest.NewRecorder() router.ServeHTTP(rr, req) if rr.Code != http.StatusOK { t.Fatalf("page 2 status: got %d, want %d", rr.Code, http.StatusOK) } if err := json.NewDecoder(rr.Body).Decode(&body); err != nil { t.Fatalf("decode page 2: %v", err) } if len(body.Repositories) != 1 { t.Fatalf("page 2 count: got %d, want 1", len(body.Repositories)) } if body.Repositories[0] != "charlie/app" { t.Fatalf("page 2: got %v", body.Repositories) } // No Link header on last page. if link := rr.Header().Get("Link"); link != "" { t.Fatalf("expected no Link header on last page, got %q", link) } } func TestCatalogEmpty(t *testing.T) { fdb := newFakeDB() h := NewHandler(fdb, newFakeBlobs(), allowAll(), nil, nil) router := testRouter(h) req := authedRequest("GET", "/v2/_catalog", nil) rr := httptest.NewRecorder() router.ServeHTTP(rr, req) if rr.Code != http.StatusOK { t.Fatalf("status: got %d, want %d", rr.Code, http.StatusOK) } var body catalogResponse if err := json.NewDecoder(rr.Body).Decode(&body); err != nil { t.Fatalf("decode body: %v", err) } if len(body.Repositories) != 0 { t.Fatalf("expected empty repositories, got %v", body.Repositories) } }