package nvidia import ( "os" "path/filepath" "strings" "testing" "git.mchus.pro/mchus/logpile/internal/models" "git.mchus.pro/mchus/logpile/internal/parser" ) func TestParseInventoryLog(t *testing.T) { // Test with the real archive archivePath := filepath.Join("../../../../example", "A514359X5A09844_logs-20260115-151707.tar") // Check if file exists if _, err := os.Stat(archivePath); os.IsNotExist(err) { t.Skip("Test archive not found, skipping test") } // Extract files from archive files, err := parser.ExtractArchive(archivePath) if err != nil { t.Fatalf("Failed to extract archive: %v", err) } // Find inventory/output.log var inventoryLog *parser.ExtractedFile for _, f := range files { if strings.Contains(f.Path, "inventory/output.log") { inventoryLog = &f break } } if inventoryLog == nil { t.Fatal("inventory/output.log not found") } content := string(inventoryLog.Content) // Test devname regex - this extracts both slot mapping and serial numbers t.Log("Testing devname extraction:") lines := strings.Split(content, "\n") serialCount := 0 for i, line := range lines { if strings.Contains(line, "devname=") && strings.Contains(line, "fieldiag") { t.Logf("Line %d: Found fieldiag command", i) matches := devnameRegex.FindAllStringSubmatch(line, -1) t.Logf(" Found %d devname matches", len(matches)) for _, match := range matches { if len(match) == 3 { pciBDF := match[1] slotName := match[2] t.Logf(" PCI: %s -> Slot: %s", pciBDF, slotName) // Extract serial number from slot name if strings.HasPrefix(slotName, "SXM") { parts := strings.Split(slotName, "_") if len(parts) == 3 && parts[1] == "SN" { serial := parts[2] t.Logf(" Serial: %s", serial) serialCount++ } } } } break } } t.Logf("\nTotal GPU serials extracted: %d", serialCount) if serialCount == 0 { t.Error("Expected to find GPU serial numbers, but found none") } } func min(a, b int) int { if a < b { return a } return b } func TestParseInventoryLog_AssignsNVSwitchSerialByBDF(t *testing.T) { content := []byte(` $ lspci -vvvs 0000:05:00.0 05:00.0 Bridge: NVIDIA Corporation Device 22a3 (rev a1) Capabilities: [2f0 v1] Device Serial Number 99-d3-61-c8-ac-2d-b0-48 /tmp/fieldiag devname=0000:ba:00.0,SXM5_SN_1653925025497 fieldiag `) result := &models.AnalysisResult{ Hardware: &models.HardwareConfig{ GPUs: []models.GPU{ { Slot: "GPUSXM5", BDF: "0000:ba:00.0", SerialNumber: "", }, }, PCIeDevices: []models.PCIeDevice{ { Slot: "NVSWITCH0", BDF: "0000:05:00.0", SerialNumber: "", }, }, }, } if err := ParseInventoryLog(content, result); err != nil { t.Fatalf("ParseInventoryLog failed: %v", err) } if got := result.Hardware.PCIeDevices[0].SerialNumber; got != "99-d3-61-c8-ac-2d-b0-48" { t.Fatalf("expected NVSwitch serial 99-d3-61-c8-ac-2d-b0-48, got %q", got) } // GPU serial should come from fieldiag devname mapping. if got := result.Hardware.GPUs[0].SerialNumber; got != "1653925025497" { t.Fatalf("expected GPU serial 1653925025497, got %q", got) } }