feat: backend native executor implement
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user