diff options
| -rw-r--r-- | internal/display/disk.go | 15 | ||||
| -rw-r--r-- | internal/display/display_test.go | 77 |
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") + } +} |
