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/homebrew_bottles_test.go
Simon Chrzanowski 2a8ceb9389
Mirror Homebrew bottles
pkg:brew PURLs failed with "unsupported ecosystem: brew", although listing their versions worked. Homebrew publishes a formula's bottles as an image on its artifact upstream, which proxy mirror can already fetch, so a brew PURL is now resolved to that image and mirrored like one: the formula's JSON API gives the tag, which carries the revision and the bottles' rebuild, and --platform selects bottles like image platforms.

Listing a formula's versions returned the versioned siblings the Homebrew client adds (openssl@3.6 for openssl@3) as versions of it; they are now left out.
2026-10-28 15:18:14 +00:00

72 lines
2.6 KiB
Go

package handler
import (
"context"
"net/http"
"net/http/httptest"
"strings"
"sync/atomic"
"testing"
)
func TestHomebrewBottleImage(t *testing.T) {
formulas := map[string]string{
"/formula/hello.json": `{"versions":{"stable":"2.12.3"},"revision":0,
"bottle":{"stable":{"rebuild":1,"files":{"arm64_linux":{}}}}}`,
"/formula/openssl@3.json": `{"versions":{"stable":"3.5.0"},"revision":2,
"bottle":{"stable":{"rebuild":0,"files":{"arm64_sequoia":{}}}}}`,
"/formula/libsigc++.json": `{"versions":{"stable":"3.6.0"},"revision":0,
"bottle":{"stable":{"rebuild":0,"files":{"x86_64_linux":{}}}}}`,
"/formula/nobottle.json": `{"versions":{"stable":"1.0"},"bottle":{}}`,
}
var requests atomic.Int32
api := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
requests.Add(1)
body, ok := formulas[r.URL.Path]
if !ok {
http.NotFound(w, r)
return
}
_, _ = w.Write([]byte(body))
}))
defer api.Close()
proxy, _, _, _ := setupTestProxy(t)
proxy.HTTPClient = api.Client()
h := NewHomebrewHandler(proxy, api.URL)
tests := []struct {
formula, version string
image, tag, err string
}{
{formula: "hello", version: "2.12.3", image: "homebrew/core/hello", tag: "2.12.3-1"},
{formula: "openssl@3", version: "3.5.0", image: "homebrew/core/openssl/3", tag: "3.5.0_2"},
{formula: "libsigc++", version: "3.6.0", image: "homebrew/core/libsigcxx", tag: "3.6.0"},
// Only the current version is described; another is the tag as given.
{formula: "hello", version: "2.12.2", image: "homebrew/core/hello", tag: "2.12.2"},
{formula: "hello", version: "2.12.3-1", image: "homebrew/core/hello", tag: "2.12.3-1"},
{formula: "nobottle", version: "1.0", err: "has no bottles"},
{formula: "missing", version: "1.0", err: `no formula "missing"`},
}
for _, tt := range tests {
ref, err := h.BottleImage(context.Background(), tt.formula, tt.version)
if tt.err != "" {
if err == nil || !strings.Contains(err.Error(), tt.err) {
t.Errorf("%s@%s: err = %v, want %q", tt.formula, tt.version, err, tt.err)
}
continue
}
if err != nil || ref.Name != tt.image || len(ref.References) != 1 || ref.References[0] != tt.tag {
t.Errorf("%s@%s = %+v, %v; want %s:%s", tt.formula, tt.version, ref, err, tt.image, tt.tag)
}
}
before := requests.Load()
for _, bad := range [][2]string{{"../hello", "1.0"}, {"Hello", "1.0"}, {"hello", "1.0/../x"}, {"hello", ""}} {
if _, err := h.BottleImage(context.Background(), bad[0], bad[1]); err == nil {
t.Errorf("%q@%q accepted", bad[0], bad[1])
}
}
if requests.Load() != before {
t.Error("an invalid name or version reached the API")
}
}