144 lines
5.0 KiB
Go
144 lines
5.0 KiB
Go
package nvidia
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"git.mchus.pro/mchus/logpile/internal/models"
|
|
"git.mchus.pro/mchus/logpile/internal/parser"
|
|
)
|
|
|
|
func TestParseVerboseRunTestStartTimes(t *testing.T) {
|
|
content := []byte(`
|
|
2026-01-22 09:11:32,458 - Testing nvswitch
|
|
2026-01-22 09:45:36,016 - Testing gpu_fieldiag
|
|
`)
|
|
got := parseVerboseRunTestStartTimes(content)
|
|
|
|
nvs := got["nvswitch"]
|
|
if nvs.IsZero() {
|
|
t.Fatalf("expected nvswitch timestamp")
|
|
}
|
|
gpu := got["gpu_fieldiag"]
|
|
if gpu.IsZero() {
|
|
t.Fatalf("expected gpu_fieldiag timestamp")
|
|
}
|
|
if nvs.Format(time.RFC3339) != "2026-01-22T09:11:32Z" {
|
|
t.Fatalf("unexpected nvswitch timestamp: %s", nvs.Format(time.RFC3339))
|
|
}
|
|
if gpu.Format(time.RFC3339) != "2026-01-22T09:45:36Z" {
|
|
t.Fatalf("unexpected gpu_fieldiag timestamp: %s", gpu.Format(time.RFC3339))
|
|
}
|
|
}
|
|
|
|
func TestParseRunLogTestStartTimes(t *testing.T) {
|
|
content := []byte(`
|
|
Start time Thu, 22 Jan 2026 07:42:26
|
|
Testing gpumem FAILED [ 26:12s ]
|
|
Testing gpustress OK [ 7:10s ]
|
|
Testing nvswitch OK [ 9:25s ]
|
|
`)
|
|
|
|
got := parseRunLogTestStartTimes(content)
|
|
if got["gpumem"].Format(time.RFC3339) != "2026-01-22T07:42:26Z" {
|
|
t.Fatalf("unexpected gpumem start: %s", got["gpumem"].Format(time.RFC3339))
|
|
}
|
|
if got["gpustress"].Format(time.RFC3339) != "2026-01-22T08:08:38Z" {
|
|
t.Fatalf("unexpected gpustress start: %s", got["gpustress"].Format(time.RFC3339))
|
|
}
|
|
if got["nvswitch"].Format(time.RFC3339) != "2026-01-22T08:15:48Z" {
|
|
t.Fatalf("unexpected nvswitch start: %s", got["nvswitch"].Format(time.RFC3339))
|
|
}
|
|
}
|
|
|
|
func TestApplyGPUAndNVSwitchCheckTimes(t *testing.T) {
|
|
gpuTs := time.Date(2026, 1, 22, 9, 45, 36, 0, time.UTC)
|
|
nvsTs := time.Date(2026, 1, 22, 9, 11, 32, 0, time.UTC)
|
|
|
|
result := &models.AnalysisResult{
|
|
Hardware: &models.HardwareConfig{
|
|
GPUs: []models.GPU{
|
|
{Slot: "GPUSXM5", Status: "FAIL"},
|
|
},
|
|
PCIeDevices: []models.PCIeDevice{
|
|
{Slot: "NVSWITCH0", DeviceClass: "NVSwitch", Status: "PASS"},
|
|
{Slot: "NIC0", DeviceClass: "NetworkController", Status: "PASS"},
|
|
},
|
|
},
|
|
}
|
|
|
|
ApplyGPUAndNVSwitchCheckTimes(result, componentCheckTimes{
|
|
GPUBySlot: map[string]time.Time{"GPUSXM5": gpuTs},
|
|
NVSwitchBySlot: map[string]time.Time{"NVSWITCH0": nvsTs},
|
|
})
|
|
|
|
if got := result.Hardware.GPUs[0].StatusCheckedAt; !got.Equal(gpuTs) {
|
|
t.Fatalf("expected gpu status_checked_at %s, got %s", gpuTs.Format(time.RFC3339), got.Format(time.RFC3339))
|
|
}
|
|
if result.Hardware.GPUs[0].StatusAtCollect == nil || !result.Hardware.GPUs[0].StatusAtCollect.At.Equal(gpuTs) {
|
|
t.Fatalf("expected gpu status_at_collection.at %s", gpuTs.Format(time.RFC3339))
|
|
}
|
|
if got := result.Hardware.PCIeDevices[0].StatusCheckedAt; !got.Equal(nvsTs) {
|
|
t.Fatalf("expected nvswitch status_checked_at %s, got %s", nvsTs.Format(time.RFC3339), got.Format(time.RFC3339))
|
|
}
|
|
if result.Hardware.PCIeDevices[0].StatusAtCollect == nil || !result.Hardware.PCIeDevices[0].StatusAtCollect.At.Equal(nvsTs) {
|
|
t.Fatalf("expected nvswitch status_at_collection.at %s", nvsTs.Format(time.RFC3339))
|
|
}
|
|
if !result.Hardware.PCIeDevices[1].StatusCheckedAt.IsZero() {
|
|
t.Fatalf("expected non-nvswitch device status_checked_at to stay zero")
|
|
}
|
|
}
|
|
|
|
func TestCollectGPUAndNVSwitchCheckTimes_FromVerboseRun(t *testing.T) {
|
|
files := []parser.ExtractedFile{
|
|
{
|
|
Path: "verbose_run.log",
|
|
Content: []byte(`
|
|
2026-01-22 09:11:32,458 - Testing nvswitch
|
|
2026-01-22 09:45:36,016 - Testing gpu_fieldiag
|
|
`),
|
|
},
|
|
}
|
|
|
|
got := CollectGPUAndNVSwitchCheckTimes(files)
|
|
if got.GPUDefault.Format(time.RFC3339) != "2026-01-22T09:45:36Z" {
|
|
t.Fatalf("unexpected GPU check time: %s", got.GPUDefault.Format(time.RFC3339))
|
|
}
|
|
if got.NVSwitchDefault.Format(time.RFC3339) != "2026-01-22T09:11:32Z" {
|
|
t.Fatalf("unexpected NVSwitch check time: %s", got.NVSwitchDefault.Format(time.RFC3339))
|
|
}
|
|
}
|
|
|
|
func TestCollectGPUAndNVSwitchCheckTimes_FromComponentOutputLogs(t *testing.T) {
|
|
files := []parser.ExtractedFile{
|
|
{
|
|
Path: "gpu_fieldiag/SXM5_SN_1653925025497/output.log",
|
|
Content: []byte(`
|
|
$ some command
|
|
MODS start: Thu Jan 22 09:45:36 2026
|
|
`),
|
|
},
|
|
{
|
|
Path: "nvswitch/output.log",
|
|
Content: []byte(`
|
|
$ cmd devname=0000:08:00.0,NVSWITCH3 devname=0000:07:00.0,NVSWITCH2 devname=0000:06:00.0,NVSWITCH1 devname=0000:05:00.0,NVSWITCH0
|
|
MODS start: Thu Jan 22 09:11:32 2026
|
|
`),
|
|
},
|
|
}
|
|
|
|
got := CollectGPUAndNVSwitchCheckTimes(files)
|
|
if got.GPUBySerial["1653925025497"].Format(time.RFC3339) != "2026-01-22T09:45:36Z" {
|
|
t.Fatalf("unexpected GPU serial check time: %s", got.GPUBySerial["1653925025497"].Format(time.RFC3339))
|
|
}
|
|
if got.GPUBySlot["GPUSXM5"].Format(time.RFC3339) != "2026-01-22T09:45:36Z" {
|
|
t.Fatalf("unexpected GPU slot check time: %s", got.GPUBySlot["GPUSXM5"].Format(time.RFC3339))
|
|
}
|
|
if got.NVSwitchBySlot["NVSWITCH0"].Format(time.RFC3339) != "2026-01-22T09:11:32Z" {
|
|
t.Fatalf("unexpected NVSwitch0 check time: %s", got.NVSwitchBySlot["NVSWITCH0"].Format(time.RFC3339))
|
|
}
|
|
if got.NVSwitchBySlot["NVSWITCH3"].Format(time.RFC3339) != "2026-01-22T09:11:32Z" {
|
|
t.Fatalf("unexpected NVSwitch3 check time: %s", got.NVSwitchBySlot["NVSWITCH3"].Format(time.RFC3339))
|
|
}
|
|
}
|