Files
mesh-host/internal/inventory/inventory_test.go
jschoubben ee2648188d Repoint ADR references after HQ consolidated 65 records to 23
96 comments across the two repos named records that no longer exist. Each now
points at the consolidated record that holds its reasoning -- ADR 0034 (a test
defends a decision) is 0017, the eight host records are 0005, the four lab
records are 0016.

Worth noting for next time: these are references from outside HQ, so renumbering
there is not free. It cost 38 files here.
2026-08-28 23:33:44 +02:00

119 lines
4.1 KiB
Go

package inventory
import (
"context"
"errors"
"os"
"strings"
"testing"
"time"
"github.com/novox/mesh-host/internal/profile"
)
func TestAnUnreadableFactIsRecordedNotFatal(t *testing.T) {
// An inventory missing one field is useful; an inventory that refused to be taken is not.
// And an absent fact and a fact that failed to read are different things — collapsing them
// loses the one worth acting on.
failing := func(string) ([]byte, error) { return nil, errors.New("permission denied") }
inv := Collect(context.Background(), failing, nil, time.Second)
if inv.Machine == "" && len(inv.Unreadable) == 0 {
t.Fatal("nothing was read and nothing was reported unreadable")
}
if len(inv.Unreadable) == 0 {
t.Fatal("every file failed and nothing was recorded as unreadable")
}
for _, u := range inv.Unreadable {
if !strings.Contains(u, ":") {
t.Errorf("unreadable entry does not say which fact failed: %q", u)
}
}
if inv.Architecture == "" || inv.CPUs == 0 {
t.Error("facts that need no file were lost along with the ones that did")
}
}
func TestDistributionIsReadFromTheMachineNotAssumed(t *testing.T) {
cases := map[string]string{
"PRETTY_NAME=\"Arch Linux\"\nID=arch\n": "Arch Linux",
"ID=arch\n": "arch",
"# a comment\n\nID=debian\nPRETTY_NAME='Debian 13'\n": "Debian 13",
"NAME=Weird\nPRETTY_NAME=\"Has=Equals\"\n": "Has=Equals",
"": "",
}
for input, want := range cases {
if got := distributionFrom(input); got != want {
t.Errorf("distributionFrom(%q) = %q, want %q", input, got, want)
}
}
}
func TestMemoryIsReadOrReportedMissing(t *testing.T) {
if kb, ok := memoryFrom("MemTotal: 32762868 kB\nMemFree: 1 kB\n"); !ok || kb != 32762868 {
t.Errorf("memoryFrom returned %d, %v", kb, ok)
}
// A meminfo without MemTotal must not read as zero memory — a machine reporting no memory
// would be excluded from placement for a parsing failure.
if _, ok := memoryFrom("MemFree: 1 kB\n"); ok {
t.Error("a meminfo with no MemTotal was read as a successful measurement")
}
if _, ok := memoryFrom("MemTotal: not-a-number kB\n"); ok {
t.Error("an unparseable MemTotal was read as a successful measurement")
}
}
func TestTheInventorySaysWhenItWasTaken(t *testing.T) {
// A node unreachable for a week is an ordinary situation (novox/hq ADR 0004), so an
// inventory that cannot be told from a stale one is missing the fact that matters.
before := time.Now().UTC()
inv := Collect(context.Background(), nil, nil, time.Second)
if inv.ObservedAt.IsZero() {
t.Fatal("the inventory does not say when it was observed")
}
if inv.ObservedAt.Before(before.Add(-time.Second)) || inv.ObservedAt.After(time.Now().UTC().Add(time.Second)) {
t.Errorf("ObservedAt is not the moment of observation: %s", inv.ObservedAt)
}
}
func TestTheHostDoesNotNameTheNode(t *testing.T) {
// A node's name is assigned by the mesh. A host that named itself would be deciding
// something, which is precisely what novox/hq ADR 0005 forbids it to do.
inv := Collect(context.Background(), nil, nil, time.Second)
hostname, _ := os.Hostname()
if inv.Machine != hostname {
t.Errorf("Machine is %q, not the machine's own hostname %q", inv.Machine, hostname)
}
}
// --- against this machine ---------------------------------------------------------------
func TestAgainstThisMachine_inventoryIsTrue(t *testing.T) {
// novox/hq ADR 0017: behaviour against a real system is tested alongside, not mocked.
inv := Collect(context.Background(), nil, profile.Default(nil), 10*time.Second)
if inv.Machine == "" {
t.Error("this machine did not report a name")
}
if inv.CPUs < 1 {
t.Errorf("this machine reported %d cpus", inv.CPUs)
}
if inv.OS == "linux" {
if inv.Kernel == "" {
t.Error("a linux machine reported no kernel version")
}
if inv.MemoryKB <= 0 {
t.Error("a linux machine reported no memory")
}
}
if len(inv.Profile.Capabilities) == 0 {
t.Error("the inventory carries no profile")
}
t.Logf("machine=%s dist=%q kernel=%s arch=%s cpus=%d mem=%dMB unreadable=%v",
inv.Machine, inv.Distribution, inv.Kernel, inv.Architecture,
inv.CPUs, inv.MemoryKB/1024, inv.Unreadable)
}