health check: the last six producers carry their dashboard sentence (R-79 option A, D3)
Docker unreachable, protected container down, and the four storage-path entries now carry a bundle key beside their wire text; the wire text is unchanged byte for byte. Hungarian values of the four storage keys equal the frozen formats (i18n_go_parity). Red-proven: a zero MsgRef on the unavailable-path warning fails TestR79_RemainingProducersCarryTheirDashboardSentence and TestR79_HealthBannersFollowTheHousehold (producer-driven, English household sees Hungarian). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -1,9 +1,14 @@
|
||||
package monitor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/config"
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/settings"
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/system"
|
||||
)
|
||||
|
||||
@@ -62,3 +67,79 @@ func TestR516_ResourceWarningsCarryTheirDashboardSentence(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// R-79 option A (operator ruling D3, 2026-10-08) — the six producers R-516 item 10 left verbatim:
|
||||
// Docker unreachable, a protected container down, and the four storage-path entries. Each now
|
||||
// carries its dashboard sentence; the wire text is byte for byte what it was (it is ON THE WIRE,
|
||||
// report health.*; the frozen storage formats are also pinned by TestStorageWarningFormatsAreFrozen).
|
||||
//
|
||||
// COMPANION RED-PROOF: give any one of them a zero MsgRef (e.g. the unavailable-path warning back to
|
||||
// addWarning) — its case fails here, and TestR79_StorageBannerFollowsTheHousehold in internal/web
|
||||
// shows the Hungarian wire text to an English household again.
|
||||
func TestR79_RemainingProducersCarryTheirDashboardSentence(t *testing.T) {
|
||||
type entry struct{ wire, key string }
|
||||
check := func(name string, texts []string, msgs func(int) MsgRef, want []entry) {
|
||||
t.Helper()
|
||||
if len(texts) != len(want) {
|
||||
t.Fatalf("%s: %d entries %q, want %d — the cases below would be compared against nothing", name, len(texts), texts, len(want))
|
||||
}
|
||||
for i := range texts {
|
||||
if texts[i] != want[i].wire {
|
||||
t.Errorf("%s: the wire text moved: %q, want %q", name, texts[i], want[i].wire)
|
||||
}
|
||||
if k := msgs(i).Key; k != want[i].key {
|
||||
t.Errorf("%s: %q carries dashboard key %q, want %q", name, texts[i], k, want[i].key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Docker and protected containers: driven through the same adders RunHealthCheck calls.
|
||||
r := &HealthReport{}
|
||||
addDockerIssue(r, fmt.Errorf("docker not reachable: exit status 1"))
|
||||
addProtectedIssues(r, []string{"cloudflared", "traefik"})
|
||||
check("docker+protected", r.Issues, r.IssueMsgAt, []entry{
|
||||
{"Docker: docker not reachable: exit status 1", "health.docker_unreachable"},
|
||||
{"Protected container not running: cloudflared", "health.protected_container_down"},
|
||||
{"Protected container not running: traefik", "health.protected_container_down"},
|
||||
})
|
||||
if a := r.IssueMsgAt(1).Args; len(a) != 1 || a[0] != "cloudflared" {
|
||||
t.Errorf("protected-container sentence args = %v, want [cloudflared]", a)
|
||||
}
|
||||
|
||||
// Storage paths: a missing path, a path that is not a mount point at 92 %, one at 97 %.
|
||||
oldMount, oldUsage := isMountPointFn, diskUsageFn
|
||||
defer func() { isMountPointFn, diskUsageFn = oldMount, oldUsage }()
|
||||
isMountPointFn = func(p string) bool { return !strings.HasSuffix(p, "/notsep") }
|
||||
diskUsageFn = func(p string) *system.DiskUsageInfo {
|
||||
switch {
|
||||
case strings.HasSuffix(p, "/notsep"):
|
||||
return &system.DiskUsageInfo{UsedPercent: 92}
|
||||
case strings.HasSuffix(p, "/full"):
|
||||
return &system.DiskUsageInfo{UsedPercent: 97}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
dir := t.TempDir()
|
||||
for _, sub := range []string{"notsep", "full"} {
|
||||
if err := os.Mkdir(filepath.Join(dir, sub), 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
missing := filepath.Join(dir, "missing")
|
||||
r = &HealthReport{}
|
||||
addStorage(r, []settings.StoragePath{{Path: missing}, {Path: dir + "/notsep"}, {Path: dir + "/full"}})
|
||||
check("storage warnings", r.Warnings, r.WarningMsgAt, []entry{
|
||||
{"Adattároló nem elérhető: " + missing, "health.storage_unavailable"},
|
||||
{"Az adattároló (" + dir + "/notsep) nem külön meghajtón van — az adatok a rendszermeghajtóra íródnak", "health.storage_not_separate"},
|
||||
{"Adattároló használat magas: " + dir + "/notsep (92%)", "health.storage_usage_high"},
|
||||
})
|
||||
check("storage issues", r.Issues, r.IssueMsgAt, []entry{
|
||||
{"Adattároló majdnem megtelt: " + dir + "/full (97%)", "health.storage_almost_full"},
|
||||
})
|
||||
if len(r.Warnings) != len(r.WarningKinds) || len(r.Warnings) != len(r.WarningMsgs) || len(r.Issues) != len(r.IssueMsgs) {
|
||||
t.Errorf("storage: the parallel slices drifted apart")
|
||||
}
|
||||
if got := r.WarningKindAt(1); got != WarnKindStorageNotSeparate {
|
||||
t.Errorf("not-separate warning lost its kind: %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user