package main // lemurs's shape (novox/hq ADR 0208): it holds node-login-manager; it owns the configuration in // lemurs 0.4's format and enables the service without ever starting, stopping or restarting it, // because the running login manager is the operator's way in. import ( "encoding/json" "os" "path/filepath" "strings" "testing" ) type manifest struct { Module string `json:"module"` Capabilities []string `json:"capabilities"` Claims []struct { Name string `json:"name"` Scope string `json:"scope"` Serves []string `json:"serves"` } `json:"claims"` Seats any `json:"seats"` Tools []string `json:"tools"` Resources []map[string]any `json:"resources"` Build struct { Artifacts []map[string]any `json:"artifacts"` } `json:"build"` } func readManifest(t *testing.T) manifest { raw, err := os.ReadFile(filepath.Join("..", "..", "module.json")) if err != nil { t.Fatal(err) } var m manifest if err := json.Unmarshal(raw, &m); err != nil { t.Fatal(err) } return m } func resource(t *testing.T, m manifest, id string) map[string]any { for _, r := range m.Resources { if r["id"] == id { return r } } t.Fatalf("no resource %s", id) return nil } func TestItHoldsTheLoginManagerSeatAndServesSessions(t *testing.T) { m := readManifest(t) if m.Seats != nil || len(m.Claims) != 1 || m.Claims[0].Name != "node-login-manager" || strings.Join(m.Claims[0].Serves, ",") != "sessions" { t.Fatalf("%+v", m.Claims) } served := map[string]bool{} for _, tool := range tools(lemurs{}) { served[tool.Name] = true } if !served["node-login-manager.sessions"] || len(served) != 1+len(m.Tools) { t.Fatalf("served %v, manifest %v", served, m.Tools) } for _, name := range m.Tools { if !served[name] { t.Errorf("%s is listed and not served", name) } } } func TestTheOfficialPackageAndItsServiceEnabledButNeverRestarted(t *testing.T) { m := readManifest(t) if p := resource(t, m, "package"); p["package"] != "lemurs" { t.Fatalf("the official package, not lemurs-git: %v", p) } s := resource(t, m, "service") // Running and enabled: the host refuses boot without a state (a stateless service declares only // its triggers). Running starts it only where it is not; with no trigger, nothing restarts it. if s["unit"] != "lemurs.service" || s["boot"] != "enabled" || s["state"] != "running" { t.Fatalf("%v", s) } for _, k := range []string{"restart-on", "reload-on"} { if _, ok := s[k]; ok { t.Fatalf("the login manager is never restarted by a push (%s): a change applies at its next start", k) } } if strings.Join(m.Capabilities, ",") != "package-manager,service-manager,seat" { t.Fatalf("%v", m.Capabilities) } } func TestTheConfigurationIsTheModulesFileAndOffersOnlyTheSessionsModulesPlace(t *testing.T) { m := readManifest(t) c := resource(t, m, "config") raw, _ := os.ReadFile(filepath.Join("..", "..", "config", "config.toml")) if c["path"] != "/etc/lemurs/config.toml" || c["content"] != string(raw) || c["into"] != nil { t.Fatal("the manifest carries config/config.toml whole, as an owned file") } text := c["content"].(string) for _, want := range []string{"[x11]", "[wayland]", `xsetup_path = "/etc/lemurs/xsetup.sh"`, `scripts_path = "/etc/lemurs/wms"`, `scripts_path = "/etc/lemurs/wayland"`, `xsessions_path = "/etc/lemurs/xsessions"`, `wayland_sessions_path = "/etc/lemurs/wayland-sessions"`, `tty = 2`, `x11_display = ":1"`, `remember = true`} { if !strings.Contains(text, want) { t.Errorf("the configuration lacks %s", want) } } for _, l := range strings.Split(text, "\n") { if (strings.HasPrefix(l, "xsessions_path") || strings.HasPrefix(l, "wayland_sessions_path")) && strings.Contains(l, "/usr/share") { t.Fatalf("a package's bare desktop entry would be offered: %s", l) } } for _, id := range []string{"xsessions", "wayland-sessions"} { if d := resource(t, m, id); d["type"] != "directory" || d["path"] != "/etc/lemurs/"+id { t.Fatalf("%v", d) } } }