feat(cli): upgrade command, rich status, and version cache
- Replace `upgrade` stub with real command (alias for `self-update`) - Also register `update` as alias: `unarr update` works too - Rewrite `status` to show full config, disk usage, daemon state, and update availability with colored sections - Add version check cache (1h TTL) so `status` is instant on repeat runs - Guard against division by zero on empty filesystems - Guard against negative durations from clock skew - Guard against stale PID via heartbeat recency check (2 min) - Add comprehensive test coverage across agent, engine, upgrade, usenet, arr, library, mediaserver, and UI packages - Improve Makefile coverage target to exclude cmd/ glue code - Fix stream handler resource cleanup and ffprobe error handling
This commit is contained in:
parent
01d62ffa13
commit
3e0f3a5a64
33 changed files with 7084 additions and 65 deletions
55
internal/cmd/daemon_test.go
Normal file
55
internal/cmd/daemon_test.go
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
package cmd
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestDeriveWSURL(t *testing.T) {
|
||||
tests := []struct {
|
||||
apiURL string
|
||||
agentID string
|
||||
want string
|
||||
}{
|
||||
{"https://torrentclaw.com", "agent-123", "wss://unarr.torrentclaw.com/ws/agent-123"},
|
||||
{"http://localhost:3000", "a1", ""}, // localhost skipped
|
||||
{"http://127.0.0.1:3000", "a1", ""}, // 127.0.0.1 skipped
|
||||
{"https://torrentclaw.com/", "a1", "wss://unarr.torrentclaw.com/ws/a1"},
|
||||
{"https://api.example.io", "x", "wss://unarr.api.example.io/ws/x"},
|
||||
{"", "agent-123", ""},
|
||||
{"https://torrentclaw.com", "", ""},
|
||||
{"", "", ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.apiURL+"_"+tt.agentID, func(t *testing.T) {
|
||||
got := deriveWSURL(tt.apiURL, tt.agentID)
|
||||
if got != tt.want {
|
||||
t.Errorf("deriveWSURL(%q, %q) = %q, want %q", tt.apiURL, tt.agentID, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatSpeedLog(t *testing.T) {
|
||||
tests := []struct {
|
||||
bps int64
|
||||
want string
|
||||
}{
|
||||
{0, "0 B/s"},
|
||||
{500, "500 B/s"},
|
||||
{1023, "1023 B/s"},
|
||||
{1024, "1 KB/s"},
|
||||
{10240, "10 KB/s"},
|
||||
{1048576, "1.0 MB/s"},
|
||||
{5242880, "5.0 MB/s"},
|
||||
{1073741824, "1.0 GB/s"},
|
||||
{2147483648, "2.0 GB/s"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.want, func(t *testing.T) {
|
||||
got := formatSpeedLog(tt.bps)
|
||||
if got != tt.want {
|
||||
t.Errorf("formatSpeedLog(%d) = %q, want %q", tt.bps, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue