package main import ( "strings" "testing" "time" "github.com/novox/mesh-controller/internal/inventory" ) // Defends novox/hq issue 160: `node` shows every fact a machine said it is made of, in one block with its // age, the architecture and kernel among them; and a fact it could not determine as unknown with why. func TestNodeShowsWhatAMachineIsMadeOfWithItsAge(t *testing.T) { now := time.Date(2026, 10, 12, 15, 0, 0, 0, time.UTC) booted := now.Add(-75 * time.Hour) a := inventory.MachineAccount{Architecture: "amd64", Kernel: "linux", Machine: &inventory.MadeOf{ ObservedAt: now.Add(-3 * time.Hour), KernelRelease: "7.2.8-arch1-2", Distribution: "Arch Linux", Version: "rolling", Processor: "AMD Ryzen 9 8945HS", Cores: 8, Threads: 16, MemoryBytes: 32891494400, Virtual: "physical", BootedAt: &booted, Timezone: "Europe/Brussels", Filesystems: []inventory.MountedFilesystem{{Mount: "/", Device: "/dev/nvme0n1p3", Type: "ext4", SizeBytes: 987978522624, FreeBytes: 31830110208}}, Unknown: map[string]string{"public address": "how it learns it is not decided yet"}, }} got := strings.Join(machineLines(a, true, now), "\n") t.Log("\n" + got) for _, want := range []string{ "what it is made of, as it said 3h ago:", "architecture amd64", "kernel linux 7.2.8-arch1-2", "distribution Arch Linux rolling", "processor AMD Ryzen 9 8945HS", "cores 8", "threads 16", "memory 30.6 GiB", "virtual physical", "up 3d, since", "timezone Europe/Brussels", "filesystems / 920.1 GiB, 29.6 GiB free (ext4 /dev/nvme0n1p3)", "public address unknown: how it learns it is not decided yet", } { if !strings.Contains(got, want) { t.Errorf("missing %q", want) } } } func TestAFactAMachineCouldNotReadIsShownUnknownNeverZero(t *testing.T) { now := time.Date(2026, 10, 12, 15, 0, 0, 0, time.UTC) a := inventory.MachineAccount{Architecture: "arm64", Kernel: "linux", Machine: &inventory.MadeOf{ ObservedAt: now, Unknown: map[string]string{"memory": "MemTotal not found in /proc/meminfo", "cores": "/proc/cpuinfo says no core id", "kernel release": "permission denied"}}} got := strings.Join(machineLines(a, true, now), "\n") t.Log("\n" + got) for _, want := range []string{ "memory unknown: MemTotal not found in /proc/meminfo", "cores unknown: /proc/cpuinfo says no core id", "kernel linux (release unknown: permission denied)", // Neither said nor named unknown: the node-engine broke its rule, and that is shown. "timezone unknown: the machine said neither it nor why", } { if !strings.Contains(got, want) { t.Errorf("missing %q", want) } } if strings.Contains(got, " 0 ") || strings.Contains(got, "0 B") { t.Error("a fact the machine could not read was shown as a zero") } } func TestAnOlderNodeEngineStillShowsArchitectureAndKernel(t *testing.T) { got := strings.Join(machineLines(inventory.MachineAccount{Architecture: "amd64", Kernel: "linux"}, true, time.Now()), "\n") if !strings.Contains(got, "older than the one that says it") || !strings.Contains(got, "architecture amd64") || !strings.Contains(got, "kernel linux") { t.Errorf("%s", got) } if got := strings.Join(machineLines(inventory.MachineAccount{}, false, time.Now()), "\n"); !strings.Contains(got, "never said") { t.Errorf("%s", got) } } func TestAnAccountWithoutItsTimeSaysAgeUnknown(t *testing.T) { got := machineLines(inventory.MachineAccount{Architecture: "amd64", Kernel: "linux", Machine: &inventory.MadeOf{KernelRelease: "7.2"}}, true, time.Now())[0] if !strings.Contains(got, "age unknown") || strings.Contains(got, "d ago") { t.Errorf("%s", got) } }