Scout/pkg/scoutpkg/manifest_test.go
2026-08-31 15:34:36 +08:00

127 lines
3.2 KiB
Go

package scoutpkg
import (
"archive/zip"
"bytes"
"encoding/json"
"os"
"path/filepath"
"testing"
)
func TestNormalizeAndMatchTarget(t *testing.T) {
targets := []Target{
{Platform: "any", Architecture: "universal", Path: "targets/all"},
{Platform: "linux", Architecture: "universal", Path: "targets/linux"},
{Platform: "linux", Architecture: "amd64", Path: "targets/linux-amd64"},
}
target, ok := MatchTarget(targets, "linux", "x86_64")
if !ok || target.Path != "targets/linux-amd64" {
t.Fatalf("目标匹配错误: %+v", target)
}
target, ok = MatchTarget(targets, "linux", "arm64")
if !ok || target.Path != "targets/linux" {
t.Fatalf("通用目标匹配错误: %+v", target)
}
}
func TestOpenAndExtract(t *testing.T) {
archivePath := filepath.Join(t.TempDir(), "demo.scout")
manifest := Manifest{
SchemaVersion: 1,
Name: "demo-core",
Version: "1.2.0",
Channel: "stable",
PackageType: "full",
Targets: []Target{{
Platform: "linux",
Architecture: "amd64",
Path: "targets/linux/amd64",
Entrypoint: "targets/linux/amd64/demo",
}},
}
createArchive(t, archivePath, manifest, map[string][]byte{
"targets/linux/amd64/demo": []byte("binary"),
})
archive, err := Open(archivePath)
if err != nil {
t.Fatal(err)
}
defer archive.Close()
destination := filepath.Join(t.TempDir(), "release")
target, err := archive.Extract("linux", "amd64", destination)
if err != nil {
t.Fatal(err)
}
if target.Entrypoint != "targets/linux/amd64/demo" {
t.Fatalf("启动入口错误: %s", target.Entrypoint)
}
content, err := os.ReadFile(filepath.Join(destination, "demo"))
if err != nil || string(content) != "binary" {
t.Fatalf("解压结果错误: %q, %v", content, err)
}
}
func TestRejectsPathTraversal(t *testing.T) {
archivePath := filepath.Join(t.TempDir(), "unsafe.scout")
buffer := bytes.NewBuffer(nil)
writer := zip.NewWriter(buffer)
manifest := Manifest{
SchemaVersion: 1,
Name: "unsafe",
Version: "1.0.0",
Targets: []Target{{
Platform: "linux",
Architecture: "amd64",
Path: "targets/linux/amd64",
}},
}
manifestData, _ := json.Marshal(manifest)
entry, _ := writer.Create(ManifestName)
_, _ = entry.Write(manifestData)
entry, _ = writer.Create("../escape")
_, _ = entry.Write([]byte("unsafe"))
_ = writer.Close()
if err := os.WriteFile(archivePath, buffer.Bytes(), 0o644); err != nil {
t.Fatal(err)
}
if _, err := Open(archivePath); err == nil {
t.Fatal("路径穿越包没有被拒绝")
}
}
func createArchive(t *testing.T, fileName string, manifest Manifest, files map[string][]byte) {
t.Helper()
output, err := os.Create(fileName)
if err != nil {
t.Fatal(err)
}
writer := zip.NewWriter(output)
manifestData, err := json.Marshal(manifest)
if err != nil {
t.Fatal(err)
}
entry, err := writer.Create(ManifestName)
if err != nil {
t.Fatal(err)
}
if _, err := entry.Write(manifestData); err != nil {
t.Fatal(err)
}
for name, content := range files {
entry, err := writer.Create(name)
if err != nil {
t.Fatal(err)
}
if _, err := entry.Write(content); err != nil {
t.Fatal(err)
}
}
if err := writer.Close(); err != nil {
t.Fatal(err)
}
if err := output.Close(); err != nil {
t.Fatal(err)
}
}