mirror of
https://github.com/tailscale/tailscale.git
synced 2025-10-24 09:39:39 +00:00
Upgrade the nfpm package to the latest version to pick up
24a43c5ad7.
The upgrade is from v0 to v2, so there was some breakage to fix.
Generated packages should have the same contents as before.
Updates https://github.com/tailscale/tailscale/issues/1882
Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
206 lines
4.9 KiB
Go
206 lines
4.9 KiB
Go
// Copyright (c) Tailscale Inc & AUTHORS
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package deb
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/md5"
|
|
"crypto/sha1"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"hash"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/goreleaser/nfpm/v2"
|
|
_ "github.com/goreleaser/nfpm/v2/deb"
|
|
)
|
|
|
|
func TestDebInfo(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
in []byte
|
|
want *Info
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "simple",
|
|
in: mkTestDeb("1.2.3", "amd64"),
|
|
want: &Info{
|
|
Version: "1.2.3",
|
|
Arch: "amd64",
|
|
Control: mkControl(
|
|
"Package", "tailscale",
|
|
"Version", "1.2.3",
|
|
"Section", "net",
|
|
"Priority", "extra",
|
|
"Architecture", "amd64",
|
|
"Maintainer", "Tail Scalar",
|
|
"Installed-Size", "0",
|
|
"Description", "test package"),
|
|
},
|
|
},
|
|
{
|
|
name: "arm64",
|
|
in: mkTestDeb("1.2.3", "arm64"),
|
|
want: &Info{
|
|
Version: "1.2.3",
|
|
Arch: "arm64",
|
|
Control: mkControl(
|
|
"Package", "tailscale",
|
|
"Version", "1.2.3",
|
|
"Section", "net",
|
|
"Priority", "extra",
|
|
"Architecture", "arm64",
|
|
"Maintainer", "Tail Scalar",
|
|
"Installed-Size", "0",
|
|
"Description", "test package"),
|
|
},
|
|
},
|
|
{
|
|
name: "unstable",
|
|
in: mkTestDeb("1.7.25", "amd64"),
|
|
want: &Info{
|
|
Version: "1.7.25",
|
|
Arch: "amd64",
|
|
Control: mkControl(
|
|
"Package", "tailscale",
|
|
"Version", "1.7.25",
|
|
"Section", "net",
|
|
"Priority", "extra",
|
|
"Architecture", "amd64",
|
|
"Maintainer", "Tail Scalar",
|
|
"Installed-Size", "0",
|
|
"Description", "test package"),
|
|
},
|
|
},
|
|
|
|
// These truncation tests assume the structure of a .deb
|
|
// package, which is as follows:
|
|
// magic: 8 bytes
|
|
// file header: 60 bytes, before each file blob
|
|
//
|
|
// The first file in a .deb ar is "debian-binary", which is 4
|
|
// bytes long and consists of "2.0\n".
|
|
// The second file is control.tar.gz, which is what we care
|
|
// about introspecting for metadata.
|
|
// The final file is data.tar.gz, which we don't care about.
|
|
//
|
|
// The first file in control.tar.gz is the "control" file we
|
|
// want to read for metadata.
|
|
{
|
|
name: "truncated_ar_magic",
|
|
in: mkTestDeb("1.7.25", "amd64")[:4],
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "truncated_ar_header",
|
|
in: mkTestDeb("1.7.25", "amd64")[:30],
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "missing_control_tgz",
|
|
// Truncate right after the "debian-binary" file, which
|
|
// makes the file a valid 1-file archive that's missing
|
|
// control.tar.gz.
|
|
in: mkTestDeb("1.7.25", "amd64")[:72],
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "truncated_tgz",
|
|
in: mkTestDeb("1.7.25", "amd64")[:172],
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
// mkTestDeb returns non-deterministic output due to
|
|
// timestamps embedded in the package file, so compute the
|
|
// wanted hashes on the fly here.
|
|
if test.want != nil {
|
|
test.want.MD5 = mkHash(test.in, md5.New)
|
|
test.want.SHA1 = mkHash(test.in, sha1.New)
|
|
test.want.SHA256 = mkHash(test.in, sha256.New)
|
|
}
|
|
|
|
t.Run(test.name, func(t *testing.T) {
|
|
b := bytes.NewBuffer(test.in)
|
|
got, err := Read(b)
|
|
if err != nil {
|
|
if test.wantErr {
|
|
t.Logf("got expected error: %v", err)
|
|
return
|
|
}
|
|
t.Fatalf("reading deb info: %v", err)
|
|
}
|
|
if diff := diff(got, test.want); diff != "" {
|
|
t.Fatalf("parsed info diff (-got+want):\n%s", diff)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func diff(got, want any) string {
|
|
matchField := func(name string) func(p cmp.Path) bool {
|
|
return func(p cmp.Path) bool {
|
|
if len(p) != 3 {
|
|
return false
|
|
}
|
|
return p[2].String() == "."+name
|
|
}
|
|
}
|
|
toLines := cmp.Transformer("lines", func(b []byte) []string { return strings.Split(string(b), "\n") })
|
|
toHex := cmp.Transformer("hex", func(b []byte) string { return hex.EncodeToString(b) })
|
|
return cmp.Diff(got, want,
|
|
cmp.FilterPath(matchField("Control"), toLines),
|
|
cmp.FilterPath(matchField("MD5"), toHex),
|
|
cmp.FilterPath(matchField("SHA1"), toHex),
|
|
cmp.FilterPath(matchField("SHA256"), toHex))
|
|
}
|
|
|
|
func mkTestDeb(version, arch string) []byte {
|
|
info := nfpm.WithDefaults(&nfpm.Info{
|
|
Name: "tailscale",
|
|
Description: "test package",
|
|
Arch: arch,
|
|
Platform: "linux",
|
|
Version: version,
|
|
Section: "net",
|
|
Priority: "extra",
|
|
Maintainer: "Tail Scalar",
|
|
})
|
|
|
|
pkg, err := nfpm.Get("deb")
|
|
if err != nil {
|
|
panic(fmt.Sprintf("getting deb packager: %v", err))
|
|
}
|
|
|
|
var b bytes.Buffer
|
|
if err := pkg.Package(info, &b); err != nil {
|
|
panic(fmt.Sprintf("creating deb package: %v", err))
|
|
}
|
|
|
|
return b.Bytes()
|
|
}
|
|
|
|
func mkControl(fs ...string) []byte {
|
|
if len(fs)%2 != 0 {
|
|
panic("odd number of control file fields")
|
|
}
|
|
var b bytes.Buffer
|
|
for i := 0; i < len(fs); i = i + 2 {
|
|
k, v := fs[i], fs[i+1]
|
|
fmt.Fprintf(&b, "%s: %s\n", k, v)
|
|
}
|
|
return bytes.TrimSpace(b.Bytes())
|
|
}
|
|
|
|
func mkHash(b []byte, hasher func() hash.Hash) []byte {
|
|
h := hasher()
|
|
h.Write(b)
|
|
return h.Sum(nil)
|
|
}
|