Files
tyto/backend/internal/collectors/amdgpu_test.go
vikingowl 1e83819318 feat: add unit tests for backend collectors and frontend
Backend tests:
- CPU, memory, disk, network collector tests (existing)
- Added temperature, processes, system, AMD GPU collector tests
- All tests use mock filesystem data

Frontend tests:
- Added Vitest with jsdom environment
- Tests for formatters (formatBytes, formatUptime, etc.)
- Tests for theme store

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 05:49:26 +01:00

167 lines
4.3 KiB
Go

package collectors
import (
"os"
"path/filepath"
"testing"
)
func TestAMDGPUCollector(t *testing.T) {
tmpDir := t.TempDir()
sysPath := filepath.Join(tmpDir, "sys")
// Create mock AMD GPU sysfs structure
gpuPath := filepath.Join(sysPath, "class/drm/card0/device")
if err := os.MkdirAll(gpuPath, 0755); err != nil {
t.Fatal(err)
}
// Create driver symlink (required for AMD GPU detection)
driverTarget := filepath.Join(tmpDir, "drivers/amdgpu")
if err := os.MkdirAll(driverTarget, 0755); err != nil {
t.Fatal(err)
}
if err := os.Symlink(driverTarget, filepath.Join(gpuPath, "driver")); err != nil {
t.Fatal(err)
}
// GPU utilization
if err := os.WriteFile(filepath.Join(gpuPath, "gpu_busy_percent"), []byte("75\n"), 0644); err != nil {
t.Fatal(err)
}
// VRAM
if err := os.WriteFile(filepath.Join(gpuPath, "mem_info_vram_used"), []byte("4294967296\n"), 0644); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(gpuPath, "mem_info_vram_total"), []byte("17179869184\n"), 0644); err != nil {
t.Fatal(err)
}
// Clock frequencies (format: "0: 500Mhz\n1: 800Mhz *\n2: 1200Mhz")
sclk := "0: 500Mhz\n1: 800Mhz\n2: 1200Mhz *\n"
if err := os.WriteFile(filepath.Join(gpuPath, "pp_dpm_sclk"), []byte(sclk), 0644); err != nil {
t.Fatal(err)
}
mclk := "0: 400Mhz\n1: 875Mhz *\n"
if err := os.WriteFile(filepath.Join(gpuPath, "pp_dpm_mclk"), []byte(mclk), 0644); err != nil {
t.Fatal(err)
}
// Create hwmon for temperature, power, fan
hwmonPath := filepath.Join(gpuPath, "hwmon/hwmon5")
if err := os.MkdirAll(hwmonPath, 0755); err != nil {
t.Fatal(err)
}
// Temperature (65°C in millidegrees)
if err := os.WriteFile(filepath.Join(hwmonPath, "temp1_input"), []byte("65000\n"), 0644); err != nil {
t.Fatal(err)
}
// Power (150W in microwatts)
if err := os.WriteFile(filepath.Join(hwmonPath, "power1_average"), []byte("150000000\n"), 0644); err != nil {
t.Fatal(err)
}
// Fan RPM
if err := os.WriteFile(filepath.Join(hwmonPath, "fan1_input"), []byte("1500\n"), 0644); err != nil {
t.Fatal(err)
}
collector := NewAMDGPUCollector(sysPath)
stats, err := collector.Collect()
if err != nil {
t.Fatalf("Collect failed: %v", err)
}
if !stats.Available {
t.Error("Expected GPU to be available")
}
if stats.Utilization != 75 {
t.Errorf("Expected utilization 75, got %d", stats.Utilization)
}
if stats.VRAMUsed != 4294967296 {
t.Errorf("Expected VRAM used 4294967296, got %d", stats.VRAMUsed)
}
if stats.VRAMTotal != 17179869184 {
t.Errorf("Expected VRAM total 17179869184, got %d", stats.VRAMTotal)
}
if stats.ClockGPU != 1200 {
t.Errorf("Expected GPU clock 1200, got %d", stats.ClockGPU)
}
if stats.ClockMemory != 875 {
t.Errorf("Expected memory clock 875, got %d", stats.ClockMemory)
}
if stats.Temperature != 65.0 {
t.Errorf("Expected temperature 65.0, got %f", stats.Temperature)
}
if stats.PowerWatts != 150.0 {
t.Errorf("Expected power 150.0W, got %f", stats.PowerWatts)
}
if stats.FanRPM != 1500 {
t.Errorf("Expected fan 1500 RPM, got %d", stats.FanRPM)
}
}
func TestAMDGPUCollector_NoGPU(t *testing.T) {
tmpDir := t.TempDir()
collector := NewAMDGPUCollector(tmpDir)
stats, err := collector.Collect()
if err != nil {
t.Fatalf("Collect failed: %v", err)
}
if stats.Available {
t.Error("Expected GPU to be unavailable")
}
}
func TestAMDGPUCollector_PartialData(t *testing.T) {
tmpDir := t.TempDir()
sysPath := filepath.Join(tmpDir, "sys")
// Create minimal GPU structure (only utilization)
gpuPath := filepath.Join(sysPath, "class/drm/card0/device")
if err := os.MkdirAll(gpuPath, 0755); err != nil {
t.Fatal(err)
}
// Create driver symlink (required for AMD GPU detection)
driverTarget := filepath.Join(tmpDir, "drivers/amdgpu")
if err := os.MkdirAll(driverTarget, 0755); err != nil {
t.Fatal(err)
}
if err := os.Symlink(driverTarget, filepath.Join(gpuPath, "driver")); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(gpuPath, "gpu_busy_percent"), []byte("50\n"), 0644); err != nil {
t.Fatal(err)
}
collector := NewAMDGPUCollector(sysPath)
stats, err := collector.Collect()
if err != nil {
t.Fatalf("Collect failed: %v", err)
}
if !stats.Available {
t.Error("Expected GPU to be available with partial data")
}
if stats.Utilization != 50 {
t.Errorf("Expected utilization 50, got %d", stats.Utilization)
}
}