1. 删除 ConfigAgent (与 MQTT 配置更新重叠且未启用) 2. OTA 完整安装流程: 解压tar.gz -> 校验ELF -> 替换二进制 -> systemctl重启 3. StreamManager stopAll 添加 Wait() 防止僵尸进程 4. InferClient socket 读写添加 timeout 防止永久阻塞 5. Heartbeat 集成 NPU 监控 (npu-smi + fallback 脚本) 6. 配置更新时动态重启 ffmpeg 以应用新 fps
97 lines
2.4 KiB
Go
97 lines
2.4 KiB
Go
package control
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
func TestParseNpuSmiOutput(t *testing.T) {
|
|
common := `Temperature(C) : 46
|
|
Aicore Usage Rate(%) : 25
|
|
Memory Usage Rate(%) : 86`
|
|
memory := `Capacity(MB) : 3513`
|
|
|
|
stats := parseNpuSmiOutput(common, memory)
|
|
if stats == nil {
|
|
t.Fatal("expected non-nil stats")
|
|
}
|
|
if stats.TempC != 46 {
|
|
t.Errorf("temp: got %d want 46", stats.TempC)
|
|
}
|
|
if stats.UtilPct != 25 {
|
|
t.Errorf("util: got %d want 25", stats.UtilPct)
|
|
}
|
|
if stats.MemTotalMB != 3513 {
|
|
t.Errorf("mem_total: got %d want 3513", stats.MemTotalMB)
|
|
}
|
|
if stats.MemPct != 86 {
|
|
t.Errorf("mem_pct: got %d want 86", stats.MemPct)
|
|
}
|
|
// 3513 * 86 / 100 = 3021
|
|
if stats.MemUsedMB != 3021 {
|
|
t.Errorf("mem_used: got %d want 3021", stats.MemUsedMB)
|
|
}
|
|
}
|
|
|
|
func TestParseInfluxLine(t *testing.T) {
|
|
line := "npu_status,device=0 temp=46,utilization=0,memory_used=3021,memory_total=3513"
|
|
stats := parseInfluxLine(line)
|
|
if stats == nil {
|
|
t.Fatal("expected non-nil stats")
|
|
}
|
|
if stats.TempC != 46 {
|
|
t.Errorf("temp: got %d want 46", stats.TempC)
|
|
}
|
|
if stats.UtilPct != 0 {
|
|
t.Errorf("util: got %d want 0", stats.UtilPct)
|
|
}
|
|
if stats.MemUsedMB != 3021 {
|
|
t.Errorf("mem_used: got %d want 3021", stats.MemUsedMB)
|
|
}
|
|
if stats.MemTotalMB != 3513 {
|
|
t.Errorf("mem_total: got %d want 3513", stats.MemTotalMB)
|
|
}
|
|
}
|
|
|
|
func TestParseInfluxLineInvalid(t *testing.T) {
|
|
// Input with no space-separated fields returns nil
|
|
stats := parseInfluxLine("garbage")
|
|
if stats != nil {
|
|
t.Error("expected nil stats for garbage input without fields")
|
|
}
|
|
|
|
// Input with fields but no valid data returns zero-valued stats
|
|
stats2 := parseInfluxLine("npu_status,device=0 ")
|
|
if stats2 == nil {
|
|
t.Fatal("expected non-nil stats for input with fields")
|
|
}
|
|
if stats2.TempC != 0 || stats2.UtilPct != 0 {
|
|
t.Errorf("expected zero values, got temp=%d util=%d", stats2.TempC, stats2.UtilPct)
|
|
}
|
|
}
|
|
|
|
func TestExtractLastNumber(t *testing.T) {
|
|
tests := []struct {
|
|
input string
|
|
want int
|
|
}{
|
|
{"Temperature(C) : 46", 46},
|
|
{"Aicore Usage Rate(%) : 25%", 25},
|
|
{" 86%", 86},
|
|
{"no numbers here", 0},
|
|
{"", 0},
|
|
{"value: 123C", 123},
|
|
}
|
|
for _, tt := range tests {
|
|
got := extractLastNumber(tt.input)
|
|
if got != tt.want {
|
|
t.Errorf("extractLastNumber(%q) = %d, want %d", tt.input, got, tt.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestInMaintenanceWindow(t *testing.T) {
|
|
// Can't test specific hours without mocking time.Time,
|
|
// but verify it doesn't panic
|
|
_ = inMaintenanceWindow()
|
|
}
|