Files
porthole/internal/collectors/host/mem_test.go
OpenCode Test 1421b4659e feat: implement ControlTower TUI for cluster and host monitoring
Add complete TUI application for monitoring Kubernetes clusters and host
systems. Features include:

Core features:
- Collector framework with concurrent scheduling
- Host collectors: disk, memory, load, network
- Kubernetes collectors: pods, nodes, workloads, events with informers
- Issue deduplication, state management, and resolve-after logic
- Bubble Tea TUI with table view, details pane, and filtering
- JSON export functionality

UX improvements:
- Help overlay with keybindings
- Priority/category filters with visual indicators
- Direct priority jump (0/1/2/3)
- Bulk acknowledge (Shift+A)
- Clipboard copy (y)
- Theme toggle (T)
- Age format toggle (d)
- Wide title toggle (t)
- Vi-style navigation (j/k)
- Home/End jump (g/G)
- Rollup drill-down in details

Robustness:
- Grace period for unreachable clusters
- Rollups for high-volume issues
- Flap suppression
- RBAC error handling

Files: All core application code with tests for host collectors,
engine, store, model, and export packages.
2025-12-24 13:29:51 -08:00

84 lines
2.3 KiB
Go

package host
import (
"testing"
"time"
"tower/internal/model"
)
func TestParseProcMeminfo(t *testing.T) {
in := "MemTotal: 8000000 kB\nMemAvailable: 800000 kB\nSwapTotal: 2000000 kB\nSwapFree: 500000 kB\n"
m := parseProcMeminfo(in)
if m["MemTotal"] != 8000000 {
t.Fatalf("MemTotal mismatch: %d", m["MemTotal"])
}
if m["MemAvailable"] != 800000 {
t.Fatalf("MemAvailable mismatch: %d", m["MemAvailable"])
}
}
func TestDesiredMemPriority(t *testing.T) {
p, w := desiredMemPriority(16.0)
if p != "" || w != 0 {
t.Fatalf("expected none")
}
p, w = desiredMemPriority(15.0)
if p != model.PriorityP2 || w != 60*time.Second {
t.Fatalf("expected P2/60s got %v/%v", p, w)
}
p, w = desiredMemPriority(10.0)
if p != model.PriorityP1 {
t.Fatalf("expected P1 got %v", p)
}
p, w = desiredMemPriority(5.0)
if p != model.PriorityP0 || w != 30*time.Second {
t.Fatalf("expected P0/30s got %v/%v", p, w)
}
}
func TestDesiredSwapPriority(t *testing.T) {
// No swap configured.
p, _ := desiredSwapPriority(4.0, 0, 90.0)
if p != "" {
t.Fatalf("expected none when SwapTotal=0")
}
p, w := desiredSwapPriority(4.0, 1000, 80.0)
if p != model.PriorityP0 || w != 30*time.Second {
t.Fatalf("expected P0/30s got %v/%v", p, w)
}
p, w = desiredSwapPriority(9.9, 1000, 50.0)
if p != model.PriorityP1 || w != 60*time.Second {
t.Fatalf("expected P1/60s got %v/%v", p, w)
}
// Swap high but RAM not tight => no issue.
p, _ = desiredSwapPriority(20.0, 1000, 90.0)
if p != "" {
t.Fatalf("expected none when RAM not tight")
}
}
func TestUpdateSustained(t *testing.T) {
now := time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC)
p, since := updateSustained(now, "", time.Time{}, model.PriorityP1)
if p != model.PriorityP1 || !since.Equal(now) {
t.Fatalf("expected set to P1 at now")
}
p2, since2 := updateSustained(now.Add(1*time.Second), p, since, model.PriorityP1)
if p2 != model.PriorityP1 || !since2.Equal(since) {
t.Fatalf("expected unchanged since")
}
p3, since3 := updateSustained(now.Add(2*time.Second), p2, since2, model.PriorityP0)
if p3 != model.PriorityP0 || !since3.Equal(now.Add(2*time.Second)) {
t.Fatalf("expected reset on priority change")
}
p4, since4 := updateSustained(now.Add(3*time.Second), p3, since3, "")
if p4 != "" || !since4.IsZero() {
t.Fatalf("expected cleared")
}
}