1
0
Fork 1
mirror of https://github.com/git-pkgs/proxy.git synced 2026-06-02 08:38:17 -04:00
pkg-proxy/internal/handler/julia_test.go
Andrew Nesbitt 1888626290
Add Julia Pkg server support
- Implement /julia/* handler for the Pkg server protocol
  (registries, registry, package, artifact, meta)
- Resolve package UUIDs to names by parsing Registry.toml from
  the General registry tarball, with a hash-guarded background
  refresh on registry updates
- Wire into router, ecosystem list, install page, badge styles
- Update README and architecture docs
2026-05-12 15:26:27 +01:00

167 lines
4.6 KiB
Go

package handler
import (
"archive/tar"
"bytes"
"compress/gzip"
"log/slog"
"net/http"
"net/http/httptest"
"testing"
)
func TestJuliaParseRegistryLine(t *testing.T) {
tests := []struct {
line string
wantUUID string
wantHash string
wantOK bool
}{
{
"/registry/23338594-aafe-5451-b93e-139f81909106/342327538ed6c1ec54c69fa145e7b6bf5934201e",
"23338594-aafe-5451-b93e-139f81909106",
"342327538ed6c1ec54c69fa145e7b6bf5934201e",
true,
},
{
" /registry/23338594-aafe-5451-b93e-139f81909106/342327538ed6c1ec54c69fa145e7b6bf5934201e\n",
"23338594-aafe-5451-b93e-139f81909106",
"342327538ed6c1ec54c69fa145e7b6bf5934201e",
true,
},
{"/registry/not-a-uuid/0000", "", "", false},
{"junk", "", "", false},
{"", "", "", false},
}
for _, tt := range tests {
uuid, hash, ok := parseRegistryLine(tt.line)
if uuid != tt.wantUUID || hash != tt.wantHash || ok != tt.wantOK {
t.Errorf("parseRegistryLine(%q) = (%q, %q, %v), want (%q, %q, %v)",
tt.line, uuid, hash, ok, tt.wantUUID, tt.wantHash, tt.wantOK)
}
}
}
func TestJuliaValidUUID(t *testing.T) {
tests := []struct {
s string
want bool
}{
{"23338594-aafe-5451-b93e-139f81909106", true},
{"295af30f-e4ad-537b-8983-00126c2a3abe", true},
{"23338594-AAFE-5451-b93e-139f81909106", false},
{"23338594aafe5451b93e139f81909106", false},
{"23338594-aafe-5451-b93e-139f8190910", false},
{"23338594-aafe-5451-b93e-139f81909106-", false},
{"23338594-gafe-5451-b93e-139f81909106", false},
{"", false},
}
for _, tt := range tests {
if got := validJuliaUUID(tt.s); got != tt.want {
t.Errorf("validJuliaUUID(%q) = %v, want %v", tt.s, got, tt.want)
}
}
}
func TestJuliaParseRegistryToml(t *testing.T) {
data := []byte(`name = "General"
uuid = "23338594-aafe-5451-b93e-139f81909106"
[packages]
295af30f-e4ad-537b-8983-00126c2a3abe = { name = "Revise", path = "R/Revise" }
91a5bcdd-55d7-5caf-9e0b-520d859cae80 = { name = "Plots", path = "P/Plots" }
`)
names, err := parseRegistryToml(data)
if err != nil {
t.Fatalf("parseRegistryToml: %v", err)
}
if got := names["295af30f-e4ad-537b-8983-00126c2a3abe"]; got != "Revise" {
t.Errorf("names[Revise uuid] = %q, want Revise", got)
}
if got := names["91a5bcdd-55d7-5caf-9e0b-520d859cae80"]; got != "Plots" {
t.Errorf("names[Plots uuid] = %q, want Plots", got)
}
if len(names) != 2 {
t.Errorf("len(names) = %d, want 2", len(names))
}
}
func TestJuliaExtractRegistryNames(t *testing.T) {
registryToml := `name = "General"
[packages]
295af30f-e4ad-537b-8983-00126c2a3abe = { name = "Revise", path = "R/Revise" }
`
var buf bytes.Buffer
gw := gzip.NewWriter(&buf)
tw := tar.NewWriter(gw)
for _, f := range []struct{ name, body string }{
{"R/Revise/Package.toml", "name = \"Revise\"\n"},
{"Registry.toml", registryToml},
} {
if err := tw.WriteHeader(&tar.Header{Name: f.name, Mode: 0o644, Size: int64(len(f.body))}); err != nil {
t.Fatalf("WriteHeader: %v", err)
}
if _, err := tw.Write([]byte(f.body)); err != nil {
t.Fatalf("Write: %v", err)
}
}
if err := tw.Close(); err != nil {
t.Fatalf("tar Close: %v", err)
}
if err := gw.Close(); err != nil {
t.Fatalf("gzip Close: %v", err)
}
names, err := extractRegistryNames(bytes.NewReader(buf.Bytes()))
if err != nil {
t.Fatalf("extractRegistryNames: %v", err)
}
if got := names["295af30f-e4ad-537b-8983-00126c2a3abe"]; got != "Revise" {
t.Errorf("names[Revise uuid] = %q, want Revise", got)
}
}
func TestJuliaResolveName(t *testing.T) {
h := &JuliaHandler{
proxy: &Proxy{Logger: slog.Default()},
names: map[string]string{
"295af30f-e4ad-537b-8983-00126c2a3abe": "Revise",
},
}
if got := h.resolveName("295af30f-e4ad-537b-8983-00126c2a3abe"); got != "Revise" {
t.Errorf("resolveName(known) = %q, want Revise", got)
}
if got := h.resolveName("00000000-0000-0000-0000-000000000000"); got != "00000000-0000-0000-0000-000000000000" {
t.Errorf("resolveName(unknown) = %q, want uuid fallback", got)
}
}
func TestJuliaRoutesValidation(t *testing.T) {
h := NewJuliaHandler(&Proxy{Logger: slog.Default()}, "")
routes := h.Routes()
tests := []struct {
path string
want int
}{
{"/package/not-a-uuid/342327538ed6c1ec54c69fa145e7b6bf5934201e", http.StatusBadRequest},
{"/package/295af30f-e4ad-537b-8983-00126c2a3abe/short", http.StatusBadRequest},
{"/registry/295af30f-e4ad-537b-8983-00126c2a3abe/zzzz", http.StatusBadRequest},
{"/artifact/nothex", http.StatusBadRequest},
{"/nope", http.StatusNotFound},
}
for _, tt := range tests {
req := httptest.NewRequest(http.MethodGet, tt.path, nil)
rr := httptest.NewRecorder()
routes.ServeHTTP(rr, req)
if rr.Code != tt.want {
t.Errorf("GET %s = %d, want %d", tt.path, rr.Code, tt.want)
}
}
}