package upsquality import ( "context" "os" "path/filepath" "strings" "testing" "scm.bstein.dev/bstein/ananke/internal/ups" ) // TestNUTProviderReadCommandFailure runs one orchestration or CLI step. // Signature: TestNUTProviderReadCommandFailure(t *testing.T). // Why: ensures upsc execution failures are surfaced with target context. func TestNUTProviderReadCommandFailure(t *testing.T) { dir := t.TempDir() upsc := filepath.Join(dir, "upsc") script := "#!/usr/bin/env sh\necho boom >&2\nexit 7\n" if err := os.WriteFile(upsc, []byte(script), 0o755); err != nil { t.Fatalf("write fake upsc: %v", err) } t.Setenv("PATH", dir+":"+os.Getenv("PATH")) p := ups.NewNUTProvider("statera@localhost") _, err := p.Read(context.Background()) if err == nil || !strings.Contains(err.Error(), "upsc statera@localhost") { t.Fatalf("expected contextual upsc failure, got %v", err) } } // TestNUTProviderReadCoversNumericParseFailureBranch runs one orchestration or CLI step. // Signature: TestNUTProviderReadCoversNumericParseFailureBranch(t *testing.T). // Why: exercises parseFloat failure branch after symbol stripping. func TestNUTProviderReadCoversNumericParseFailureBranch(t *testing.T) { dir := t.TempDir() upsc := filepath.Join(dir, "upsc") script := `#!/usr/bin/env sh cat <<'EOF' ups.status: OB battery.runtime: 10 battery.charge: ++ ups.load: -- ups.realpower.nominal: .. EOF ` if err := os.WriteFile(upsc, []byte(script), 0o755); err != nil { t.Fatalf("write fake upsc: %v", err) } t.Setenv("PATH", dir+":"+os.Getenv("PATH")) p := ups.NewNUTProvider("pyrphoros@localhost") sample, err := p.Read(context.Background()) if err != nil { t.Fatalf("read sample: %v", err) } if !sample.OnBattery { t.Fatalf("expected OB status to set OnBattery, got %+v", sample) } if sample.BatteryCharge != 0 || sample.LoadPercent != 0 || sample.NominalPowerW != 0 { t.Fatalf("expected parse failures to leave numeric fields at zero, got %+v", sample) } } // TestNUTProviderReadScannerTooLongError runs one orchestration or CLI step. // Signature: TestNUTProviderReadScannerTooLongError(t *testing.T). // Why: covers scanner error handling branch for malformed oversized NUT output lines. func TestNUTProviderReadScannerTooLongError(t *testing.T) { dir := t.TempDir() upsc := filepath.Join(dir, "upsc") long := strings.Repeat("x", 80*1024) script := "#!/usr/bin/env sh\nprintf '%s\\n' '" + long + "'\n" if err := os.WriteFile(upsc, []byte(script), 0o755); err != nil { t.Fatalf("write fake upsc: %v", err) } t.Setenv("PATH", dir+":"+os.Getenv("PATH")) p := ups.NewNUTProvider("oversize@localhost") if _, err := p.Read(context.Background()); err == nil { t.Fatalf("expected scanner token-size parse error") } }