The laptop model's hardware module and a memory-pressure module for any machine (hq research 027/03, 026/05, to-be 42 phase 3). The predecessor's polling auto-profile and mem-guard user scripts become each module's own Go code launched by the node runtime (ADR 0198): a profile switcher woken by the kernel's power-supply uevents, and a guard that warns on RAM, swap or PSI before systemd-oomd acts, on the desktop over the account's bus and always as an event. supergfxctl and triggerhappy are kept as found (research 027 Q1).
111 lines
3.0 KiB
Go
111 lines
3.0 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
type manifest struct {
|
|
Module string `json:"module"`
|
|
Tools []string `json:"tools"`
|
|
Emits []string `json:"emits"`
|
|
Resources []map[string]any `json:"resources"`
|
|
}
|
|
|
|
func readManifest(t *testing.T) manifest {
|
|
t.Helper()
|
|
raw, err := os.ReadFile("../../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 TestTheManifestNamesExactlyTheToolsTheBundleServes(t *testing.T) {
|
|
m := readManifest(t)
|
|
var served []string
|
|
for _, tool := range Tools(&Machine{Root: t.TempDir(), Run: newFake(t).run}, nil) {
|
|
served = append(served, tool.Name)
|
|
}
|
|
sort.Strings(served)
|
|
listed := append([]string(nil), m.Tools...)
|
|
sort.Strings(listed)
|
|
if strings.Join(served, ",") != strings.Join(listed, ",") {
|
|
t.Fatalf("served %v, listed %v", served, listed)
|
|
}
|
|
if len(m.Emits) != 1 || m.Emits[0] != "profile.switched" {
|
|
t.Fatalf("emits %v", m.Emits)
|
|
}
|
|
}
|
|
|
|
// The module names the model, never a node, a person or a user id (novox/hq ADR 0112), and every
|
|
// trigger it names a service restart or reload on is one of its own resources.
|
|
func TestTheManifestNamesNoMachineAndItsTriggersExist(t *testing.T) {
|
|
m := readManifest(t)
|
|
ids := map[string]bool{}
|
|
for _, r := range m.Resources {
|
|
ids[r["id"].(string)] = true
|
|
}
|
|
raw, _ := os.ReadFile("../../module.json")
|
|
for _, banned := range []string{"jochen", "/home/", "/run/user/1000", "\"g14\"", "shanks"} {
|
|
if strings.Contains(string(raw), banned) {
|
|
t.Errorf("the manifest says %q", banned)
|
|
}
|
|
}
|
|
for _, r := range m.Resources {
|
|
for _, key := range []string{"restart-on", "reload-on"} {
|
|
list, _ := r[key].([]any)
|
|
for _, id := range list {
|
|
if !ids[id.(string)] {
|
|
t.Errorf("%s %s names %v, which is not a resource", r["id"], key, id)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Every trigger runs a script the module ships, and every script parses.
|
|
func TestTheVendorKeysRunTheModulesOwnScriptsAndTheyParse(t *testing.T) {
|
|
m := readManifest(t)
|
|
var triggers string
|
|
for _, r := range m.Resources {
|
|
if r["id"] == "vendor-keys" {
|
|
triggers = r["content"].(string)
|
|
}
|
|
}
|
|
if triggers == "" {
|
|
t.Fatal("no vendor-keys resource")
|
|
}
|
|
for _, line := range strings.Split(triggers, "\n") {
|
|
f := strings.Split(line, "\t")
|
|
if strings.HasPrefix(line, "#") || len(f) < 3 {
|
|
continue
|
|
}
|
|
script := strings.Fields(f[2])[0]
|
|
local := filepath.Join("../../files/bin", filepath.Base(script))
|
|
if !strings.HasPrefix(script, "/usr/local/lib/asus-zephyrus-g14/bin/") {
|
|
t.Errorf("%s runs %s, which the module does not ship", f[0], script)
|
|
} else if st, err := os.Stat(local); err != nil || st.Mode()&0o111 == 0 {
|
|
t.Errorf("%s: %s is missing or not executable", f[0], local)
|
|
}
|
|
}
|
|
scripts, _ := filepath.Glob("../../files/bin/*")
|
|
if len(scripts) == 0 {
|
|
t.Fatal("no scripts")
|
|
}
|
|
for _, s := range scripts {
|
|
if out, err := exec.Command("bash", "-n", s).CombinedOutput(); err != nil {
|
|
t.Errorf("%s: %v %s", s, err, out)
|
|
}
|
|
}
|
|
}
|