package resource import ( "testing" ) func TestParseNvidiaSMI(t *testing.T) { output := `0, NVIDIA GeForce RTX 4090, 45, 30, 4096, 24576, 16.67, 150.5, 450.0 1, NVIDIA GeForce RTX 4090, 52, 75, 8192, 24576, 33.33, 320.0, 450.0` metrics := parseNvidiaSMI(output) if len(metrics) != 2 { t.Fatalf("expected 2 GPUs, got %d", len(metrics)) } if metrics[0].Index != 0 { t.Errorf("expected index 0, got %d", metrics[0].Index) } if metrics[0].Name != "NVIDIA GeForce RTX 4090" { t.Errorf("unexpected name: %s", metrics[0].Name) } if metrics[0].TemperatureC != 45 { t.Errorf("expected temp 45, got %d", metrics[0].TemperatureC) } if metrics[0].UtilizationGPU != 30 { t.Errorf("expected util 30, got %d", metrics[0].UtilizationGPU) } if metrics[0].MemoryUsedMB != 4096 { t.Errorf("expected mem used 4096, got %d", metrics[0].MemoryUsedMB) } if metrics[0].MemoryTotalMB != 24576 { t.Errorf("expected mem total 24576, got %d", metrics[0].MemoryTotalMB) } if metrics[0].PowerDrawW != 150.5 { t.Errorf("expected power 150.5, got %f", metrics[0].PowerDrawW) } if metrics[1].Index != 1 { t.Errorf("expected index 1, got %d", metrics[1].Index) } if metrics[1].UtilizationGPU != 75 { t.Errorf("expected util 75, got %d", metrics[1].UtilizationGPU) } } func TestParseNvidiaSMIEmpty(t *testing.T) { metrics := parseNvidiaSMI("") if len(metrics) != 0 { t.Errorf("expected 0 metrics for empty input, got %d", len(metrics)) } } func TestParseNvidiaSMIInvalidLines(t *testing.T) { output := `invalid line 0, GPU0, 40, 50, 1024, 8192, 12.5, 100.0, 300.0 , , , , , , , , ` metrics := parseNvidiaSMI(output) // Both lines with 9 fields parse; the empty-name one has Name="" validCount := 0 for _, m := range metrics { if m.Name != "" { validCount++ } } if validCount != 1 { t.Errorf("expected 1 valid metric with name, got %d", validCount) } } func TestGPUCollectorTotals(t *testing.T) { c := &GPUCollector{ metrics: []GPUMetrics{ {MemoryUsedMB: 4096, MemoryTotalMB: 24576, UtilizationGPU: 30}, {MemoryUsedMB: 8192, MemoryTotalMB: 24576, UtilizationGPU: 75}, }, } if c.TotalMemoryUsedMB() != 12288 { t.Errorf("expected 12288, got %d", c.TotalMemoryUsedMB()) } if c.TotalMemoryTotalMB() != 49152 { t.Errorf("expected 49152, got %d", c.TotalMemoryTotalMB()) } avg := c.AverageUtilization() if avg != 52.5 { t.Errorf("expected 52.5, got %f", avg) } ratio := c.MemoryUtilizationRatio() expectedRatio := 12288.0 / 49152.0 if ratio != expectedRatio { t.Errorf("expected %f, got %f", expectedRatio, ratio) } } func TestGPUCollectorEmpty(t *testing.T) { c := &GPUCollector{} if c.TotalMemoryUsedMB() != 0 { t.Error("expected 0 for empty collector") } if c.AverageUtilization() != 0 { t.Error("expected 0 for empty collector") } if c.MemoryUtilizationRatio() != 0 { t.Error("expected 0 for empty collector") } } func TestParseIntSafe(t *testing.T) { if parseIntSafe("42") != 42 { t.Error("expected 42") } if parseIntSafe("invalid") != 0 { t.Error("expected 0 for invalid") } if parseIntSafe(" 100 ") != 100 { t.Error("expected 100 with whitespace") } } func TestParseFloatSafe(t *testing.T) { if parseFloatSafe("3.14") != 3.14 { t.Error("expected 3.14") } if parseFloatSafe("invalid") != 0 { t.Error("expected 0 for invalid") } }