127 lines
3.1 KiB
Go
127 lines
3.1 KiB
Go
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)
|
|
}
|
|
}
|