Files
mesh-controller/cmd/mesh-controller/settings_effective_test.go
T
jochen af63b233db
mesh/merge-gate pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step; every machine composes with the change as it…
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery delivered
mesh/delivery-group group feat/setting-defaults failed: a member failed
Leave out a module whose stored manifest has an unknown field, and raise it (hq ADR 0262 review)
A key dropped silently ran a module without what its manifest says, and a key inside a block still
failed the whole catalogue. Judge a key by what it is about, and narrow the listing to one machine.
2026-10-08 17:34:53 +02:00

110 lines
4.8 KiB
Go

package main
import (
"strings"
"testing"
"github.com/novox/mesh-controller/internal/catalogue"
)
// `settings` says each value and where it came from, and the default a layer overrides (novox/hq ADR 0262).
func TestSettingsSayWhereEachValueComesFrom(t *testing.T) {
got := describeEffective("dunst", "laptop", []catalogue.SettingSource{
{Key: "font-size", Value: float64(13), From: "laptop", Default: float64(10), HasDefault: true},
{Key: "width", Value: float64(250), From: catalogue.DefaultLayer, FromDefault: true, Default: float64(250), HasDefault: true},
})
want := "dunst on laptop, every value and where it comes from:\n" +
" font-size = 13 (laptop; the default is 10)\n" +
" width = 250 (default)\n"
if got != want {
t.Fatalf("said\n%s\nwant\n%s", got, want)
}
}
// `settings` with list "preferences" is the one listing of every module's preferences; module and node
// narrow it, and no other listing is taken.
func TestSettingsListPreferences(t *testing.T) {
for _, c := range []struct {
args map[string]any
want string
}{
{map[string]any{"list": "preferences"}, "settings preferences"},
{map[string]any{"list": "preferences", "module": "dunst"}, "settings preferences dunst"},
{map[string]any{"list": "preferences", "node": "laptop"}, "settings preferences --node laptop"},
} {
argv, err := argvFor("settings", c.args)
if err != nil || strings.Join(argv, " ") != c.want {
t.Errorf("%v: %v %v, want %s", c.args, argv, err, c.want)
}
}
for args, want := range map[string]map[string]any{
"a module is needed to set values": {"values": `{"width": 300}`},
"a module is needed to clear a layer": {"clear": "true"},
} {
if _, err := argvFor("settings", want); err == nil || !strings.Contains(err.Error(), args) {
t.Errorf("%v: %v, want %q", want, err, args)
}
}
if _, err := argvFor("settings", map[string]any{"list": "everything"}); err == nil {
t.Error("a listing other than preferences was taken")
}
if argv, err := argvFor("settings", map[string]any{}); err != nil || strings.Join(argv, " ") != "settings preferences" {
t.Errorf("settings naming no module is the listing: %v %v", argv, err)
}
}
func TestPreferencesSayEachMachinesValueAndItsSource(t *testing.T) {
m := catalogue.Manifest{Module: "dunst", Settings: map[string]catalogue.SettingDeclaration{
"font-size": {Kind: catalogue.KindPreference, Default: float64(10), Why: "readable at 100 DPI"},
"width": {Kind: catalogue.KindPreference, Default: float64(250), Why: "forty characters"},
}}
on := map[string][]catalogue.SettingSource{
"laptop": catalogue.Effective(m, []catalogue.Layer{{From: "laptop", Values: map[string]any{"font-size": float64(16)}}}),
"desk": catalogue.Effective(m, []catalogue.Layer{{From: catalogue.MeshWideLayer, Values: map[string]any{"width": float64(300)}}}),
}
got := describePreferences([]preferencesOf{{Manifest: m, Nodes: []string{"desk", "laptop"}, On: on}})
want := "dunst (on desk, laptop)\n" +
" font-size, default 10: readable at 100 DPI\n" +
" desk: 10 (default)\n" +
" laptop: 16 (the node)\n" +
" width, default 250: forty characters\n" +
" desk: 300 (the mesh)\n" +
" laptop: 250 (default)\n"
if got != want {
t.Fatalf("said\n%s\nwant\n%s", got, want)
}
if describePreferences(nil) != "no module declares a preference\n" {
t.Fatal("an empty listing")
}
}
// The listing over the real stores: each machine's value with its source; a machine names only the
// modules on it; a machine the mesh does not know is refused (novox/hq ADR 0262).
func TestPreferencesListedFromTheStores(t *testing.T) {
open := aMesh(t)
ctx := t.Context()
register(t, open, catalogue.Manifest{Module: "notes", Version: "1",
Settings: map[string]catalogue.SettingDeclaration{
"font-size": {Kind: catalogue.KindPreference, Default: float64(10), Why: "readable at 100 DPI"},
},
Resources: []map[string]any{{"id": "rc", "type": "file", "path": "/etc/notes.conf", "mode": "0644",
"content": "font = ${setting:font-size}\n"}}})
if _, err := assign(ctx, open, "laptop", "notes"); err != nil {
t.Fatal(err)
}
if err := open.inventory.SetSettings(ctx, "laptop", "notes", map[string]any{"font-size": float64(16)}); err != nil {
t.Fatal(err)
}
all := stdoutOf(t, func() error { return settingsCommand(ctx, []string{"preferences"}) })
if !strings.Contains(all, "notes (on laptop)") || !strings.Contains(all, "laptop: 16 (the node)") ||
!strings.Contains(all, "font-size, default 10: readable at 100 DPI") {
t.Fatalf("the listing:\n%s", all)
}
if got := stdoutOf(t, func() error { return settingsCommand(ctx, []string{"preferences", "--node", "anchor"}) }); got != "no module on anchor declares a preference\n" {
t.Fatalf("a machine without the module:\n%s", got)
}
if err := settingsCommand(ctx, []string{"preferences", "--node", "nowhere"}); err == nil {
t.Fatal("a machine the mesh does not know was answered")
}
}