Some checks failed
Go package / build (push) Has been cancelled
- Reject RPM, Debian, and Arch metadata that fails the configured signature policy before trusting its checksums or package paths. - Preserve the last verified repository generation when signed metadata rotates inconsistently or required files remain unavailable. - Let operators pin signer keyrings or retrieve unknown issuers from configured keyservers, including archived GnuPG v1 RSA signatures. - Gate cached server entry points and package misses until a crawl completes under the active signature policy.
157 lines
4.5 KiB
Go
157 lines
4.5 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// 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")
|
|
}
|
|
}
|
|
|
|
// TestKeyserverConfiguration verifies the built-in lookup services can be
|
|
// replaced or disabled without retaining entries from the default list.
|
|
func TestKeyserverConfiguration(t *testing.T) {
|
|
path := writeConfig(t, "crawler:\n keyservers:\n - https://keys.example.com\n")
|
|
require.NoError(t, Init(path))
|
|
assert.Equal(t, []string{"https://keys.example.com"}, C.Crawler.Keyservers)
|
|
|
|
path = writeConfig(t, "crawler:\n keyservers: []\n")
|
|
require.NoError(t, Init(path))
|
|
assert.Empty(t, C.Crawler.Keyservers)
|
|
}
|