Files
jbergner 4a48f9b8c5
Citizen Launcher CI / verify (push) Failing after 1m18s
Citizen Launcher CI / arch-package (push) Failing after 1m19s
Citizen Launcher CI / rpm-package (push) Failing after 1m21s
v1.1.1
2026-09-01 19:50:44 +02:00

193 lines
6.3 KiB
Go

package main
import (
"os"
"os/exec"
"path/filepath"
"testing"
)
func TestCompareVersions(t *testing.T) {
cases := []struct {
a, b string
want int
}{
{"0.9.2", "0.9.1", 1},
{"v1.0.0", "0.9.9", 1},
{"0.9.2", "0.9.2", 0},
{"0.9.1", "0.9.2", -1},
{"0.9.2-1", "0.9.2", 0},
}
for _, tc := range cases {
got := compareVersions(tc.a, tc.b)
if got != tc.want {
t.Fatalf("compareVersions(%q,%q)=%d want %d", tc.a, tc.b, got, tc.want)
}
}
}
func TestReleaseAssetForDeb(t *testing.T) {
a, _ := newApp()
r := githubRelease{TagName: "v0.9.2", Assets: []githubAsset{
{Name: "citizen-launcher-0.9.2-linux-amd64.tar.gz"},
{Name: "citizen-launcher_0.9.2_amd64.deb", Digest: "sha256:abc"},
}}
asset, err := a.releaseAssetForMode(r, "0.9.2", "deb")
if err != nil {
t.Fatal(err)
}
if asset.Name != "citizen-launcher_0.9.2_amd64.deb" {
t.Fatalf("wrong asset: %s", asset.Name)
}
}
func TestVerifyDebPackageMetadata(t *testing.T) {
if _, err := exec.LookPath("dpkg-deb"); err != nil {
t.Skip("dpkg-deb unavailable")
}
root := t.TempDir()
pkg := filepath.Join(root, "pkg")
if err := os.MkdirAll(filepath.Join(pkg, "DEBIAN"), 0o755); err != nil {
t.Fatal(err)
}
control := "Package: citizen-launcher\nVersion: 0.9.2\nArchitecture: amd64\nMaintainer: test\nDescription: test\n"
if err := os.WriteFile(filepath.Join(pkg, "DEBIAN", "control"), []byte(control), 0o644); err != nil {
t.Fatal(err)
}
deb := filepath.Join(root, "citizen-launcher_0.9.2_amd64.deb")
cmd := exec.Command("dpkg-deb", "--build", "--root-owner-group", pkg, deb)
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("dpkg-deb: %v: %s", err, out)
}
if err := verifyDebPackage(deb, "0.9.2"); err != nil {
t.Fatal(err)
}
}
func TestVerifyDebPackageRejectsMismatchedNewerVersion(t *testing.T) {
if _, err := exec.LookPath("dpkg-deb"); err != nil {
t.Skip("dpkg-deb unavailable")
}
root := t.TempDir()
pkg := filepath.Join(root, "pkg")
if err := os.MkdirAll(filepath.Join(pkg, "DEBIAN"), 0o755); err != nil {
t.Fatal(err)
}
control := "Package: citizen-launcher\nVersion: 9.9.9\nArchitecture: amd64\nMaintainer: test\nDescription: test\n"
if err := os.WriteFile(filepath.Join(pkg, "DEBIAN", "control"), []byte(control), 0o644); err != nil {
t.Fatal(err)
}
deb := filepath.Join(root, "citizen-launcher_1.0.0_amd64.deb")
if out, err := exec.Command("dpkg-deb", "--build", "--root-owner-group", pkg, deb).CombinedOutput(); err != nil {
t.Fatalf("dpkg-deb: %v: %s", err, out)
}
if err := verifyDebPackage(deb, "1.0.0"); err == nil {
t.Fatal("mismatched package version was accepted")
}
}
func TestReleaseAssetsForAllNativeModes(t *testing.T) {
a, _ := newApp()
r := githubRelease{TagName: "v1.1.1", Assets: []githubAsset{
{Name: "citizen-launcher_1.1.1_amd64.deb"},
{Name: "citizen-launcher-1.1.1-1.linux.x86_64.rpm"},
{Name: "citizen-launcher-1.1.1-1-x86_64.pkg.tar.zst"},
{Name: "citizen-launcher-1.1.1-linux-amd64.tar.gz"},
}}
want := map[string]string{
"deb": "citizen-launcher_1.1.1_amd64.deb",
"rpm": "citizen-launcher-1.1.1-1.linux.x86_64.rpm",
"arch": "citizen-launcher-1.1.1-1-x86_64.pkg.tar.zst",
"user": "citizen-launcher-1.1.1-linux-amd64.tar.gz",
}
for mode, name := range want {
asset, err := a.releaseAssetForMode(r, "1.1.1", mode)
if err != nil {
t.Fatalf("%s: %v", mode, err)
}
if asset.Name != name {
t.Fatalf("%s: got %q want %q", mode, asset.Name, name)
}
}
}
func TestVerifyPackageIdentityAcceptsNativeReleaseSuffixes(t *testing.T) {
cases := []struct{ version, arch, wantArch string }{
{"1.1.0", "amd64", "amd64"},
{"1.1.0-1", "x86_64", "x86_64"},
{"1.1.0", "x86_64", "x86_64"},
}
for _, tc := range cases {
if err := verifyPackageIdentity("citizen-launcher", tc.version, tc.arch, "1.1.0", tc.wantArch); err != nil {
t.Fatal(err)
}
}
if err := verifyPackageIdentity("evil", "1.1.0", "x86_64", "1.1.0", "x86_64"); err == nil {
t.Fatal("wrong package name accepted")
}
}
func TestNativePackageDatabaseParsers(t *testing.T) {
root := t.TempDir()
write := func(name, body string) {
p := filepath.Join(root, name)
if err := os.WriteFile(p, []byte("#!/bin/sh\n"+body+"\n"), 0o755); err != nil {
t.Fatal(err)
}
}
write("dpkg-query", "printf 'install ok installed\\n1.1.0\\n'")
write("rpm", "printf '1.1.0\\n'")
write("pacman", "printf 'citizen-launcher 1.1.0-1\\n'")
t.Setenv("PATH", root)
for mode, want := range map[string]string{"deb": "1.1.0", "rpm": "1.1.0", "arch": "1.1.0-1"} {
pkg := queryInstalledPackage(mode)
if pkg.Mode != mode || pkg.Version != want {
t.Fatalf("%s parser: %#v want version %s", mode, pkg, want)
}
}
}
func TestParseLauncherReleaseSource(t *testing.T) {
cases := []struct {
in, kind string
ok bool
}{
{"owner/repo", "github", true},
{"github:owner/repo", "github", true},
{"gitea:https://git.example.test/api/v1/repos/owner/repo", "gitea", true},
{"gitea:https://git.example.test/sub/path/api/v1/repos/owner/repo", "gitea", true},
{"gitea:https://git.example.test/api/v1/repos/owner/repo/", "gitea", true},
{"gitea:http://git.example.test/api/v1/repos/owner/repo", "", false},
{"gitea:https://user:pass@git.example.test/api/v1/repos/owner/repo", "", false},
{"gitea:https://git.example.test/owner/repo", "", false},
{"../evil", "", false},
}
for _, tc := range cases {
src, ok := parseLauncherReleaseSource(tc.in)
if ok != tc.ok {
t.Fatalf("parseLauncherReleaseSource(%q) ok=%v want %v", tc.in, ok, tc.ok)
}
if ok && src.Kind != tc.kind {
t.Fatalf("parseLauncherReleaseSource(%q) kind=%q want %q", tc.in, src.Kind, tc.kind)
}
}
}
func TestParseSHA256SUMS(t *testing.T) {
body := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa citizen-launcher_1.1.1_amd64.deb\n" +
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb *citizen-launcher-1.1.1-linux-amd64.tar.gz\n" +
"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ../escape.deb\n" +
"not-a-hash ignored\n"
got := parseSHA256SUMS(body)
if got["citizen-launcher_1.1.1_amd64.deb"] != "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" {
t.Fatal("deb checksum missing")
}
if got["citizen-launcher-1.1.1-linux-amd64.tar.gz"] != "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" {
t.Fatal("tarball checksum missing")
}
if _, ok := got["escape.deb"]; ok {
t.Fatal("path-traversal checksum entry accepted")
}
}