repo-sync/config/config_test.go
James Coleman 5af1dd8928
Some checks failed
Go package / build (push) Has been cancelled
first commit
2026-07-28 19:22:20 -05:00

142 lines
3.9 KiB
Go

package config
import (
"os"
"path/filepath"
"testing"
)
// writeConfig writes a temp config file and returns its path.
func writeConfig(t *testing.T, content string) string {
t.Helper()
name := filepath.Join(t.TempDir(), "config.yaml")
if err := os.WriteFile(name, []byte(content), 0644); err != nil {
t.Fatal(err)
}
return name
}
// TestInitExample verifies the shipped example configuration is valid.
func TestInitExample(t *testing.T) {
if err := Init("../config.example.yaml"); err != nil {
t.Fatal(err)
}
if _, ok := C.Domain("mirror.example.com:443"); !ok {
t.Error("online domain not resolvable with a port")
}
if C.OnlineDomain().Domain != "mirror.example.com" {
t.Errorf("online domain = %q", C.OnlineDomain().Domain)
}
mount, ok := C.MountFor("/almalinux/9/BaseOS/x86_64/os")
if !ok || mount.Path != "/almalinux" {
t.Errorf("mount = %+v, %v", mount, ok)
}
}
// TestStatePathDefault verifies an unset state path lands next to the
// config file.
func TestStatePathDefault(t *testing.T) {
path := writeConfig(t, `
domains:
- {domain: m.test, role: online, root: /tmp/online}
mounts:
- {path: /, upstream: "https://example.com"}
`)
if err := Init(path); err != nil {
t.Fatal(err)
}
want := filepath.Join(filepath.Dir(path), "state.yaml")
if C.StatePath != want {
t.Errorf("StatePath = %q, want %q", C.StatePath, want)
}
}
// TestMountLongestPrefix verifies the most specific mount wins.
func TestMountLongestPrefix(t *testing.T) {
path := writeConfig(t, `
state_path: /tmp/state.yaml
domains:
- {domain: m.test, role: online, root: /tmp/online}
mounts:
- {path: /, upstream: "https://fallback.example.com"}
- {path: /centos, upstream: "https://centos.example.com"}
- {path: /centos/vault, upstream: "https://vault.example.com"}
`)
if err := Init(path); err != nil {
t.Fatal(err)
}
cases := map[string]string{
"/centos/vault/7/os": "https://vault.example.com",
"/centos/8/BaseOS": "https://centos.example.com",
"/debian/dists/testy": "https://fallback.example.com",
}
for reqPath, want := range cases {
mount, ok := C.MountFor(reqPath)
if !ok || mount.Upstream != want {
t.Errorf("MountFor(%q) = %q, want %q", reqPath, mount.Upstream, want)
}
}
}
// TestInitServerRejections verifies invalid server configurations fail
// with clear errors.
func TestInitServerRejections(t *testing.T) {
cases := map[string]string{
"two online domains": `
state_path: /tmp/state.yaml
domains:
- {domain: a.test, role: online, root: /tmp/a}
- {domain: b.test, role: online, root: /tmp/b}
mounts:
- {path: /, upstream: "https://example.com"}
`,
"no online domain": `
state_path: /tmp/state.yaml
domains:
- {domain: a.test, role: offline, root: /tmp/a}
mounts:
- {path: /, upstream: "https://example.com"}
`,
"repo outside mount": `
state_path: /tmp/state.yaml
domains:
- {domain: a.test, role: online, root: /tmp/a}
mounts:
- path: /centos
upstream: "https://example.com"
repos:
- {path: /debian/dists/x, type: deb}
`,
"bad repo type": `
state_path: /tmp/state.yaml
domains:
- {domain: a.test, role: online, root: /tmp/a}
mounts:
- path: /centos
upstream: "https://example.com"
repos:
- {path: /centos/7/os, type: gentoo}
`,
}
for name, content := range cases {
if err := InitServer(writeConfig(t, content)); err == nil {
t.Errorf("%s: configuration unexpectedly accepted", name)
}
}
}
// TestInitWithoutServerSections verifies a configuration carrying no
// domains or mounts loads for the sync commands but is refused for the
// server.
func TestInitWithoutServerSections(t *testing.T) {
path := writeConfig(t, "state_path: /tmp/state.yaml\ncrawler:\n workers: 9\n")
if err := Init(path); err != nil {
t.Fatalf("Init rejected a sync-only configuration: %v", err)
}
if C.Crawler.Workers != 9 {
t.Errorf("Crawler.Workers = %d, want 9", C.Crawler.Workers)
}
if err := InitServer(path); err == nil {
t.Error("InitServer accepted a configuration with no domains")
}
}