mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-27 00:06:13 +00:00
New test files: - internal/ai/providers/gemini_test.go: Comprehensive Gemini provider tests - internal/api/ai_intelligence_handlers_test.go: AI intelligence endpoint tests - internal/api/ai_patrol_handlers_test.go: AI patrol endpoint tests - internal/api/license_handlers_test.go: License API handler tests - internal/api/security_oidc_response_test.go: OIDC response formatting tests - internal/config/ai_config_test.go: AI configuration function tests - internal/config/persistence_ai_test.go: AI config persistence tests - internal/config/persistence_extended_test.go: Extended persistence tests - internal/license/persistence_test.go: License persistence tests - internal/license/pubkey_test.go: Public key handling tests - internal/monitoring/host_agent_temps_test.go: Temperature processing tests Enhanced existing files: - internal/api/updates_test.go: Added update handler tests - internal/license/license_test.go: Added Service method tests Coverage improvements: - ai/providers: 57.3% -> 73.0% (+15.7%) - license: 78.3% -> 85.9% (+7.6%) - config: 49.7% -> 53.9% (+4.2%) - monitoring: 49.8% -> 50.8% (+1.0%) - api: 28.4% -> 29.8% (+1.4%)
304 lines
7.3 KiB
Go
304 lines
7.3 KiB
Go
package monitoring
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/models"
|
|
)
|
|
|
|
func TestConvertHostSensorsToTemperature_Empty(t *testing.T) {
|
|
sensors := models.HostSensorSummary{}
|
|
result := convertHostSensorsToTemperature(sensors, time.Now())
|
|
if result != nil {
|
|
t.Error("expected nil for empty sensors")
|
|
}
|
|
}
|
|
|
|
func TestConvertHostSensorsToTemperature_CPUOnly(t *testing.T) {
|
|
sensors := models.HostSensorSummary{
|
|
TemperatureCelsius: map[string]float64{
|
|
"cpu_package": 55.0,
|
|
"cpu_core_0": 50.0,
|
|
"cpu_core_1": 52.0,
|
|
},
|
|
}
|
|
now := time.Now()
|
|
result := convertHostSensorsToTemperature(sensors, now)
|
|
|
|
if result == nil {
|
|
t.Fatal("expected non-nil result")
|
|
}
|
|
if !result.Available {
|
|
t.Error("expected Available to be true")
|
|
}
|
|
if !result.HasCPU {
|
|
t.Error("expected HasCPU to be true")
|
|
}
|
|
if result.CPUPackage != 55.0 {
|
|
t.Errorf("expected CPUPackage 55.0, got %f", result.CPUPackage)
|
|
}
|
|
if len(result.Cores) != 2 {
|
|
t.Errorf("expected 2 cores, got %d", len(result.Cores))
|
|
}
|
|
// Cores should be sorted
|
|
if result.Cores[0].Core != 0 || result.Cores[1].Core != 1 {
|
|
t.Error("cores not sorted correctly")
|
|
}
|
|
if result.CPUMax != 52.0 { // Max of core temps
|
|
t.Errorf("expected CPUMax 52.0, got %f", result.CPUMax)
|
|
}
|
|
}
|
|
|
|
func TestConvertHostSensorsToTemperature_NVMe(t *testing.T) {
|
|
sensors := models.HostSensorSummary{
|
|
TemperatureCelsius: map[string]float64{
|
|
"cpu_package": 45.0,
|
|
"nvme0": 40.0,
|
|
"nvme1": 42.0,
|
|
},
|
|
}
|
|
result := convertHostSensorsToTemperature(sensors, time.Now())
|
|
|
|
if result == nil {
|
|
t.Fatal("expected non-nil result")
|
|
}
|
|
if !result.HasNVMe {
|
|
t.Error("expected HasNVMe to be true")
|
|
}
|
|
if len(result.NVMe) != 2 {
|
|
t.Errorf("expected 2 NVMe devices, got %d", len(result.NVMe))
|
|
}
|
|
// NVMe should be sorted
|
|
if result.NVMe[0].Device != "nvme0" || result.NVMe[1].Device != "nvme1" {
|
|
t.Error("NVMe devices not sorted correctly")
|
|
}
|
|
}
|
|
|
|
func TestConvertHostSensorsToTemperature_GPU(t *testing.T) {
|
|
sensors := models.HostSensorSummary{
|
|
TemperatureCelsius: map[string]float64{
|
|
"cpu_package": 45.0,
|
|
"gpu_edge": 60.0,
|
|
"gpu_junction": 65.0,
|
|
"gpu_mem": 55.0,
|
|
},
|
|
}
|
|
result := convertHostSensorsToTemperature(sensors, time.Now())
|
|
|
|
if result == nil {
|
|
t.Fatal("expected non-nil result")
|
|
}
|
|
if !result.HasGPU {
|
|
t.Error("expected HasGPU to be true")
|
|
}
|
|
if len(result.GPU) != 1 {
|
|
t.Errorf("expected 1 GPU, got %d", len(result.GPU))
|
|
}
|
|
if result.GPU[0].Device != "gpu0" {
|
|
t.Errorf("expected device 'gpu0', got %q", result.GPU[0].Device)
|
|
}
|
|
if result.GPU[0].Edge != 60.0 {
|
|
t.Errorf("expected Edge 60.0, got %f", result.GPU[0].Edge)
|
|
}
|
|
if result.GPU[0].Junction != 65.0 {
|
|
t.Errorf("expected Junction 65.0, got %f", result.GPU[0].Junction)
|
|
}
|
|
}
|
|
|
|
func TestConvertHostSensorsToTemperature_GenericGPU(t *testing.T) {
|
|
sensors := models.HostSensorSummary{
|
|
TemperatureCelsius: map[string]float64{
|
|
"cpu_package": 45.0,
|
|
"gpu_nvidia": 70.0,
|
|
},
|
|
}
|
|
result := convertHostSensorsToTemperature(sensors, time.Now())
|
|
|
|
if result == nil {
|
|
t.Fatal("expected non-nil result")
|
|
}
|
|
if !result.HasGPU {
|
|
t.Error("expected HasGPU to be true")
|
|
}
|
|
if len(result.GPU) != 1 {
|
|
t.Errorf("expected 1 GPU, got %d", len(result.GPU))
|
|
}
|
|
if result.GPU[0].Device != "nvidia" {
|
|
t.Errorf("expected device 'nvidia', got %q", result.GPU[0].Device)
|
|
}
|
|
if result.GPU[0].Edge != 70.0 {
|
|
t.Errorf("expected Edge 70.0, got %f", result.GPU[0].Edge)
|
|
}
|
|
}
|
|
|
|
func TestConvertHostSensorsToTemperature_NoPackageUsesMaxCore(t *testing.T) {
|
|
sensors := models.HostSensorSummary{
|
|
TemperatureCelsius: map[string]float64{
|
|
"cpu_core_0": 50.0,
|
|
"cpu_core_1": 55.0,
|
|
},
|
|
}
|
|
result := convertHostSensorsToTemperature(sensors, time.Now())
|
|
|
|
if result == nil {
|
|
t.Fatal("expected non-nil result")
|
|
}
|
|
// When no package temp, CPUPackage should use max core temp
|
|
if result.CPUPackage != 55.0 {
|
|
t.Errorf("expected CPUPackage to be max core temp 55.0, got %f", result.CPUPackage)
|
|
}
|
|
}
|
|
|
|
func TestIsHostAgentTemperatureRecent(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
lastSeen time.Time
|
|
expected bool
|
|
}{
|
|
{
|
|
name: "recent - just now",
|
|
lastSeen: time.Now(),
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "recent - 1 minute ago",
|
|
lastSeen: time.Now().Add(-1 * time.Minute),
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "stale - 3 minutes ago",
|
|
lastSeen: time.Now().Add(-3 * time.Minute),
|
|
expected: false,
|
|
},
|
|
{
|
|
name: "stale - 1 hour ago",
|
|
lastSeen: time.Now().Add(-1 * time.Hour),
|
|
expected: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := isHostAgentTemperatureRecent(tt.lastSeen)
|
|
if result != tt.expected {
|
|
t.Errorf("isHostAgentTemperatureRecent() = %v, want %v", result, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMergeTemperatureData_NilInputs(t *testing.T) {
|
|
t.Run("both nil", func(t *testing.T) {
|
|
result := mergeTemperatureData(nil, nil)
|
|
if result != nil {
|
|
t.Error("expected nil for both nil inputs")
|
|
}
|
|
})
|
|
|
|
t.Run("host nil", func(t *testing.T) {
|
|
proxy := &models.Temperature{CPUPackage: 50.0}
|
|
result := mergeTemperatureData(nil, proxy)
|
|
if result != proxy {
|
|
t.Error("expected proxy when host is nil")
|
|
}
|
|
})
|
|
|
|
t.Run("proxy nil", func(t *testing.T) {
|
|
host := &models.Temperature{CPUPackage: 55.0}
|
|
result := mergeTemperatureData(host, nil)
|
|
if result != host {
|
|
t.Error("expected host when proxy is nil")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestMergeTemperatureData_Merge(t *testing.T) {
|
|
hostTemp := &models.Temperature{
|
|
CPUPackage: 55.0,
|
|
CPUMax: 55.0,
|
|
HasCPU: true,
|
|
Cores: []models.CoreTemp{
|
|
{Core: 0, Temp: 50.0},
|
|
{Core: 1, Temp: 55.0},
|
|
},
|
|
LastUpdate: time.Now(),
|
|
}
|
|
|
|
proxyTemp := &models.Temperature{
|
|
CPUPackage: 52.0,
|
|
CPUMin: 30.0,
|
|
CPUMaxRecord: 60.0,
|
|
HasCPU: true,
|
|
HasSMART: true,
|
|
SMART: []models.DiskTemp{
|
|
{Device: "/dev/sda", Temperature: 35},
|
|
},
|
|
}
|
|
|
|
result := mergeTemperatureData(hostTemp, proxyTemp)
|
|
|
|
if result == nil {
|
|
t.Fatal("expected non-nil result")
|
|
}
|
|
|
|
// Host agent CPU takes priority
|
|
if result.CPUPackage != 55.0 {
|
|
t.Errorf("expected CPUPackage 55.0 from host, got %f", result.CPUPackage)
|
|
}
|
|
|
|
// Proxy historical data preserved
|
|
if result.CPUMin != 30.0 {
|
|
t.Errorf("expected CPUMin 30.0 from proxy, got %f", result.CPUMin)
|
|
}
|
|
|
|
// SMART data from proxy preserved
|
|
if !result.HasSMART {
|
|
t.Error("expected HasSMART to be true")
|
|
}
|
|
if len(result.SMART) != 1 {
|
|
t.Errorf("expected 1 SMART disk, got %d", len(result.SMART))
|
|
}
|
|
}
|
|
|
|
func TestMergeTemperatureData_FallbackToProxy(t *testing.T) {
|
|
// Host has no CPU data, should fall back to proxy
|
|
hostTemp := &models.Temperature{
|
|
HasGPU: true,
|
|
GPU: []models.GPUTemp{
|
|
{Device: "gpu0", Edge: 70.0},
|
|
},
|
|
LastUpdate: time.Now(),
|
|
}
|
|
|
|
proxyTemp := &models.Temperature{
|
|
CPUPackage: 52.0,
|
|
CPUMax: 52.0,
|
|
HasCPU: true,
|
|
Cores: []models.CoreTemp{
|
|
{Core: 0, Temp: 48.0},
|
|
},
|
|
}
|
|
|
|
result := mergeTemperatureData(hostTemp, proxyTemp)
|
|
|
|
if result == nil {
|
|
t.Fatal("expected non-nil result")
|
|
}
|
|
|
|
// Should fall back to proxy CPU data
|
|
if result.CPUPackage != 52.0 {
|
|
t.Errorf("expected CPUPackage 52.0 from proxy fallback, got %f", result.CPUPackage)
|
|
}
|
|
if len(result.Cores) != 1 {
|
|
t.Errorf("expected 1 core from proxy, got %d", len(result.Cores))
|
|
}
|
|
|
|
// Host GPU data should be present
|
|
if !result.HasGPU {
|
|
t.Error("expected HasGPU to be true")
|
|
}
|
|
if len(result.GPU) != 1 {
|
|
t.Errorf("expected 1 GPU from host, got %d", len(result.GPU))
|
|
}
|
|
}
|