package minecraft import ( "net/http" "net/http/httptest" "strings" "sync" "testing" "zlh-agent/internal/state" ) func TestResolveProxyVersion(t *testing.T) { data := `{ "1.20.1": "2.6.0", "1.20.2-1.20.4": "2.7.0", "1.20.5": "2.8.0", "1.21.0-1.21.8": "2.9.0" }` server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/zpacks/minecraft/fabric/fabric-proxy-lite/map.json" { http.NotFound(w, r) return } w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(data)) })) defer server.Close() t.Setenv("ZLH_ARTIFACT_BASE_URL", server.URL) origRoot := fabricProxyArtifactRoot origMap := fabricProxyMap origErr := fabricProxyMapErr origOnce := fabricProxyMapOnce fabricProxyArtifactRoot = "zpacks/minecraft/fabric/fabric-proxy-lite" fabricProxyMap = nil fabricProxyMapErr = nil fabricProxyMapOnce = sync.Once{} t.Cleanup(func() { fabricProxyArtifactRoot = origRoot fabricProxyMap = origMap fabricProxyMapErr = origErr fabricProxyMapOnce = origOnce }) tests := []struct { name string version string want string wantErr string }{ {name: "exact match", version: "1.20.1", want: "2.6.0"}, {name: "range lower bound", version: "1.20.2", want: "2.7.0"}, {name: "range middle", version: "1.20.3", want: "2.7.0"}, {name: "range upper bound", version: "1.21.8", want: "2.9.0"}, {name: "missing", version: "1.19.4", wantErr: "no fabricproxy-lite mapping"}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { fabricProxyMap = nil fabricProxyMapErr = nil fabricProxyMapOnce = sync.Once{} got, err := resolveProxyVersion(tc.version) if tc.wantErr != "" { if err == nil || !strings.Contains(err.Error(), tc.wantErr) { t.Fatalf("expected error containing %q, got %v", tc.wantErr, err) } return } if err != nil { t.Fatalf("resolveProxyVersion(%q) error = %v", tc.version, err) } if got != tc.want { t.Fatalf("resolveProxyVersion(%q) = %q, want %q", tc.version, got, tc.want) } }) } } func TestShouldInjectFabricProxyLiteOnlyForVanillaProfile(t *testing.T) { tests := []struct { name string cfg state.Config want bool }{ { name: "vanilla fabric profile", cfg: state.Config{ ContainerType: "game", Game: "minecraft", Variant: "vanilla", InternalProfile: "vanilla-fabric", }, want: true, }, { name: "fabric variant with stale vanilla profile", cfg: state.Config{ ContainerType: "game", Game: "minecraft", Variant: "fabric", InternalProfile: "vanilla-fabric", }, want: false, }, { name: "vanilla without internal profile", cfg: state.Config{ ContainerType: "game", Game: "minecraft", Variant: "vanilla", }, want: false, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { if got := shouldInjectFabricProxyLite(tc.cfg); got != tc.want { t.Fatalf("shouldInjectFabricProxyLite() = %v, want %v", got, tc.want) } }) } } func TestResolveFabricAPIArtifactURL(t *testing.T) { baseURL := "http://artifacts.test" origRoot := fabricAPIArtifactRoot fabricAPIArtifactRoot = "zpacks/minecraft/fabric/fabric-api" t.Cleanup(func() { fabricAPIArtifactRoot = origRoot }) tests := []struct { name string version string want string wantErr string }{ { name: "version expands to artifact path", version: "1.21.1", want: baseURL + "/zpacks/minecraft/fabric/fabric-api/1.21.1/fabric-api.jar", }, { name: "latest offered version", version: "1.21.7", want: baseURL + "/zpacks/minecraft/fabric/fabric-api/1.21.7/fabric-api.jar", }, { name: "empty", version: "", wantErr: "empty minecraft version", }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { t.Setenv("ZLH_ARTIFACT_BASE_URL", baseURL) got, err := resolveFabricAPIArtifactURL(tc.version) if tc.wantErr != "" { if err == nil || !strings.Contains(err.Error(), tc.wantErr) { t.Fatalf("expected error containing %q, got %v", tc.wantErr, err) } return } if err != nil { t.Fatalf("resolveFabricAPIArtifactURL(%q) error = %v", tc.version, err) } if got != tc.want { t.Fatalf("resolveFabricAPIArtifactURL(%q) = %q, want %q", tc.version, got, tc.want) } }) } }