146 lines
3.4 KiB
Go
146 lines
3.4 KiB
Go
package webui
|
|
|
|
import (
|
|
"database/sql"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"bee/audit/internal/platform"
|
|
_ "modernc.org/sqlite"
|
|
)
|
|
|
|
func TestMetricsDBLoadSamplesKeepsChronologicalRangeForGPUs(t *testing.T) {
|
|
db, err := openMetricsDB(filepath.Join(t.TempDir(), "metrics.db"))
|
|
if err != nil {
|
|
t.Fatalf("openMetricsDB: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
base := time.Unix(1_700_000_000, 0).UTC()
|
|
for i := 0; i < 3; i++ {
|
|
err := db.Write(platform.LiveMetricSample{
|
|
Timestamp: base.Add(time.Duration(i) * time.Second),
|
|
CPULoadPct: float64(10 + i),
|
|
MemLoadPct: float64(20 + i),
|
|
PowerW: float64(300 + i),
|
|
GPUs: []platform.GPUMetricRow{
|
|
{GPUIndex: 0, PowerW: float64(100 + i)},
|
|
{GPUIndex: 2, PowerW: float64(200 + i)},
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Write(%d): %v", i, err)
|
|
}
|
|
}
|
|
|
|
all, err := db.LoadAll()
|
|
if err != nil {
|
|
t.Fatalf("LoadAll: %v", err)
|
|
}
|
|
if len(all) != 3 {
|
|
t.Fatalf("LoadAll len=%d want 3", len(all))
|
|
}
|
|
for i, sample := range all {
|
|
if len(sample.GPUs) != 2 {
|
|
t.Fatalf("LoadAll sample %d GPUs=%v want 2 rows", i, sample.GPUs)
|
|
}
|
|
if sample.GPUs[0].GPUIndex != 0 || sample.GPUs[0].PowerW != float64(100+i) {
|
|
t.Fatalf("LoadAll sample %d GPU0=%+v", i, sample.GPUs[0])
|
|
}
|
|
if sample.GPUs[1].GPUIndex != 2 || sample.GPUs[1].PowerW != float64(200+i) {
|
|
t.Fatalf("LoadAll sample %d GPU1=%+v", i, sample.GPUs[1])
|
|
}
|
|
}
|
|
|
|
recent, err := db.LoadRecent(2)
|
|
if err != nil {
|
|
t.Fatalf("LoadRecent: %v", err)
|
|
}
|
|
if len(recent) != 2 {
|
|
t.Fatalf("LoadRecent len=%d want 2", len(recent))
|
|
}
|
|
if !recent[0].Timestamp.Before(recent[1].Timestamp) {
|
|
t.Fatalf("LoadRecent timestamps not ascending: %v >= %v", recent[0].Timestamp, recent[1].Timestamp)
|
|
}
|
|
for i, sample := range recent {
|
|
if len(sample.GPUs) != 2 {
|
|
t.Fatalf("LoadRecent sample %d GPUs=%v want 2 rows", i, sample.GPUs)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMetricsDBMigratesLegacyGPUSchema(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "metrics.db")
|
|
raw, err := sql.Open("sqlite", path)
|
|
if err != nil {
|
|
t.Fatalf("sql.Open: %v", err)
|
|
}
|
|
_, err = raw.Exec(`
|
|
CREATE TABLE gpu_metrics (
|
|
ts INTEGER NOT NULL,
|
|
gpu_index INTEGER NOT NULL,
|
|
temp_c REAL,
|
|
usage_pct REAL,
|
|
mem_usage_pct REAL,
|
|
power_w REAL,
|
|
PRIMARY KEY (ts, gpu_index)
|
|
);
|
|
CREATE TABLE sys_metrics (
|
|
ts INTEGER NOT NULL,
|
|
cpu_load_pct REAL,
|
|
mem_load_pct REAL,
|
|
power_w REAL,
|
|
PRIMARY KEY (ts)
|
|
);
|
|
CREATE TABLE fan_metrics (
|
|
ts INTEGER NOT NULL,
|
|
name TEXT NOT NULL,
|
|
rpm REAL,
|
|
PRIMARY KEY (ts, name)
|
|
);
|
|
CREATE TABLE temp_metrics (
|
|
ts INTEGER NOT NULL,
|
|
name TEXT NOT NULL,
|
|
grp TEXT NOT NULL,
|
|
celsius REAL,
|
|
PRIMARY KEY (ts, name)
|
|
);
|
|
`)
|
|
if err != nil {
|
|
t.Fatalf("create legacy schema: %v", err)
|
|
}
|
|
_ = raw.Close()
|
|
|
|
db, err := openMetricsDB(path)
|
|
if err != nil {
|
|
t.Fatalf("openMetricsDB: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
now := time.Unix(1_700_000_100, 0).UTC()
|
|
err = db.Write(platform.LiveMetricSample{
|
|
Timestamp: now,
|
|
GPUs: []platform.GPUMetricRow{
|
|
{GPUIndex: 0, ClockMHz: 1410, MemClockMHz: 2600},
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Write: %v", err)
|
|
}
|
|
|
|
samples, err := db.LoadAll()
|
|
if err != nil {
|
|
t.Fatalf("LoadAll: %v", err)
|
|
}
|
|
if len(samples) != 1 || len(samples[0].GPUs) != 1 {
|
|
t.Fatalf("samples=%+v", samples)
|
|
}
|
|
if got := samples[0].GPUs[0].ClockMHz; got != 1410 {
|
|
t.Fatalf("ClockMHz=%v want 1410", got)
|
|
}
|
|
if got := samples[0].GPUs[0].MemClockMHz; got != 2600 {
|
|
t.Fatalf("MemClockMHz=%v want 2600", got)
|
|
}
|
|
}
|