hugin/cli/internal/bundle/bundle_test.go
2026-10-27 08:33:21 +01:00

92 lines
3.8 KiB
Go

package bundle
import (
"archive/zip"
"bytes"
"encoding/json"
"os"
"path/filepath"
"strings"
"testing"
)
const examples = "../../../contract/examples/bundles"
func TestReadExamples(t *testing.T) {
entries, err := os.ReadDir(examples)
if err != nil {
t.Fatal(err)
}
for _, e := range entries {
if _, err := Read(filepath.Join(examples, e.Name())); err != nil {
t.Errorf("%s: %v", e.Name(), err)
}
}
}
func zipWith(t *testing.T, instructions map[string]any, files map[string]string) []byte {
t.Helper()
var buffer bytes.Buffer
z := zip.NewWriter(&buffer)
raw, _ := json.Marshal(instructions)
files[InstructionsFile] = string(raw)
for name, content := range files {
w, _ := z.Create(name)
w.Write([]byte(content))
}
z.Close()
return buffer.Bytes()
}
func instructions(ops ...map[string]any) map[string]any {
return map[string]any{"format": 1, "generated": "2026-10-18T12:00:00Z", "tools": []string{"claude"},
"packages": []any{}, "operations": ops, "hints": []any{}}
}
func install(pkg, version, path, source, sha string) map[string]any {
return map[string]any{"op": "install", "package": pkg, "version": version, "checksum": sha, "runtime": "python",
"entry": "x", "files": []any{map[string]any{"path": path, "source": source, "sha256": sha}}}
}
func TestInvalidBundles(t *testing.T) {
content := "x"
sha := Sha256([]byte(content))
tests := []struct {
name string
zip []byte
message string
}{
{"Pfad nach draußen", zipWith(t, instructions(map[string]any{"op": "file", "package": "pub-x",
"path": "../x", "source": "files/x", "sha256": sha}), map[string]string{"files/x": content}), "Segment"},
{"absoluter Pfad", zipWith(t, instructions(map[string]any{"op": "remove", "package": "pub-x",
"path": "/etc/passwd"}), map[string]string{}), "relative"},
{"Windows-Pfad", zipWith(t, instructions(map[string]any{"op": "remove", "package": "pub-x",
"path": `C:\x`}), map[string]string{}), "relative"},
{"falsche Prüfsumme", zipWith(t, instructions(map[string]any{"op": "file", "package": "pub-x",
"path": "x", "source": "files/x", "sha256": Sha256([]byte("y"))}), map[string]string{"files/x": content}), "Prüfsumme"},
{"Quelle fehlt", zipWith(t, instructions(map[string]any{"op": "file", "package": "pub-x",
"path": "x", "source": "files/x", "sha256": sha}), map[string]string{}), "fehlt"},
{"Quelle außerhalb files/", zipWith(t, instructions(map[string]any{"op": "file", "package": "pub-x",
"path": "x", "source": "x", "sha256": sha}), map[string]string{"x": content}), "files/"},
{"unbekannte Operation", zipWith(t, instructions(map[string]any{"op": "ausfuehren"}), map[string]string{}), "unbekannte"},
{"lokaler Server: Paket als Pfad", zipWith(t, instructions(install("../x", "1.0.0", "x", "local/../x/1.0.0/x", sha)),
map[string]string{}), "ungültiges Paket"},
{"lokaler Server: Version als Pfad", zipWith(t, instructions(install("pub-x", "..", "x", "local/pub-x/../x", sha)),
map[string]string{}), "ungültiges Paket"},
{"lokaler Server: Datei nach draußen", zipWith(t, instructions(install("pub-x", "1.0.0", "../x", "local/pub-x/1.0.0/../x", sha)),
map[string]string{}), "Segment"},
{"lokaler Server: Quelle passt nicht", zipWith(t, instructions(install("pub-x", "1.0.0", "x", "local/pub-y/1.0.0/x", sha)),
map[string]string{"local/pub-y/1.0.0/x": content}), "passt nicht"},
{"lokaler Server: falsche Prüfsumme", zipWith(t, instructions(install("pub-x", "1.0.0", "x", "local/pub-x/1.0.0/x", Sha256([]byte("y")))),
map[string]string{"local/pub-x/1.0.0/x": content}), "Prüfsumme"},
{"neues Format", zipWith(t, map[string]any{"format": 2}, map[string]string{}), "Format"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := FromZip(tt.zip)
if err == nil || !strings.Contains(err.Error(), tt.message) {
t.Errorf("Fehler %v, erwartet %q", err, tt.message)
}
})
}
}