package app import ( "archive/tar" "compress/gzip" "context" "encoding/json" "errors" "io" "os" "path/filepath" "testing" "bee/audit/internal/platform" "bee/audit/internal/schema" ) type fakeNetwork struct { listInterfacesFn func() ([]platform.InterfaceInfo, error) defaultRouteFn func() string dhcpOneFn func(string) (string, error) dhcpAllFn func() (string, error) setStaticIPv4Fn func(platform.StaticIPv4Config) (string, error) } func (f fakeNetwork) ListInterfaces() ([]platform.InterfaceInfo, error) { return f.listInterfacesFn() } func (f fakeNetwork) DefaultRoute() string { return f.defaultRouteFn() } func (f fakeNetwork) DHCPOne(iface string) (string, error) { return f.dhcpOneFn(iface) } func (f fakeNetwork) DHCPAll() (string, error) { return f.dhcpAllFn() } func (f fakeNetwork) SetStaticIPv4(cfg platform.StaticIPv4Config) (string, error) { return f.setStaticIPv4Fn(cfg) } func (f fakeNetwork) SetInterfaceState(_ string, _ bool) error { return nil } func (f fakeNetwork) GetInterfaceState(_ string) (bool, error) { return true, nil } func (f fakeNetwork) CaptureNetworkSnapshot() (platform.NetworkSnapshot, error) { return platform.NetworkSnapshot{}, nil } func (f fakeNetwork) RestoreNetworkSnapshot(platform.NetworkSnapshot) error { return nil } type fakeServices struct { serviceStatusFn func(string) (string, error) serviceDoFn func(string, platform.ServiceAction) (string, error) } func (f fakeServices) ListBeeServices() ([]string, error) { return nil, nil } func (f fakeServices) ServiceState(name string) string { return "active" } func (f fakeServices) ServiceStatus(name string) (string, error) { return f.serviceStatusFn(name) } func (f fakeServices) ServiceDo(name string, action platform.ServiceAction) (string, error) { return f.serviceDoFn(name, action) } type fakeExports struct { listTargetsFn func() ([]platform.RemovableTarget, error) exportToTargetFn func(string, platform.RemovableTarget) (string, error) } func (f fakeExports) ListRemovableTargets() ([]platform.RemovableTarget, error) { if f.listTargetsFn != nil { return f.listTargetsFn() } return nil, nil } func (f fakeExports) ExportFileToTarget(src string, target platform.RemovableTarget) (string, error) { if f.exportToTargetFn != nil { return f.exportToTargetFn(src, target) } return "", nil } type fakeRuntime struct { collectFn func(string) (schema.RuntimeHealth, error) dumpFn func(string) error } func (f fakeRuntime) CollectRuntimeHealth(exportDir string) (schema.RuntimeHealth, error) { return f.collectFn(exportDir) } func (f fakeRuntime) CaptureTechnicalDump(baseDir string) error { if f.dumpFn != nil { return f.dumpFn(baseDir) } return nil } type fakeTools struct { tailFileFn func(string, int) string checkToolsFn func([]string) []platform.ToolStatus } func (f fakeTools) TailFile(path string, lines int) string { return f.tailFileFn(path, lines) } func (f fakeTools) CheckTools(names []string) []platform.ToolStatus { return f.checkToolsFn(names) } type fakeSAT struct { runNvidiaFn func(string) (string, error) runNvidiaBenchmarkFn func(string, platform.NvidiaBenchmarkOptions) (string, error) runNvidiaStressFn func(string, platform.NvidiaStressOptions) (string, error) runNvidiaComputeFn func(string, int, []int) (string, error) runNvidiaPowerFn func(string, int, []int) (string, error) runNvidiaPulseFn func(string, int, []int) (string, error) runNvidiaBandwidthFn func(string, []int) (string, error) runNvidiaTargetedStressFn func(string, int, []int) (string, error) runMemoryFn func(string) (string, error) runStorageFn func(string) (string, error) runCPUFn func(string, int) (string, error) detectVendorFn func() string listAMDGPUsFn func() ([]platform.AMDGPUInfo, error) runAMDPackFn func(string) (string, error) listNvidiaGPUsFn func() ([]platform.NvidiaGPU, error) } func (f fakeSAT) RunNvidiaAcceptancePack(baseDir string, _ func(string)) (string, error) { return f.runNvidiaFn(baseDir) } func (f fakeSAT) RunNvidiaAcceptancePackWithOptions(_ context.Context, baseDir string, _ int, _ []int, _ func(string)) (string, error) { return f.runNvidiaFn(baseDir) } func (f fakeSAT) RunNvidiaBenchmark(_ context.Context, baseDir string, opts platform.NvidiaBenchmarkOptions, _ func(string)) (string, error) { if f.runNvidiaBenchmarkFn != nil { return f.runNvidiaBenchmarkFn(baseDir, opts) } return f.runNvidiaFn(baseDir) } func (f fakeSAT) RunNvidiaTargetedStressValidatePack(_ context.Context, baseDir string, durationSec int, gpuIndices []int, _ func(string)) (string, error) { if f.runNvidiaTargetedStressFn != nil { return f.runNvidiaTargetedStressFn(baseDir, durationSec, gpuIndices) } return f.runNvidiaFn(baseDir) } func (f fakeSAT) RunNvidiaOfficialComputePack(_ context.Context, baseDir string, durationSec int, gpuIndices []int, _ func(string)) (string, error) { if f.runNvidiaComputeFn != nil { return f.runNvidiaComputeFn(baseDir, durationSec, gpuIndices) } return f.runNvidiaFn(baseDir) } func (f fakeSAT) RunNvidiaTargetedPowerPack(_ context.Context, baseDir string, durationSec int, gpuIndices []int, _ func(string)) (string, error) { if f.runNvidiaPowerFn != nil { return f.runNvidiaPowerFn(baseDir, durationSec, gpuIndices) } return f.runNvidiaFn(baseDir) } func (f fakeSAT) RunNvidiaPulseTestPack(_ context.Context, baseDir string, durationSec int, gpuIndices []int, _ func(string)) (string, error) { if f.runNvidiaPulseFn != nil { return f.runNvidiaPulseFn(baseDir, durationSec, gpuIndices) } return f.runNvidiaFn(baseDir) } func (f fakeSAT) RunNvidiaBandwidthPack(_ context.Context, baseDir string, gpuIndices []int, _ func(string)) (string, error) { if f.runNvidiaBandwidthFn != nil { return f.runNvidiaBandwidthFn(baseDir, gpuIndices) } return f.runNvidiaFn(baseDir) } func (f fakeSAT) RunNvidiaStressPack(_ context.Context, baseDir string, opts platform.NvidiaStressOptions, _ func(string)) (string, error) { if f.runNvidiaStressFn != nil { return f.runNvidiaStressFn(baseDir, opts) } return f.runNvidiaFn(baseDir) } func (f fakeSAT) ListNvidiaGPUs() ([]platform.NvidiaGPU, error) { if f.listNvidiaGPUsFn != nil { return f.listNvidiaGPUsFn() } return nil, nil } func (f fakeSAT) RunMemoryAcceptancePack(_ context.Context, baseDir string, _ func(string)) (string, error) { return f.runMemoryFn(baseDir) } func (f fakeSAT) RunStorageAcceptancePack(_ context.Context, baseDir string, _ func(string)) (string, error) { return f.runStorageFn(baseDir) } func (f fakeSAT) RunCPUAcceptancePack(_ context.Context, baseDir string, durationSec int, _ func(string)) (string, error) { if f.runCPUFn != nil { return f.runCPUFn(baseDir, durationSec) } return "", nil } func (f fakeSAT) DetectGPUVendor() string { if f.detectVendorFn != nil { return f.detectVendorFn() } return "" } func (f fakeSAT) ListAMDGPUs() ([]platform.AMDGPUInfo, error) { if f.listAMDGPUsFn != nil { return f.listAMDGPUsFn() } return nil, nil } func (f fakeSAT) RunAMDAcceptancePack(_ context.Context, baseDir string, _ func(string)) (string, error) { if f.runAMDPackFn != nil { return f.runAMDPackFn(baseDir) } return "", nil } func (f fakeSAT) RunAMDMemIntegrityPack(_ context.Context, _ string, _ func(string)) (string, error) { return "", nil } func (f fakeSAT) RunAMDMemBandwidthPack(_ context.Context, _ string, _ func(string)) (string, error) { return "", nil } func (f fakeSAT) RunAMDStressPack(_ context.Context, _ string, _ int, _ func(string)) (string, error) { return "", nil } func (f fakeSAT) RunMemoryStressPack(_ context.Context, _ string, _ int, _ func(string)) (string, error) { return "", nil } func (f fakeSAT) RunSATStressPack(_ context.Context, _ string, _ int, _ func(string)) (string, error) { return "", nil } func (f fakeSAT) RunFanStressTest(_ context.Context, _ string, _ platform.FanStressOptions) (string, error) { return "", nil } func (f fakeSAT) RunPlatformStress(_ context.Context, _ string, _ platform.PlatformStressOptions, _ func(string)) (string, error) { return "", nil } func (f fakeSAT) RunNCCLTests(_ context.Context, _ string, _ func(string)) (string, error) { return "", nil } func TestNetworkStatusFormatsInterfacesAndRoute(t *testing.T) { t.Parallel() a := &App{ network: fakeNetwork{ listInterfacesFn: func() ([]platform.InterfaceInfo, error) { return []platform.InterfaceInfo{ {Name: "eth0", State: "UP", IPv4: []string{"10.0.0.2/24"}}, {Name: "eth1", State: "DOWN", IPv4: nil}, }, nil }, defaultRouteFn: func() string { return "10.0.0.1" }, }, runtime: fakeRuntime{ collectFn: func(string) (schema.RuntimeHealth, error) { return schema.RuntimeHealth{}, nil }, }, } result, err := a.NetworkStatus() if err != nil { t.Fatalf("NetworkStatus error: %v", err) } if result.Title != "Network status" { t.Fatalf("title=%q want %q", result.Title, "Network status") } if want := "- eth0: state=UP ip=10.0.0.2/24"; !contains(result.Body, want) { t.Fatalf("body missing %q\nbody=%s", want, result.Body) } if want := "- eth1: state=DOWN ip=(no IPv4)"; !contains(result.Body, want) { t.Fatalf("body missing %q\nbody=%s", want, result.Body) } if want := "Default route: 10.0.0.1"; !contains(result.Body, want) { t.Fatalf("body missing %q\nbody=%s", want, result.Body) } } func TestNetworkStatusHandlesNoInterfaces(t *testing.T) { t.Parallel() a := &App{ network: fakeNetwork{ listInterfacesFn: func() ([]platform.InterfaceInfo, error) { return nil, nil }, defaultRouteFn: func() string { return "" }, }, runtime: fakeRuntime{ collectFn: func(string) (schema.RuntimeHealth, error) { return schema.RuntimeHealth{}, nil }, }, } result, err := a.NetworkStatus() if err != nil { t.Fatalf("NetworkStatus error: %v", err) } if result.Body != "No physical interfaces found." { t.Fatalf("body=%q want %q", result.Body, "No physical interfaces found.") } } func TestNetworkStatusPropagatesListError(t *testing.T) { t.Parallel() a := &App{ network: fakeNetwork{ listInterfacesFn: func() ([]platform.InterfaceInfo, error) { return nil, errors.New("boom") }, defaultRouteFn: func() string { return "" }, }, runtime: fakeRuntime{ collectFn: func(string) (schema.RuntimeHealth, error) { return schema.RuntimeHealth{}, nil }, }, } result, err := a.NetworkStatus() if err == nil { t.Fatal("expected error") } if result.Title != "Network status" { t.Fatalf("title=%q want %q", result.Title, "Network status") } } func TestParseStaticIPv4ConfigAndDefaults(t *testing.T) { t.Parallel() a := &App{ network: fakeNetwork{ defaultRouteFn: func() string { return " 192.168.1.1 " }, listInterfacesFn: func() ([]platform.InterfaceInfo, error) { return nil, nil }, dhcpOneFn: func(string) (string, error) { return "", nil }, dhcpAllFn: func() (string, error) { return "", nil }, setStaticIPv4Fn: func(platform.StaticIPv4Config) (string, error) { return "", nil }, }, runtime: fakeRuntime{ collectFn: func(string) (schema.RuntimeHealth, error) { return schema.RuntimeHealth{}, nil }, }, } defaults := a.DefaultStaticIPv4FormFields("eth0") if len(defaults) != 4 { t.Fatalf("len(defaults)=%d want 4", len(defaults)) } if defaults[1] != "24" || defaults[2] != "192.168.1.1" { t.Fatalf("unexpected defaults: %#v", defaults) } cfg := a.ParseStaticIPv4Config("eth0", []string{ " 10.10.0.5 ", " 23 ", " 10.10.0.1 ", " 1.1.1.1 8.8.8.8 ", }) if cfg.Interface != "eth0" || cfg.Address != "10.10.0.5" || cfg.Prefix != "23" || cfg.Gateway != "10.10.0.1" { t.Fatalf("unexpected cfg: %#v", cfg) } if len(cfg.DNS) != 2 || cfg.DNS[0] != "1.1.1.1" || cfg.DNS[1] != "8.8.8.8" { t.Fatalf("unexpected dns: %#v", cfg.DNS) } } func TestServiceActionResults(t *testing.T) { t.Parallel() a := &App{ services: fakeServices{ serviceStatusFn: func(name string) (string, error) { return "active", nil }, serviceDoFn: func(name string, action platform.ServiceAction) (string, error) { return string(action) + " ok", nil }, }, runtime: fakeRuntime{ collectFn: func(string) (schema.RuntimeHealth, error) { return schema.RuntimeHealth{}, nil }, }, } statusResult, err := a.ServiceStatusResult("bee-audit") if err != nil { t.Fatalf("ServiceStatusResult error: %v", err) } if statusResult.Title != "service status: bee-audit" || statusResult.Body != "active" { t.Fatalf("unexpected status result: %#v", statusResult) } actionResult, err := a.ServiceActionResult("bee-audit", platform.ServiceRestart) if err != nil { t.Fatalf("ServiceActionResult error: %v", err) } if actionResult.Title != "service restart: bee-audit" || actionResult.Body != "restart ok" { t.Fatalf("unexpected action result: %#v", actionResult) } } func TestToolCheckAndLogTailResults(t *testing.T) { t.Parallel() a := &App{ tools: fakeTools{ tailFileFn: func(path string, lines int) string { return path }, checkToolsFn: func(names []string) []platform.ToolStatus { return []platform.ToolStatus{ {Name: "dmidecode", OK: true, Path: "/usr/bin/dmidecode"}, {Name: "smartctl", OK: false}, } }, }, } toolsResult := a.ToolCheckResult([]string{"dmidecode", "smartctl"}) if toolsResult.Title != "Required tools" { t.Fatalf("title=%q want %q", toolsResult.Title, "Required tools") } if want := "- dmidecode: OK (/usr/bin/dmidecode)"; !contains(toolsResult.Body, want) { t.Fatalf("body missing %q\nbody=%s", want, toolsResult.Body) } if want := "- smartctl: MISSING"; !contains(toolsResult.Body, want) { t.Fatalf("body missing %q\nbody=%s", want, toolsResult.Body) } logResult := a.AuditLogTailResult() if logResult.Title != "Audit log tail" { t.Fatalf("title=%q want %q", logResult.Title, "Audit log tail") } if want := DefaultAuditLogPath + "\n\n" + DefaultAuditJSONPath; logResult.Body != want { t.Fatalf("body=%q want %q", logResult.Body, want) } } func TestActionResultsUseFallbackBody(t *testing.T) { t.Parallel() a := &App{ network: fakeNetwork{ dhcpOneFn: func(string) (string, error) { return " ", nil }, dhcpAllFn: func() (string, error) { return "", nil }, setStaticIPv4Fn: func(platform.StaticIPv4Config) (string, error) { return "", nil }, listInterfacesFn: func() ([]platform.InterfaceInfo, error) { return nil, nil }, defaultRouteFn: func() string { return "" }, }, services: fakeServices{ serviceStatusFn: func(string) (string, error) { return "", nil }, serviceDoFn: func(string, platform.ServiceAction) (string, error) { return "", nil }, }, tools: fakeTools{ tailFileFn: func(string, int) string { return " " }, checkToolsFn: func([]string) []platform.ToolStatus { return nil }, }, sat: fakeSAT{ runNvidiaFn: func(string) (string, error) { return "", nil }, runMemoryFn: func(string) (string, error) { return "", nil }, runStorageFn: func(string) (string, error) { return "", nil }, }, runtime: fakeRuntime{ collectFn: func(string) (schema.RuntimeHealth, error) { return schema.RuntimeHealth{Status: "PARTIAL", ExportDir: "/tmp/export"}, nil }, }, } if got, _ := a.DHCPOneResult("eth0"); got.Body != "DHCP completed." { t.Fatalf("dhcp one body=%q", got.Body) } if got, _ := a.DHCPAllResult(); got.Body != "DHCP completed." { t.Fatalf("dhcp all body=%q", got.Body) } if got, _ := a.SetStaticIPv4Result(platform.StaticIPv4Config{Interface: "eth0"}); got.Body != "Static IPv4 updated." { t.Fatalf("static body=%q", got.Body) } if got, _ := a.ServiceStatusResult("bee-audit"); got.Body != "No status output." { t.Fatalf("status body=%q", got.Body) } if got, _ := a.ServiceActionResult("bee-audit", platform.ServiceRestart); got.Body != "Action completed." { t.Fatalf("action body=%q", got.Body) } if got := a.ToolCheckResult(nil); got.Body != "No tools checked." { t.Fatalf("tool body=%q", got.Body) } if got := a.AuditLogTailResult(); got.Body != "No audit logs found." { t.Fatalf("log body=%q", got.Body) } if got, _ := a.RunNvidiaAcceptancePackResult(""); got.Body != "Archive written." { t.Fatalf("sat body=%q", got.Body) } if got, _ := a.RunMemoryAcceptancePackResult(""); got.Body != "No output produced." { t.Fatalf("memory sat body=%q", got.Body) } if got, _ := a.RunStorageAcceptancePackResult(""); got.Body != "No output produced." { t.Fatalf("storage sat body=%q", got.Body) } } func TestExportSupportBundleResultMentionsUnmountedUSB(t *testing.T) { t.Parallel() tmp := t.TempDir() oldExportDir := DefaultExportDir DefaultExportDir = tmp t.Cleanup(func() { DefaultExportDir = oldExportDir }) if err := os.WriteFile(filepath.Join(tmp, "bee-audit.json"), []byte("{}\n"), 0644); err != nil { t.Fatalf("write bee-audit.json: %v", err) } if err := os.WriteFile(filepath.Join(tmp, "bee-audit.log"), []byte("audit ok\n"), 0644); err != nil { t.Fatalf("write bee-audit.log: %v", err) } a := &App{ exports: fakeExports{ exportToTargetFn: func(src string, target platform.RemovableTarget) (string, error) { if filepath.Base(src) == "" { t.Fatalf("expected non-empty source path") } return "/media/bee/" + filepath.Base(src), nil }, }, } result, err := a.ExportSupportBundleResult(platform.RemovableTarget{Device: "/dev/sdb1"}) if err != nil { t.Fatalf("ExportSupportBundleResult error: %v", err) } if result.Title != "Export support bundle" { t.Fatalf("title=%q want %q", result.Title, "Export support bundle") } if want := "USB target unmounted and safe to remove."; !contains(result.Body, want) { t.Fatalf("body missing %q\nbody=%s", want, result.Body) } } func TestExportSupportBundleResultDoesNotPretendSuccessOnError(t *testing.T) { t.Parallel() tmp := t.TempDir() oldExportDir := DefaultExportDir DefaultExportDir = tmp t.Cleanup(func() { DefaultExportDir = oldExportDir }) if err := os.WriteFile(filepath.Join(tmp, "bee-audit.json"), []byte("{}\n"), 0644); err != nil { t.Fatalf("write bee-audit.json: %v", err) } if err := os.WriteFile(filepath.Join(tmp, "bee-audit.log"), []byte("audit ok\n"), 0644); err != nil { t.Fatalf("write bee-audit.log: %v", err) } a := &App{ exports: fakeExports{ exportToTargetFn: func(string, platform.RemovableTarget) (string, error) { return "", errors.New("mount /dev/sda1: exFAT support is missing in this ISO build") }, }, } result, err := a.ExportSupportBundleResult(platform.RemovableTarget{Device: "/dev/sda1", FSType: "exfat"}) if err == nil { t.Fatal("expected export error") } if contains(result.Body, "exported to") { t.Fatalf("body should not claim success:\n%s", result.Body) } if result.Body != "Support bundle export failed." { t.Fatalf("body=%q want %q", result.Body, "Support bundle export failed.") } } func TestRunNvidiaAcceptancePackResult(t *testing.T) { t.Parallel() a := &App{ sat: fakeSAT{ runNvidiaFn: func(baseDir string) (string, error) { if baseDir != "/tmp/sat" { t.Fatalf("baseDir=%q want %q", baseDir, "/tmp/sat") } return "/tmp/sat/out.tar.gz", nil }, runMemoryFn: func(string) (string, error) { return "", nil }, runStorageFn: func(string) (string, error) { return "", nil }, }, runtime: fakeRuntime{ collectFn: func(string) (schema.RuntimeHealth, error) { return schema.RuntimeHealth{}, nil }, }, } result, err := a.RunNvidiaAcceptancePackResult("/tmp/sat") if err != nil { t.Fatalf("RunNvidiaAcceptancePackResult error: %v", err) } if result.Title != "NVIDIA SAT" || result.Body != "Archive written to /tmp/sat/out.tar.gz" { t.Fatalf("unexpected result: %#v", result) } } func TestRunSATDefaultsToExportDir(t *testing.T) { t.Parallel() oldSATBaseDir := DefaultSATBaseDir DefaultSATBaseDir = "/tmp/export/bee-sat" t.Cleanup(func() { DefaultSATBaseDir = oldSATBaseDir }) a := &App{ sat: fakeSAT{ runNvidiaFn: func(baseDir string) (string, error) { if baseDir != "/tmp/export/bee-sat" { t.Fatalf("nvidia baseDir=%q", baseDir) } return "", nil }, runMemoryFn: func(baseDir string) (string, error) { if baseDir != "/tmp/export/bee-sat" { t.Fatalf("memory baseDir=%q", baseDir) } return "", nil }, runStorageFn: func(baseDir string) (string, error) { if baseDir != "/tmp/export/bee-sat" { t.Fatalf("storage baseDir=%q", baseDir) } return "", nil }, }, runtime: fakeRuntime{ collectFn: func(string) (schema.RuntimeHealth, error) { return schema.RuntimeHealth{}, nil }, }, } if _, err := a.RunNvidiaAcceptancePack("", nil); err != nil { t.Fatal(err) } if _, err := a.RunMemoryAcceptancePack("", nil); err != nil { t.Fatal(err) } if _, err := a.RunStorageAcceptancePack("", nil); err != nil { t.Fatal(err) } } func TestFormatSATSummary(t *testing.T) { t.Parallel() got := formatSATSummary("Memory SAT", "overall_status=PARTIAL\njob_ok=2\njob_failed=0\njob_unsupported=1\ndevices=3\n") want := "Memory SAT: PARTIAL ok=2 failed=0 unsupported=1\nDevices: 3" if got != want { t.Fatalf("got %q want %q", got, want) } } func TestHealthSummaryResultIncludesCompactSATSummary(t *testing.T) { tmp := t.TempDir() oldAuditPath := DefaultAuditJSONPath oldSATBaseDir := DefaultSATBaseDir DefaultAuditJSONPath = filepath.Join(tmp, "audit.json") DefaultSATBaseDir = filepath.Join(tmp, "sat") t.Cleanup(func() { DefaultAuditJSONPath = oldAuditPath }) t.Cleanup(func() { DefaultSATBaseDir = oldSATBaseDir }) satDir := filepath.Join(DefaultSATBaseDir, "memory-testcase") if err := os.MkdirAll(satDir, 0755); err != nil { t.Fatalf("mkdir sat dir: %v", err) } raw := `{"collected_at":"2026-03-15T10:00:00Z","hardware":{"board":{"serial_number":"SRV123"},"storage":[{"serial_number":"DISK1","status":"Warning"}]}}` if err := os.WriteFile(DefaultAuditJSONPath, []byte(raw), 0644); err != nil { t.Fatalf("write audit json: %v", err) } if err := os.WriteFile(filepath.Join(satDir, "summary.txt"), []byte("overall_status=OK\njob_ok=3\njob_failed=0\njob_unsupported=0\n"), 0644); err != nil { t.Fatalf("write sat summary: %v", err) } result := (&App{}).HealthSummaryResult() if !contains(result.Body, "Memory SAT: OK ok=3 failed=0") { t.Fatalf("body missing compact sat summary:\n%s", result.Body) } } func TestApplySATOverlayFiltersIgnoredLegacyDevices(t *testing.T) { tmp := t.TempDir() oldSATBaseDir := DefaultSATBaseDir DefaultSATBaseDir = filepath.Join(tmp, "sat") t.Cleanup(func() { DefaultSATBaseDir = oldSATBaseDir }) raw := `{ "collected_at": "2026-03-15T10:00:00Z", "hardware": { "board": {"serial_number": "SRV123"}, "storage": [ {"model": "Virtual HDisk0", "serial_number": "AAAABBBBCCCC3"}, {"model": "PASCARI", "serial_number": "DISK1", "status": "OK"} ], "pcie_devices": [ {"device_class": "Co-processor", "model": "402xx Series QAT", "status": "OK"}, {"device_class": "VideoController", "model": "NVIDIA H100", "status": "OK"} ] } }` got, err := ApplySATOverlay([]byte(raw)) if err != nil { t.Fatalf("ApplySATOverlay error: %v", err) } text := string(got) if contains(text, "Virtual HDisk0") { t.Fatalf("overlaid audit should drop virtual hdisk:\n%s", text) } if contains(text, "\"device_class\": \"Co-processor\"") { t.Fatalf("overlaid audit should drop co-processors:\n%s", text) } if !contains(text, "PASCARI") || !contains(text, "NVIDIA H100") { t.Fatalf("overlaid audit should keep real devices:\n%s", text) } } func TestBuildSupportBundleIncludesExportDirContents(t *testing.T) { tmp := t.TempDir() exportDir := filepath.Join(tmp, "export") if err := os.MkdirAll(filepath.Join(exportDir, "bee-sat", "memory-run"), 0755); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(exportDir, "bee-audit.json"), []byte(`{"collected_at":"2026-03-15T10:00:00Z","hardware":{"board":{"serial_number":"SRV123"},"storage":[{"model":"Virtual HDisk0","serial_number":"AAAABBBBCCCC3"},{"model":"PASCARI","serial_number":"DISK1"}],"pcie_devices":[{"device_class":"Co-processor","model":"402xx Series QAT"},{"device_class":"VideoController","model":"NVIDIA H100"}]}}`), 0644); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(exportDir, "bee-sat", "memory-run", "verbose.log"), []byte("sat verbose"), 0644); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(exportDir, "bee-sat", "memory-run.tar.gz"), []byte("nested sat archive"), 0644); err != nil { t.Fatal(err) } archive, err := BuildSupportBundle(exportDir) if err != nil { t.Fatalf("BuildSupportBundle error: %v", err) } if _, err := os.Stat(archive); err != nil { t.Fatalf("archive stat: %v", err) } file, err := os.Open(archive) if err != nil { t.Fatalf("open archive: %v", err) } defer file.Close() gzr, err := gzip.NewReader(file) if err != nil { t.Fatalf("gzip reader: %v", err) } defer gzr.Close() tr := tar.NewReader(gzr) var names []string var auditJSON string for { hdr, err := tr.Next() if errors.Is(err, io.EOF) { break } if err != nil { t.Fatalf("read tar entry: %v", err) } names = append(names, hdr.Name) if contains(hdr.Name, "/export/bee-audit.json") { body, err := io.ReadAll(tr) if err != nil { t.Fatalf("read audit entry: %v", err) } auditJSON = string(body) } } for _, want := range []string{ "/system/ip-link.txt", "/system/ip-link-stats.txt", "/system/ethtool-info.txt", "/system/ethtool-link.txt", "/system/ethtool-module.txt", "/system/mstflint-query.txt", } { var found bool for _, name := range names { if contains(name, want) { found = true break } } if !found { t.Fatalf("support bundle missing %s, names=%v", want, names) } } var foundRaw bool for _, name := range names { if contains(name, "/export/bee-sat/memory-run/verbose.log") { foundRaw = true } if contains(name, "/export/bee-sat/memory-run.tar.gz") { t.Fatalf("support bundle should not contain nested SAT archive: %s", name) } } if !foundRaw { t.Fatalf("support bundle missing raw SAT log, names=%v", names) } if contains(auditJSON, "Virtual HDisk0") || contains(auditJSON, "\"device_class\": \"Co-processor\"") { t.Fatalf("support bundle should normalize ignored devices:\n%s", auditJSON) } if !contains(auditJSON, "PASCARI") || !contains(auditJSON, "NVIDIA H100") { t.Fatalf("support bundle should keep real devices:\n%s", auditJSON) } } func TestMainBanner(t *testing.T) { tmp := t.TempDir() oldAuditPath := DefaultAuditJSONPath DefaultAuditJSONPath = filepath.Join(tmp, "audit.json") t.Cleanup(func() { DefaultAuditJSONPath = oldAuditPath }) trueValue := true manufacturer := "Dell" product := "PowerEdge R760" cpuModel := "Intel Xeon Gold 6430" memoryType := "DDR5" memorySerialA := "DIMM-A" memorySerialB := "DIMM-B" storageSerialA := "DISK-A" storageSerialB := "DISK-B" gpuClass := "VideoController" gpuModel := "NVIDIA H100" payload := schema.HardwareIngestRequest{ Hardware: schema.HardwareSnapshot{ Board: schema.HardwareBoard{ Manufacturer: &manufacturer, ProductName: &product, SerialNumber: "SRV123", }, CPUs: []schema.HardwareCPU{ {Model: &cpuModel}, {Model: &cpuModel}, }, Memory: []schema.HardwareMemory{ {Present: &trueValue, SizeMB: intPtr(524288), Type: &memoryType, SerialNumber: &memorySerialA}, {Present: &trueValue, SizeMB: intPtr(524288), Type: &memoryType, SerialNumber: &memorySerialB}, }, Storage: []schema.HardwareStorage{ {Present: &trueValue, SizeGB: intPtr(3840), SerialNumber: &storageSerialA}, {Present: &trueValue, SizeGB: intPtr(3840), SerialNumber: &storageSerialB}, }, PCIeDevices: []schema.HardwarePCIeDevice{ {DeviceClass: &gpuClass, Model: &gpuModel}, {DeviceClass: &gpuClass, Model: &gpuModel}, }, }, } raw, err := json.Marshal(payload) if err != nil { t.Fatalf("marshal: %v", err) } if err := os.WriteFile(DefaultAuditJSONPath, raw, 0644); err != nil { t.Fatalf("write audit json: %v", err) } a := &App{ network: fakeNetwork{ listInterfacesFn: func() ([]platform.InterfaceInfo, error) { return []platform.InterfaceInfo{ {Name: "eth0", IPv4: []string{"10.0.0.10"}}, {Name: "eth1", IPv4: []string{"192.168.1.10"}}, }, nil }, }, } got := a.MainBanner() for _, want := range []string{ "System: Dell PowerEdge R760 | S/N SRV123", "CPU: 2 x Intel Xeon Gold 6430", "Memory: 1.0 TB DDR5 (2 DIMMs)", "Storage: 2 drives / 7.5 TB", "GPU: 2 x NVIDIA H100", "IP: 10.0.0.10, 192.168.1.10", } { if !contains(got, want) { t.Fatalf("banner missing %q:\n%s", want, got) } } } func TestRuntimeHealthResultUsesAMDLabels(t *testing.T) { tmp := t.TempDir() oldRuntimePath := DefaultRuntimeJSONPath DefaultRuntimeJSONPath = filepath.Join(tmp, "runtime-health.json") t.Cleanup(func() { DefaultRuntimeJSONPath = oldRuntimePath }) raw, err := json.Marshal(schema.RuntimeHealth{ Status: "OK", ExportDir: "/appdata/bee/export", DriverReady: true, CUDAReady: true, NetworkStatus: "OK", }) if err != nil { t.Fatalf("marshal runtime health: %v", err) } if err := os.WriteFile(DefaultRuntimeJSONPath, raw, 0644); err != nil { t.Fatalf("write runtime health: %v", err) } a := &App{ sat: fakeSAT{ detectVendorFn: func() string { return "amd" }, }, } result := a.RuntimeHealthResult() if !contains(result.Body, "AMDGPU ready: true") { t.Fatalf("body missing AMD driver label:\n%s", result.Body) } if !contains(result.Body, "ROCm SMI ready: true") { t.Fatalf("body missing ROCm label:\n%s", result.Body) } if contains(result.Body, "CUDA ready") { t.Fatalf("body should not mention CUDA on AMD:\n%s", result.Body) } } func intPtr(v int) *int { return &v } func contains(haystack, needle string) bool { return len(needle) == 0 || (len(haystack) >= len(needle) && (haystack == needle || containsAt(haystack, needle))) } func containsAt(haystack, needle string) bool { for i := 0; i+len(needle) <= len(haystack); i++ { if haystack[i:i+len(needle)] == needle { return true } } return false }