Files
mesh-catalog/modules/disk-load/cmd/disk-load/tools_test.go
T
jschoubben 35ff67bda0
mesh/delivery-group group feat/774-l3-reland rejected: composed together: the checker's verdict at the members' heads (b48c90fea31f): integration: mesh-self-ch…
mesh/delivery closed: a newer head of the same pull request
mesh/check failed: integration: mesh-self-check/cmd/mesh-self-check.TestTheSelfCheckWholeRunsOnTheBus: the run answered {Run:doctor-1793351737-1 At:20…
Design 47's last milestones: the keeper, self-check, healers, hand-acts, provisioner, vault, artifact sweep, disk readings, credential forms (issues 774, 1952, 1953, 1954, 1955)
One commit with exactly the tree of the reviewed head 35b4509c0a, on main 12c2574c9d, so two compiled programs added and removed on the branch leave no trace in history (issue 1577).
2026-10-30 02:21:51 +01:00

204 lines
6.8 KiB
Go

package main
import (
"encoding/json"
"os"
"regexp"
"sort"
"strings"
"testing"
"time"
stdio "git.novox.be/novox/mesh-sdk/go"
)
func tool(t *testing.T, m *Machine, name string) stdio.Tool {
t.Helper()
for _, tl := range Tools(m) {
if tl.Name == name {
return tl
}
}
t.Fatalf("no tool %s", name)
return stdio.Tool{}
}
func TestTheManifestNamesExactlyTheToolsTheBundleServesAndNoMachine(t *testing.T) {
raw, err := os.ReadFile("../../module.json")
if err != nil {
t.Fatal(err)
}
var m struct {
Tools []string `json:"tools"`
Resources []any `json:"resources"`
}
if err := json.Unmarshal(raw, &m); err != nil {
t.Fatal(err)
}
var served []string
k := &Keeper{Store: &memStore{m: map[string]json.RawMessage{}}}
for _, tl := range append(Tools(newFake(t).machine()), ReadingTools(k)...) {
served = append(served, tl.Name)
// disk_measure writes the module's own state of readings and nothing else of the machine.
if !strings.HasSuffix(tl.Description, "(r)") && tl.Name != "disk_measure" {
t.Errorf("%s only reads and does not say so", tl.Name)
}
}
sort.Strings(served)
sort.Strings(m.Tools)
if strings.Join(served, ",") != strings.Join(m.Tools, ",") {
t.Fatalf("served %v, listed %v", served, m.Tools)
}
if len(m.Resources) != 0 {
t.Errorf("the module only reads, and declares %d resources", len(m.Resources))
}
for _, banned := range []string{"g14", "novox", "ace", "shanks", "jochen", "/home/"} {
if regexp.MustCompile(`(^|[^a-z0-9-])` + regexp.QuoteMeta(banned) + `($|[^a-z0-9-])`).Match(raw) {
t.Errorf("the manifest says %q", banned)
}
}
}
func TestDiskLoadSamplesTwoSecondsAndNamesFiveProcessesByDefault(t *testing.T) {
f := aServerUnderWrites(t)
out, err := tool(t, f.machine(), "disk_load").Run(map[string]any{})
if err != nil {
t.Fatal(err)
}
l := out.(Load)
if f.waited != 2*time.Second || l.WindowS != 2 || len(l.Processes) != 3 || len(l.Units) != 3 || len(l.Filesystems) != 3 {
t.Errorf("waited %s, %+v", f.waited, l)
}
}
func TestTheWindowIsAWholeNumberOfSecondsHeldAtTen(t *testing.T) {
f := aServerUnderWrites(t)
load := tool(t, f.machine(), "disk_load")
for _, bad := range []any{0.0, -1.0, 1.5, "soon", true} {
if _, err := load.Run(map[string]any{"seconds": bad}); err == nil {
t.Errorf("seconds %v was accepted", bad)
}
}
if _, err := load.Run(map[string]any{"seconds": 30.0}); err != nil || f.waited != 10*time.Second {
t.Errorf("30 s was not held at 10: waited %s, %v", f.waited, err)
}
if _, err := load.Run(map[string]any{"processes": -1.0}); err == nil {
t.Error("processes -1 was accepted")
}
}
func TestDiskTopRanksUnitsFromTheirCgroupsCountingEachByteOnce(t *testing.T) {
f := aServerUnderWrites(t)
out, err := tool(t, f.machine(), "disk_top").Run(map[string]any{})
if err != nil {
t.Fatal(err)
}
if out.(map[string]any)["by"] != "unit" || f.waited != 2*time.Second {
t.Errorf("the default: %+v, waited %s", out, f.waited)
}
got := out.(map[string]any)["top"].([]Process)
want := []Process{
{Unit: "docker-" + store + ".scope", Container: "store-check", ReadMiBs: 5, WriteMiBs: 50, ReadMiB: 10, WriteMiB: 100, ReadIOPS: 100, WriteIOPS: 500},
{Unit: "editor.scope", WriteMiBs: 2.5, WriteMiB: 5, WriteIOPS: 25},
{Unit: "systemd-journald.service", WriteMiBs: 1, WriteMiB: 2, WriteIOPS: 10},
}
if g, w := must(json.Marshal(got)), must(json.Marshal(want)); string(g) != string(w) {
t.Errorf("by unit\n got %s\nwant %s", g, w)
}
}
func TestDiskTopByContainerNamesOnlyContainers(t *testing.T) {
out, err := tool(t, aServerUnderWrites(t).machine(), "disk_top").Run(map[string]any{"by": "container", "seconds": 1.0})
if err != nil {
t.Fatal(err)
}
got := out.(map[string]any)["top"].([]Process)
if len(got) != 1 || got[0].Container != "store-check" || got[0].Unit != "" || got[0].WriteMiBs != 100 {
t.Errorf("by container %+v", got)
}
}
func TestDiskTopByProcessSaysWhatItCouldNotRead(t *testing.T) {
f := aServerUnderWrites(t)
top := tool(t, f.machine(), "disk_top")
out, err := top.Run(map[string]any{"by": "process", "limit": 2.0})
if err != nil {
t.Fatal(err)
}
got := out.(map[string]any)["top"].([]Process)
if len(got) != 2 || got[0].PID != 100 || got[1].PID != 101 || got[1].ReadMiBs != 5 || got[1].Command != "postgres" {
t.Errorf("by process %+v", got)
}
if out.(map[string]any)["processes_unreadable"] != 1 {
t.Errorf("unreadable not said: %+v", out)
}
if _, err := top.Run(map[string]any{"by": "disk"}); err == nil {
t.Error("by=disk was accepted")
}
}
func TestAContainerTheRuntimeCannotNameIsSaidByItsShortID(t *testing.T) {
f := aServerUnderWrites(t)
delete(f.answers, "docker ps --no-trunc --format {{.ID}}\t{{.Names}}")
out, err := tool(t, f.machine(), "disk_top").Run(map[string]any{"by": "process"})
if err != nil {
t.Fatal(err)
}
if got := out.(map[string]any)["top"].([]Process); got[0].Container != store[:12] {
t.Errorf("%+v", got[0])
}
if n := len(f.calls); n != 1 {
t.Errorf("the runtime was asked %d times, not once", n)
}
}
func TestFilesystemsAreSaidOnceWithTheirOtherMounts(t *testing.T) {
out, err := tool(t, aServerUnderWrites(t).machine(), "disk_filesystems").Run(nil)
if err != nil {
t.Fatal(err)
}
fss := out.(map[string]any)["filesystems"].([]Filesystem)
var mounts []string
for _, fs := range fss {
mounts = append(mounts, fs.Mount)
}
if strings.Join(mounts, ",") != "/,/boot,/mnt/back up" {
t.Fatalf("mounts %v: proc, tmpfs and overlay are not stored data, and a second mount is not a second filesystem", mounts)
}
root := fss[0]
if strings.Join(root.AlsoAt, ",") != "/var/lib/docker" || root.Device != "dm-0" || root.Type != "ext4" ||
root.SizeGiB != 100 || root.UsedGiB != 90 || root.AvailGiB != 5 || root.UsedPct != 94.7 || root.InodesUsed != 40 {
t.Errorf("root %+v", root)
}
if fss[1].Device != "nvme0n1p1" || fss[1].UsedPct != 50 || fss[1].InodesUsed != 0 {
t.Errorf("boot %+v", fss[1])
}
if fss[2].Unanswered == "" {
t.Errorf("a filesystem statfs could not read says so: %+v", fss[2])
}
said := strings.Join(out.(map[string]any)["said"].([]string), "\n")
if !strings.Contains(said, "/ (ext4, /dev/mapper/root): 94.7 % used, 5.0 GiB free of 100.0 GiB — NEARLY FULL") ||
!strings.Contains(said, "/boot (vfat, /dev/nvme0n1p1): 50.0 % used, 0.5 GiB free of 1.0 GiB\n") {
t.Errorf("said:\n%s", said)
}
}
func TestTheMountTablesEscapesAreUndone(t *testing.T) {
for in, want := range map[string]string{`/a\040b`: "/a b", `/tab\011x`: "/tab\tx", `/plain`: "/plain", `/end\04`: `/end\04`, `/back\134slash`: `/back\slash`} {
if got := unescape(in); got != want {
t.Errorf("%q: %q, not %q", in, got, want)
}
}
}
func TestDiskDevicesAnswersWithoutWaiting(t *testing.T) {
f := aServerUnderWrites(t)
out, err := tool(t, f.machine(), "disk_devices").Run(map[string]any{})
if err != nil {
t.Fatal(err)
}
if f.waited != 0 || len(out.(map[string]any)["devices"].([]DeviceInfo)) != 3 {
t.Errorf("waited %s, %+v", f.waited, out)
}
}