package binary import ( "archive/tar" "compress/gzip" "crypto/sha256" "encoding/hex" "io" "os" "os/exec" "path/filepath" "strings" "testing" "github.com/klauspost/compress/zstd" "git.spectoria.dev/huntedbytheirs/zeta-reconstruct/internal/registry" ) const fixturePkg = "../../../testdata/hello-1.0-1-x86_64.pkg.tar.zst" func TestConvert(t *testing.T) { out := t.TempDir() err := Convert(fixturePkg, registry.Options{Output: out, Repo: "https://example.org/repo"}) if err != nil { t.Fatalf("Convert() error = %v, want nil", err) } manifestPath := filepath.Join(out, "packages", "hello", "package.lua") tarballPath := filepath.Join(out, "packages", "hello", "hello-1.0-1.tar.gz") content, err := os.ReadFile(manifestPath) if err != nil { t.Fatalf("package.lua not written: %v", err) } src := string(content) if !strings.Contains(src, "archive = { strip = 1 }") { t.Errorf("package.lua does not contain archive mode marker:\n%s", src) } if !strings.Contains(src, `name = "hello"`) { t.Errorf("package.lua does not contain name field:\n%s", src) } if _, err := os.Stat(tarballPath); err != nil { t.Fatalf("tarball not written: %v", err) } // The sha256 field must equal a fresh hash of the written tarball. got := extractField(t, src, "sha256") want := fileSHA256(t, tarballPath) if got != want { t.Errorf("package.lua sha256 = %q, sha256(tarball) = %q", got, want) } // Deps: glibc dropped, zlib renamed to libz. if !strings.Contains(src, `"libz"`) { t.Errorf("package.lua deps does not contain mapped libz:\n%s", src) } if strings.Contains(src, "glibc") { t.Errorf("package.lua still contains dropped glibc:\n%s", src) } // Cross-tool validation: the emitted manifest must load through the // real Zeta manifest loader. lua, err := exec.LookPath("lua") if err != nil { t.Skip("lua not available; skipping cross-tool validation") } probe := `package.path="/home/specter/Public/ZETA/lib/?.lua;"..package.path; ` + `local m=require("manifest"); assert(m.load(` + quoteLua(manifestPath) + `))` cmd := exec.Command(lua, "-e", probe) if b, err := cmd.CombinedOutput(); err != nil { t.Fatalf("real Zeta manifest.load rejected the emitted manifest: %v\n%s", err, b) } // The tarball must be a valid gzip+tar whose content matches the input // payload (usr/bin/hello). verifyTarballPayload(t, tarballPath) } func TestConvertMissingPKGINFO(t *testing.T) { // A zstd-compressed tar without a .PKGINFO member. var buf strings.Builder tw := tar.NewWriter(&buf) body := "#!/bin/sh\n" if err := tw.WriteHeader(&tar.Header{Name: "usr/bin/x", Mode: 0o755, Size: int64(len(body))}); err != nil { t.Fatal(err) } if _, err := tw.Write([]byte(body)); err != nil { t.Fatal(err) } if err := tw.Close(); err != nil { t.Fatal(err) } enc, err := zstd.NewWriter(nil) if err != nil { t.Fatal(err) } compressed := enc.EncodeAll([]byte(buf.String()), nil) pkg := filepath.Join(t.TempDir(), "noinfo.pkg.tar.zst") if err := os.WriteFile(pkg, compressed, 0o644); err != nil { t.Fatal(err) } err = Convert(pkg, registry.Options{Output: t.TempDir(), Repo: "https://example.org/repo"}) if err == nil { t.Fatal("Convert() error = nil, want error for archive without .PKGINFO") } if !strings.Contains(err.Error(), "PKGINFO") { t.Errorf("Convert() error = %q, want it to name the missing .PKGINFO", err) } } func TestConvertMissingInput(t *testing.T) { err := Convert(filepath.Join(t.TempDir(), "nope.pkg.tar.zst"), registry.Options{Output: t.TempDir(), Repo: "https://example.org/repo"}) if err == nil { t.Fatal("Convert() error = nil, want error for missing input file") } } // extractField pulls the value of a `key = "value",` line from an emitted // package.lua. func extractField(t *testing.T, src, key string) string { t.Helper() for _, line := range strings.Split(src, "\n") { line = strings.TrimSpace(line) if !strings.HasPrefix(line, key) { continue } i := strings.Index(line, `"`) j := strings.LastIndex(line, `"`) if i < 0 || j <= i { t.Fatalf("field %q has no quoted value in %q", key, line) } return line[i+1 : j] } t.Fatalf("field %q not found in package.lua", key) return "" } // fileSHA256 returns the lowercase hex sha256 of the file at path. func fileSHA256(t *testing.T, path string) string { t.Helper() f, err := os.Open(path) if err != nil { t.Fatal(err) } defer f.Close() h := sha256.New() if _, err := io.Copy(h, f); err != nil { t.Fatal(err) } return hex.EncodeToString(h.Sum(nil)) } // quoteLua renders a path as a safe single-quoted Lua string literal. func quoteLua(s string) string { return `'` + strings.ReplaceAll(s, `\`, `\\`) + `'` } // verifyTarballPayload re-opens the emitted tarball and asserts the payload // file survived with the right content. func verifyTarballPayload(t *testing.T, path string) { t.Helper() f, err := os.Open(path) if err != nil { t.Fatal(err) } defer f.Close() gz, err := gzip.NewReader(f) if err != nil { t.Fatal(err) } defer gz.Close() var found bool tr := tar.NewReader(gz) for { hdr, err := tr.Next() if err == io.EOF { break } if err != nil { t.Fatal(err) } if strings.TrimPrefix(hdr.Name, "./") == "usr/bin/hello" { found = true b, err := io.ReadAll(tr) if err != nil { t.Fatal(err) } if !strings.Contains(string(b), "hello") { t.Errorf("payload usr/bin/hello content = %q", b) } } } if !found { t.Error("payload member usr/bin/hello missing from tarball") } }