Files
mesh-catalog/modules/pacman/cmd/pacman-tools/manifest_test.go
T
jochen d9336d11d0 pacman: the package manager's configuration, mirrors and cache as a module
Mirrors were generated once and never again and caches never cleaned. The
module holds node-package-manager (hq ADR 0207), declares pacman itself, owns
/etc/pacman.conf whole — [options] cannot take an appended block — with the
union of the enabled repositories and improved options, proven by pacman-conf
in its test, and enables reflector.timer (its config owned) and
paccache.timer. Fifteen tools from a Go bundle; transactions run as transient
units so a call's timeout never kills pacman mid-transaction (to-be 42).
2026-10-04 12:50:20 +02:00

104 lines
4.0 KiB
Go

package main
// The module's shape (novox/hq to-be 42 Phase 1, ADR 0207, research 027): it holds the
// node-package-manager seat and declares the package manager's own package; it owns pacman.conf
// whole — proven by pacman-conf on the rendered file, because a pacman.conf pacman cannot read is a
// machine that can neither install nor upgrade — and reflector's configuration, with the refresher
// and the cache cleaner on their timers.
import (
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
)
func TestItHoldsThePackageManagerSeatAndDeclaresItsPackage(t *testing.T) {
m := manifest(t)
if len(m.Claims) != 1 || m.Claims[0]["name"] != "node-package-manager" || m.Claims[0]["scope"] != "node" || m.Claims[0]["serves"] != nil {
t.Fatalf("claims: %v", m.Claims)
}
for id, pkg := range map[string]string{"package": "pacman", "contrib": "pacman-contrib", "reflector": "reflector"} {
if r := m.resource(t, id); r["package"] != pkg || r["absent"] != nil {
t.Errorf("%s: %v", id, r)
}
}
for id, unit := range map[string]string{"mirror-refresh": "reflector.timer", "cache-cleaning": "paccache.timer"} {
r := m.resource(t, id)
if r["unit"] != unit || r["state"] != "running" || r["boot"] != "enabled" {
t.Errorf("%s: %v", id, r)
}
}
}
func TestPacmanConfIsWholeTheUnionOfRepositoriesAndTheImprovedOptions(t *testing.T) {
f := manifest(t).resource(t, "config")
content := f["content"].(string)
if f["path"] != "/etc/pacman.conf" || f["into"] != nil || !strings.HasPrefix(content, MeshHeader) {
t.Fatalf("%v", f)
}
var sections []string
for _, l := range strings.Split(content, "\n") {
if strings.HasPrefix(l, "[") {
sections = append(sections, l)
}
}
if strings.Join(sections, " ") != "[options] [core] [extra] [multilib]" {
t.Fatalf("sections: %v", sections)
}
for _, want := range []string{"\nColor\n", "\nCheckSpace\n", "\nVerbosePkgLists\n", "\nParallelDownloads = 5\n", "\nDownloadUser = alpm\n", "\nSigLevel = Required DatabaseOptional\n"} {
if !strings.Contains(content, want) {
t.Errorf("missing %q", strings.TrimSpace(want))
}
}
conf, err := exec.LookPath("pacman-conf")
if err != nil {
t.Skip("pacman-conf is not installed here; the rendered file is not proven")
}
file := filepath.Join(t.TempDir(), "pacman.conf")
if err := os.WriteFile(file, []byte(content), 0o644); err != nil {
t.Fatal(err)
}
repos, err := exec.Command(conf, "--config", file, "--repo-list").CombinedOutput()
if err != nil || strings.Join(strings.Fields(string(repos)), " ") != "core extra multilib" {
t.Fatalf("pacman-conf --repo-list: %v\n%s", err, repos)
}
out, err := exec.Command(conf, "--config", file).CombinedOutput()
if err != nil {
t.Fatalf("pacman-conf refuses the file: %v\n%s", err, out)
}
c := ParseConf(string(out))
if c.Options["ParallelDownloads"][0] != "5" || c.Options["DownloadUser"] == nil || c.Options["Color"] == nil || c.Options["VerbosePkgLists"] == nil {
t.Fatalf("pacman-conf does not read the options as written: %v", c.Options)
}
}
func TestReflectorWritesTheListPacmanReads(t *testing.T) {
content := manifest(t).resource(t, "mirrors")["content"].(string)
opts := map[string]string{}
for _, l := range strings.Split(content, "\n") {
if l == "" || strings.HasPrefix(l, "#") {
continue
}
k, v, _ := strings.Cut(l, " ")
opts[k] = v
}
if opts["--save"] != Mirrorlist || opts["--protocol"] != "https" || opts["--latest"] != "20" || opts["--sort"] != "rate" || opts["--country"] == "" {
t.Fatalf("%v", opts)
}
if manifest(t).resource(t, "mirrors")["path"] != ReflectorConf {
t.Fatal("reflector reads its options from " + ReflectorConf)
}
}
func TestTheReflectorPackageIsDeclaredBeforeTheFileItShips(t *testing.T) {
order := map[string]int{}
for i, r := range manifest(t).Resources {
order[r["id"].(string)] = i
}
if order["reflector"] > order["mirrors"] || order["contrib"] > order["cache-cleaning"] || order["reflector"] > order["mirror-refresh"] {
t.Fatalf("a package's file and timer come after the package: %v", order)
}
}