package updatepackage import ( "archive/zip" "bytes" "crypto/sha256" "encoding/hex" "encoding/json" "os" "path/filepath" "strings" "testing" ) func TestOpenAndExtractNativeBackend(t *testing.T) { jar := []byte("native backend JAR") packagePath := writeBackendPackage(t, jar, nil) updatePackage, err := OpenBackendNative(packagePath) if err != nil { t.Fatalf("open native backend package: %v", err) } defer updatePackage.Close() if updatePackage.CustomerCode != "customer-01" || updatePackage.VersionID != "V1.1.8" || updatePackage.ArtifactID != 42 { t.Fatalf("unexpected package metadata: %+v", updatePackage) } if updatePackage.Identity.Size != int64(len(jar)) || updatePackage.PackageSHA256 == "" { t.Fatalf("unexpected package identity: package=%s artifact=%+v", updatePackage.PackageSHA256, updatePackage.Identity) } destination := filepath.Join(t.TempDir(), "incoming", "backend.jar") if err := updatePackage.ExtractArtifact(destination); err != nil { t.Fatalf("extract native backend artifact: %v", err) } actual, err := os.ReadFile(destination) if err != nil || !bytes.Equal(actual, jar) { t.Fatalf("unexpected extracted artifact: content=%q err=%v", actual, err) } } func TestOpenRejectsUnknownManifestField(t *testing.T) { jar := []byte("native backend JAR") packagePath := writeBackendPackage(t, jar, func(manifest map[string]any) { manifest["VersionID"] = "wrong-case" }) _, err := OpenBackendNative(packagePath) if err == nil || !strings.Contains(err.Error(), "VersionID") { t.Fatalf("expected unknown manifest field rejection, got %v", err) } } func TestOpenRejectsMissingDeclaredArtifact(t *testing.T) { jar := []byte("native backend JAR") packagePath := writePackageEntries(t, map[string][]byte{ manifestName: manifestJSON(t, jar, func(manifest map[string]any) { artifacts := manifest["backendArtifacts"].([]any) artifacts[0].(map[string]any)["fileName"] = "missing.jar" }), }) _, err := OpenBackendNative(packagePath) if err == nil || !strings.Contains(err.Error(), "missing.jar") { t.Fatalf("expected missing artifact rejection, got %v", err) } } func TestExtractRejectsArtifactDigestMismatch(t *testing.T) { jar := []byte("native backend JAR") packagePath := writeBackendPackage(t, jar, func(manifest map[string]any) { artifacts := manifest["backendArtifacts"].([]any) artifacts[0].(map[string]any)["sha256"] = strings.Repeat("0", 64) }) updatePackage, err := OpenBackendNative(packagePath) if err != nil { t.Fatalf("open package before digest verification: %v", err) } defer updatePackage.Close() destination := filepath.Join(t.TempDir(), "backend.jar") if err := updatePackage.ExtractArtifact(destination); err == nil || !strings.Contains(err.Error(), "SHA-256 mismatch") { t.Fatalf("expected artifact digest mismatch, got %v", err) } if _, err := os.Stat(destination); !os.IsNotExist(err) { t.Fatalf("digest mismatch published artifact: %v", err) } } func TestOpenRejectsUnsafeAndDuplicateEntries(t *testing.T) { jar := []byte("native backend JAR") manifest := manifestJSON(t, jar, nil) t.Run("unsafe", func(t *testing.T) { packagePath := writePackageEntries(t, map[string][]byte{ manifestName: manifest, "backend.jar": jar, "../escape": []byte("escape"), }) if _, err := OpenBackendNative(packagePath); err == nil { t.Fatal("expected unsafe ZIP entry rejection") } }) t.Run("duplicate", func(t *testing.T) { path := filepath.Join(t.TempDir(), "package.zip") file, err := os.Create(path) if err != nil { t.Fatalf("create duplicate package: %v", err) } writer := zip.NewWriter(file) for _, content := range [][]byte{manifest, manifest} { entry, err := writer.Create(manifestName) if err != nil { t.Fatalf("create duplicate manifest entry: %v", err) } if _, err := entry.Write(content); err != nil { t.Fatalf("write duplicate manifest entry: %v", err) } } if err := writer.Close(); err != nil { t.Fatalf("close duplicate package writer: %v", err) } if err := file.Close(); err != nil { t.Fatalf("close duplicate package: %v", err) } if _, err := OpenBackendNative(path); err == nil || !strings.Contains(err.Error(), "duplicate") { t.Fatalf("expected duplicate ZIP entry rejection, got %v", err) } }) } func writeBackendPackage(t *testing.T, jar []byte, modify func(map[string]any)) string { t.Helper() return writePackageEntries(t, map[string][]byte{ manifestName: manifestJSON(t, jar, modify), "backend.jar": jar, }) } func manifestJSON(t *testing.T, jar []byte, modify func(map[string]any)) []byte { t.Helper() digest := sha256.Sum256(jar) manifest := map[string]any{ "customerCode": "customer-01", "customerDisplayName": "Customer 01", "versionId": "V1.1.8", "items": []string{"deploy-sync.sh"}, "backendArtifacts": []any{map[string]any{ "id": int64(42), "versionCode": "V1.1.8", "artifactKind": backendArtifactKind, "type": nativeArtifactType, "selectedType": nativeArtifactType, "platform": nil, "fileName": "backend.jar", "filePath": "/archive/backend.jar", "sha256": hex.EncodeToString(digest[:]), "imageRef": nil, }}, "frontendArtifacts": []any{}, "nodeSsrArtifacts": []any{}, "remark": nil, } if modify != nil { modify(manifest) } content, err := json.Marshal(manifest) if err != nil { t.Fatalf("encode manifest: %v", err) } return content } func writePackageEntries(t *testing.T, entries map[string][]byte) string { t.Helper() packagePath := filepath.Join(t.TempDir(), "package.zip") file, err := os.Create(packagePath) if err != nil { t.Fatalf("create package: %v", err) } writer := zip.NewWriter(file) for name, content := range entries { entry, err := writer.Create(name) if err != nil { t.Fatalf("create package entry %s: %v", name, err) } if _, err := entry.Write(content); err != nil { t.Fatalf("write package entry %s: %v", name, err) } } if err := writer.Close(); err != nil { t.Fatalf("close package writer: %v", err) } if err := file.Close(); err != nil { t.Fatalf("close package: %v", err) } return packagePath }