package systemmetrics import ( "context" "os" "path/filepath" "testing" "time" "tera-clone/services/tera-api/internal/domain" ) func TestLinuxReaderCollectsBoundedDashboardMetrics(t *testing.T) { root := t.TempDir() procRoot := filepath.Join(root, "proc") sysRoot := filepath.Join(root, "sys") etcRoot := filepath.Join(root, "etc") writeMetricFile(t, filepath.Join(procRoot, "uptime"), "93784.9 0\n") writeMetricFile(t, filepath.Join(procRoot, "loadavg"), "0.46 0.45 0.41 1/100 10\n") writeMetricFile(t, filepath.Join(procRoot, "stat"), "cpu 100 0 50 850 0 0 0 0\n") writeMetricFile(t, filepath.Join(procRoot, "meminfo"), "MemTotal: 2048000 kB\nMemFree: 256000 kB\nMemAvailable: 512000 kB\nBuffers: 64000 kB\nCached: 128000 kB\n") writeMetricFile(t, filepath.Join(sysRoot, "class", "thermal", "thermal_zone0", "temp"), "53800\n") writeMetricFile(t, filepath.Join(etcRoot, "tera", "build-number"), "N010-0020-2609-0062\n") writeMetricFile(t, filepath.Join(etcRoot, "machine-id"), "device-4027\n") interfaceRoot := filepath.Join(sysRoot, "class", "net", "eth0") writeMetricFile(t, filepath.Join(interfaceRoot, "address"), "6c:b3:50:0d:36:12\n") writeMetricFile(t, filepath.Join(interfaceRoot, "operstate"), "up\n") writeMetricFile(t, filepath.Join(interfaceRoot, "speed"), "1000\n") writeMetricFile(t, filepath.Join(interfaceRoot, "statistics", "rx_bytes"), "12345\n") writeMetricFile(t, filepath.Join(interfaceRoot, "statistics", "tx_bytes"), "67890\n") now := time.Date(2026, 8, 14, 12, 0, 0, 0, time.UTC) reader := NewLinuxReader(LinuxReaderOptions{ProcRoot: procRoot, SysRoot: sysRoot, EtcRoot: etcRoot, Clock: func() time.Time { return now }}) interfaces := []domain.NetworkInterface{{Name: "Interface-1", Device: "eth0", Address: "192.168.0.223/24", IPv6Address: "fe80::1/64"}} first := reader.Read(context.Background(), interfaces) if first.CPUUsagePercent != nil { t.Fatalf("first CPU sample = %v, want nil baseline", *first.CPUUsagePercent) } writeMetricFile(t, filepath.Join(procRoot, "stat"), "cpu 150 0 50 900 0 0 0 0\n") metrics := reader.Read(context.Background(), interfaces) if metrics.BuildNumber != "N010-0020-2609-0062" || metrics.DeviceID != "device-4027" || metrics.UptimeSeconds != 93784 || !metrics.SystemTime.Equal(now) { t.Fatalf("identity/runtime metrics = %+v", metrics) } if metrics.TemperatureCelsius == nil || *metrics.TemperatureCelsius != 53.8 || metrics.CPUUsagePercent == nil || *metrics.CPUUsagePercent != 50 { t.Fatalf("temperature/CPU metrics = %+v", metrics) } if len(metrics.LoadAverages) != 3 || metrics.LoadAverages[2] != 0.41 { t.Fatalf("load averages = %v", metrics.LoadAverages) } if metrics.MemoryTotalBytes != 2097152000 || metrics.MemoryAvailableBytes != 524288000 || metrics.MemoryUsedBytes != 1572864000 || metrics.MemoryUsagePercent == nil || *metrics.MemoryUsagePercent != 75 { t.Fatalf("memory metrics = %+v", metrics) } if len(metrics.NetworkInterfaces) != 1 { t.Fatalf("interfaces = %+v", metrics.NetworkInterfaces) } item := metrics.NetworkInterfaces[0] if item.MACAddress != "6c:b3:50:0d:36:12" || item.Link != "up" || item.SpeedMbps != 1000 || item.RXBytes != 12345 || item.TXBytes != 67890 || len(item.Addresses) != 2 { t.Fatalf("network metrics = %+v", item) } } func TestLinuxReaderRejectsUnsafeInterfaceDevicePath(t *testing.T) { root := t.TempDir() reader := NewLinuxReader(LinuxReaderOptions{ProcRoot: root, SysRoot: root, EtcRoot: root}) metrics := reader.Read(context.Background(), []domain.NetworkInterface{{Name: "Interface-1", Device: "../secret", Link: "down"}}) if len(metrics.NetworkInterfaces) != 1 || metrics.NetworkInterfaces[0].MACAddress != "" || metrics.NetworkInterfaces[0].Link != "down" { t.Fatalf("unsafe device result = %+v", metrics.NetworkInterfaces) } } func writeMetricFile(t *testing.T, path, content string) { t.Helper() if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { t.Fatal(err) } if err := os.WriteFile(path, []byte(content), 0o644); err != nil { t.Fatal(err) } }