1
0
mirror of https://github.com/tw93/Mole.git synced 2026-02-04 11:31:46 +00:00
Files
Mole/cmd/status/view_test.go
tw93 64f79a59d8 feat: optimize log system and add mo log command
- Add get_timestamp() helper and optimize log rotation
- Create mo log viewer with search/filter capabilities
- Improve test coverage to 18.4% with better assertions
- Add security fixes for grep injection prevention
2026-01-28 19:46:01 +08:00

371 lines
9.0 KiB
Go

package main
import "testing"
func TestFormatRate(t *testing.T) {
tests := []struct {
name string
input float64
want string
}{
// Below threshold (< 0.01).
{"zero", 0, "0 MB/s"},
{"tiny", 0.001, "0 MB/s"},
{"just under threshold", 0.009, "0 MB/s"},
// Small rates (0.01 to < 1) — 2 decimal places.
{"at threshold", 0.01, "0.01 MB/s"},
{"small rate", 0.5, "0.50 MB/s"},
{"just under 1", 0.99, "0.99 MB/s"},
// Medium rates (1 to < 10) — 1 decimal place.
{"exactly 1", 1.0, "1.0 MB/s"},
{"medium rate", 5.5, "5.5 MB/s"},
{"just under 10", 9.9, "9.9 MB/s"},
// Large rates (>= 10) — no decimal places.
{"exactly 10", 10.0, "10 MB/s"},
{"large rate", 100.5, "100 MB/s"},
{"very large", 1000.0, "1000 MB/s"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := formatRate(tt.input)
if got != tt.want {
t.Errorf("formatRate(%v) = %q, want %q", tt.input, got, tt.want)
}
})
}
}
func TestColorizePercent(t *testing.T) {
tests := []struct {
name string
percent float64
input string
expectDanger bool
expectWarn bool
expectOk bool
}{
{"low usage", 30.0, "30%", false, false, true},
{"just below warn", 59.9, "59.9%", false, false, true},
{"at warn threshold", 60.0, "60%", false, true, false},
{"mid range", 70.0, "70%", false, true, false},
{"just below danger", 84.9, "84.9%", false, true, false},
{"at danger threshold", 85.0, "85%", true, false, false},
{"high usage", 95.0, "95%", true, false, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := colorizePercent(tt.percent, tt.input)
if got == "" {
t.Errorf("colorizePercent(%v, %q) returned empty string", tt.percent, tt.input)
return
}
expected := ""
if tt.expectDanger {
expected = dangerStyle.Render(tt.input)
} else if tt.expectWarn {
expected = warnStyle.Render(tt.input)
} else if tt.expectOk {
expected = okStyle.Render(tt.input)
}
if got != expected {
t.Errorf("colorizePercent(%v, %q) = %q, want %q (danger=%v warn=%v ok=%v)",
tt.percent, tt.input, got, expected, tt.expectDanger, tt.expectWarn, tt.expectOk)
}
})
}
}
func TestColorizeBattery(t *testing.T) {
tests := []struct {
name string
percent float64
input string
expectDanger bool
expectWarn bool
expectOk bool
}{
{"critical low", 10.0, "10%", true, false, false},
{"just below low", 19.9, "19.9%", true, false, false},
{"at low threshold", 20.0, "20%", false, true, false},
{"mid range", 35.0, "35%", false, true, false},
{"just below ok", 49.9, "49.9%", false, true, false},
{"at ok threshold", 50.0, "50%", false, false, true},
{"healthy", 80.0, "80%", false, false, true},
{"full", 100.0, "100%", false, false, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := colorizeBattery(tt.percent, tt.input)
if got == "" {
t.Errorf("colorizeBattery(%v, %q) returned empty string", tt.percent, tt.input)
return
}
expected := ""
if tt.expectDanger {
expected = dangerStyle.Render(tt.input)
} else if tt.expectWarn {
expected = warnStyle.Render(tt.input)
} else if tt.expectOk {
expected = okStyle.Render(tt.input)
}
if got != expected {
t.Errorf("colorizeBattery(%v, %q) = %q, want %q (danger=%v warn=%v ok=%v)",
tt.percent, tt.input, got, expected, tt.expectDanger, tt.expectWarn, tt.expectOk)
}
})
}
}
func TestShorten(t *testing.T) {
tests := []struct {
name string
input string
maxLen int
want string
}{
// No truncation needed.
{"empty string", "", 10, ""},
{"shorter than max", "hello", 10, "hello"},
{"exactly at max", "hello", 5, "hello"},
// Truncation needed.
{"one over max", "hello!", 5, "hell…"},
{"much longer", "hello world", 5, "hell…"},
// Edge cases.
{"maxLen 1", "hello", 1, "…"},
{"maxLen 2", "hello", 2, "h…"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := shorten(tt.input, tt.maxLen)
if got != tt.want {
t.Errorf("shorten(%q, %d) = %q, want %q", tt.input, tt.maxLen, got, tt.want)
}
})
}
}
func TestHumanBytesShort(t *testing.T) {
tests := []struct {
name string
input uint64
want string
}{
// Zero and small values.
{"zero", 0, "0"},
{"one byte", 1, "1"},
{"999 bytes", 999, "999"},
// Kilobyte boundaries.
{"exactly 1KB", 1 << 10, "1K"},
{"just under 1KB", (1 << 10) - 1, "1023"},
{"1.5KB rounds to 2K", 1536, "2K"},
{"999KB", 999 << 10, "999K"},
// Megabyte boundaries.
{"exactly 1MB", 1 << 20, "1M"},
{"just under 1MB", (1 << 20) - 1, "1024K"},
{"500MB", 500 << 20, "500M"},
// Gigabyte boundaries.
{"exactly 1GB", 1 << 30, "1G"},
{"just under 1GB", (1 << 30) - 1, "1024M"},
{"100GB", 100 << 30, "100G"},
// Terabyte boundaries.
{"exactly 1TB", 1 << 40, "1T"},
{"just under 1TB", (1 << 40) - 1, "1024G"},
{"2TB", 2 << 40, "2T"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := humanBytesShort(tt.input)
if got != tt.want {
t.Errorf("humanBytesShort(%d) = %q, want %q", tt.input, got, tt.want)
}
})
}
}
func TestHumanBytes(t *testing.T) {
tests := []struct {
name string
input uint64
want string
}{
// Zero and small values.
{"zero", 0, "0 B"},
{"one byte", 1, "1 B"},
{"1023 bytes", 1023, "1023 B"},
// Kilobyte boundaries (uses > not >=).
{"exactly 1KB", 1 << 10, "1024 B"},
{"just over 1KB", (1 << 10) + 1, "1.0 KB"},
{"1.5KB", 1536, "1.5 KB"},
// Megabyte boundaries (uses > not >=).
{"exactly 1MB", 1 << 20, "1024.0 KB"},
{"just over 1MB", (1 << 20) + 1, "1.0 MB"},
{"500MB", 500 << 20, "500.0 MB"},
// Gigabyte boundaries (uses > not >=).
{"exactly 1GB", 1 << 30, "1024.0 MB"},
{"just over 1GB", (1 << 30) + 1, "1.0 GB"},
{"100GB", 100 << 30, "100.0 GB"},
// Terabyte boundaries (uses > not >=).
{"exactly 1TB", 1 << 40, "1024.0 GB"},
{"just over 1TB", (1 << 40) + 1, "1.0 TB"},
{"2TB", 2 << 40, "2.0 TB"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := humanBytes(tt.input)
if got != tt.want {
t.Errorf("humanBytes(%d) = %q, want %q", tt.input, got, tt.want)
}
})
}
}
func TestHumanBytesCompact(t *testing.T) {
tests := []struct {
name string
input uint64
want string
}{
// Zero and small values.
{"zero", 0, "0"},
{"one byte", 1, "1"},
{"1023 bytes", 1023, "1023"},
// Kilobyte boundaries (uses >= not >).
{"exactly 1KB", 1 << 10, "1.0K"},
{"1.5KB", 1536, "1.5K"},
// Megabyte boundaries.
{"exactly 1MB", 1 << 20, "1.0M"},
{"500MB", 500 << 20, "500.0M"},
// Gigabyte boundaries.
{"exactly 1GB", 1 << 30, "1.0G"},
{"100GB", 100 << 30, "100.0G"},
// Terabyte boundaries.
{"exactly 1TB", 1 << 40, "1.0T"},
{"2TB", 2 << 40, "2.0T"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := humanBytesCompact(tt.input)
if got != tt.want {
t.Errorf("humanBytesCompact(%d) = %q, want %q", tt.input, got, tt.want)
}
})
}
}
func TestSplitDisks(t *testing.T) {
tests := []struct {
name string
disks []DiskStatus
wantInternal int
wantExternal int
}{
{
name: "empty slice",
disks: []DiskStatus{},
wantInternal: 0,
wantExternal: 0,
},
{
name: "all internal",
disks: []DiskStatus{
{Mount: "/", External: false},
{Mount: "/System", External: false},
},
wantInternal: 2,
wantExternal: 0,
},
{
name: "all external",
disks: []DiskStatus{
{Mount: "/Volumes/USB", External: true},
{Mount: "/Volumes/Backup", External: true},
},
wantInternal: 0,
wantExternal: 2,
},
{
name: "mixed",
disks: []DiskStatus{
{Mount: "/", External: false},
{Mount: "/Volumes/USB", External: true},
{Mount: "/System", External: false},
},
wantInternal: 2,
wantExternal: 1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
internal, external := splitDisks(tt.disks)
if len(internal) != tt.wantInternal {
t.Errorf("splitDisks() internal count = %d, want %d", len(internal), tt.wantInternal)
}
if len(external) != tt.wantExternal {
t.Errorf("splitDisks() external count = %d, want %d", len(external), tt.wantExternal)
}
})
}
}
func TestDiskLabel(t *testing.T) {
tests := []struct {
name string
prefix string
index int
total int
want string
}{
// Single disk — no numbering.
{"single disk", "INTR", 0, 1, "INTR"},
{"single external", "EXTR", 0, 1, "EXTR"},
// Multiple disks — numbered (1-indexed).
{"first of two", "INTR", 0, 2, "INTR1"},
{"second of two", "INTR", 1, 2, "INTR2"},
{"third of three", "EXTR", 2, 3, "EXTR3"},
// Edge case: total 0 treated as single.
{"total zero", "DISK", 0, 0, "DISK"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := diskLabel(tt.prefix, tt.index, tt.total)
if got != tt.want {
t.Errorf("diskLabel(%q, %d, %d) = %q, want %q", tt.prefix, tt.index, tt.total, got, tt.want)
}
})
}
}