summaryrefslogtreecommitdiff
path: root/internal/display
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-02-18 19:23:54 +0200
committerPaul Buetow <paul@buetow.org>2026-02-18 19:23:54 +0200
commit3cc9d42252b7d5f9c24c10ef748cff1d2e1bbd67 (patch)
tree1118ef7b2cf4988780e0c3fbc4ec64a4ae211e13 /internal/display
parentf7887117c5269ed0336cc058c78c4b222e0e6b34 (diff)
fix: make disk bars visible when idle, filter zram devices, add rendering test
- Draw dim purple background (#180028) instead of black so disk bar slots are visible even when the disk is idle - First sample no longer returns early; records baseline and still draws the bar background - Filter out zram devices from whole-disk detection - Add TestDiskBar_Rendering: end-to-end pixel test verifying purple bars appear after two disk data samples Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/display')
-rw-r--r--internal/display/disk.go15
-rw-r--r--internal/display/display_test.go77
2 files changed, 85 insertions, 7 deletions
diff --git a/internal/display/disk.go b/internal/display/disk.go
index 0143b68..9d03ba9 100644
--- a/internal/display/disk.go
+++ b/internal/display/disk.go
@@ -18,7 +18,7 @@ var nvmePartition = regexp.MustCompile(`^nvme\d+n\d+p\d+$`)
// isWholeDisk returns true if the device name represents a whole disk (not a partition,
// loop, ram, or device-mapper device). Used to filter /proc/diskstats entries.
func isWholeDisk(name string) bool {
- if strings.HasPrefix(name, "loop") || strings.HasPrefix(name, "ram") || strings.HasPrefix(name, "dm-") {
+ if strings.HasPrefix(name, "loop") || strings.HasPrefix(name, "ram") || strings.HasPrefix(name, "dm-") || strings.HasPrefix(name, "zram") {
return false
}
if partitionSuffix.MatchString(name) {
@@ -116,22 +116,23 @@ func updateDiskPeak(snap map[string]*stats.HostStats, state *runState, diskMax f
// drawDiskBarSmoothed draws a single disk bar with read (top, purple) and write (bottom,
// darker purple). Returns the current DiskStamp to be stored as previous for the next frame.
func drawDiskBarSmoothed(renderer *sdl.Renderer, cur stats.DiskStamp, cfg *runState, smoothed *struct{ readPct, writePct float64 }, prev stats.DiskStamp, factor float64, barW, x, y, barH int32, extended bool) stats.DiskStamp {
- // Clear this slot to black
- renderer.SetDrawColor(constants.Black.R, constants.Black.G, constants.Black.B, 255)
+ // Clear this slot to a dim purple so the bar is visible even when idle.
+ // This distinguishes "disk bar present but idle" from background.
+ renderer.SetDrawColor(0x18, 0x00, 0x28, 255)
renderer.FillRect(&sdl.Rect{X: x, Y: y, W: barW, H: barH})
// Only recompute when the collector has provided new data (same guard as net bars).
if cur.Stamp > prev.Stamp && prev.Stamp > 0 {
prev = smoothDiskUtilization(cur, prev, cfg, smoothed, factor)
- } else if prev.Stamp == 0 {
- // First sample: record but don't draw yet (no delta available)
- return cur
+ } else if prev.Stamp == 0 && cur.Stamp > 0 {
+ // First sample: record it but can't compute delta yet.
+ prev = cur
}
drawDiskHalves(renderer, smoothed, x, y, barW, barH)
// In extended mode, overlay a utilization % line
- if extended {
+ if extended && prev.Stamp > 0 {
drawDiskUtilLine(renderer, cur, prev, cfg, x, y, barW, barH)
}
return prev
diff --git a/internal/display/display_test.go b/internal/display/display_test.go
index a587818..6a2d8fe 100644
--- a/internal/display/display_test.go
+++ b/internal/display/display_test.go
@@ -1819,3 +1819,80 @@ func TestCountBars_WithDisk(t *testing.T) {
t.Errorf("DiskModeDevices: expected 3, got %d", n)
}
}
+
+func TestDiskBar_Rendering(t *testing.T) {
+ // End-to-end: two disk snapshots with different sector counts → visible purple bars
+ const w, h int32 = 200, 100
+
+ renderer, surface, err := createTestRenderer(w, h)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer renderer.Destroy()
+ defer surface.Free()
+
+ prev, cur := makeCPUPair(50, 30, 20)
+ cfg := defaultTestConfig()
+ cfg.CPUMode = constants.CPUModeAverage
+ cfg.ShowMem = false
+ cfg.ShowNet = false
+ cfg.DiskMode = constants.DiskModeAggregate
+
+ // First snapshot: disk data at t=1.0
+ src1 := &mockSource{
+ data: map[string]*stats.HostStats{
+ "host1": {
+ CPU: map[string]collector.CPULine{"cpu": cur},
+ Disk: map[string]stats.DiskStamp{
+ "sda": {SectorsRead: 0, SectorsWrite: 0, IoTicks: 0, Stamp: 1.0},
+ },
+ },
+ },
+ }
+
+ state := newRunState(cfg, w, h)
+ state.prevCPU["host1;cpu"] = prev
+
+ // Frame 1: establishes the first disk sample (no bars drawn yet for disk)
+ drawFrame(renderer, src1, cfg, state)
+
+ t.Logf("After frame 1: prevDisk=%+v", state.prevDisk)
+ t.Logf("After frame 1: smoothedDisk=%+v", state.smoothedDisk)
+ t.Logf("After frame 1: diskPeak=%f", state.diskPeak)
+
+ // Verify bar count: 1 CPU + 1 disk = 2 bars → each 100px wide
+ snap := src1.Snapshot()
+ numBars := countBars(snap, state.cpuMode, state.showMem, state.showNet, state.showLoad, state.diskMode)
+ t.Logf("numBars = %d (expected 2)", numBars)
+ if numBars != 2 {
+ t.Errorf("expected 2 bars (1 CPU + 1 disk), got %d", numBars)
+ }
+
+ // Second snapshot: disk data at t=4.0 with 100000 sectors read (= 51.2MB in 3s ≈ 17MB/s)
+ src2 := &mockSource{
+ data: map[string]*stats.HostStats{
+ "host1": {
+ CPU: map[string]collector.CPULine{"cpu": cur},
+ Disk: map[string]stats.DiskStamp{
+ "sda": {SectorsRead: 100000, SectorsWrite: 50000, IoTicks: 500, Stamp: 4.0},
+ },
+ },
+ },
+ }
+
+ // Frame 2: now delta is available, bars should draw purple
+ drawFrame(renderer, src2, cfg, state)
+
+ t.Logf("After frame 2: prevDisk=%+v", state.prevDisk)
+ t.Logf("After frame 2: smoothedDisk=%+v", state.smoothedDisk)
+ t.Logf("After frame 2: diskPeak=%f", state.diskPeak)
+
+ // Disk bar at x=100..199 (second bar). Check for purple (DiskRead) at the top.
+ r, g, b := getPixelColor(surface, 150, 5)
+ t.Logf("Pixel at (150,5) = RGB(%d,%d,%d), want DiskRead=%+v", r, g, b, constants.DiskRead)
+
+ // The bar should have some purple (DiskRead) near the top
+ if r == 0 && g == 0 && b == 0 {
+ t.Errorf("disk bar at (150,5) is black; expected some DiskRead purple color")
+ }
+}