package redfishprofile import ( "encoding/json" "os" "path/filepath" "strings" "testing" ) func TestBuildAcquisitionPlan_Fixture_MSI_CG480(t *testing.T) { signals := loadProfileFixtureSignals(t, "msi-cg480.json") match := MatchProfiles(signals) plan := BuildAcquisitionPlan(signals) resolved := ResolveAcquisitionPlan(match, plan, discoveredResourcesFromSignals(signals), signals) if match.Mode != ModeMatched { t.Fatalf("expected matched mode, got %q", match.Mode) } assertProfileSelected(t, match, "msi") assertProfileSelected(t, match, "ami-family") assertProfileNotSelected(t, match, "hgx-topology") if plan.Tuning.PrefetchWorkers < 6 { t.Fatalf("expected msi prefetch worker tuning, got %d", plan.Tuning.PrefetchWorkers) } if !containsString(resolved.SeedPaths, "/redfish/v1/Chassis/GPU1") { t.Fatalf("expected MSI chassis GPU seed path") } if !containsString(resolved.CriticalPaths, "/redfish/v1/Chassis/GPU1/Sensors") { t.Fatal("expected MSI GPU sensor critical path") } if !containsString(resolved.Plan.PlanBPaths, "/redfish/v1/Chassis/GPU1/Sensors") { t.Fatal("expected MSI GPU sensor plan-b path") } if plan.Tuning.ETABaseline.SnapshotSeconds <= 0 { t.Fatal("expected MSI snapshot eta baseline") } if !plan.Tuning.PostProbePolicy.EnableNumericCollectionProbe { t.Fatal("expected MSI fixture to inherit generic numeric post-probe policy") } if !containsString(plan.ScopedPaths.SystemSeedSuffixes, "/SimpleStorage") { t.Fatal("expected MSI fixture to inherit generic SimpleStorage scoped seed suffix") } if !containsString(plan.ScopedPaths.SystemCriticalSuffixes, "/Memory") { t.Fatal("expected MSI fixture to inherit generic system critical suffixes") } if !containsString(plan.Tuning.PrefetchPolicy.IncludeSuffixes, "/Storage") { t.Fatal("expected MSI fixture to inherit generic storage prefetch policy") } if !containsString(plan.CriticalPaths, "/redfish/v1/UpdateService") { t.Fatal("expected MSI fixture to inherit generic top-level critical path") } if !plan.Tuning.RecoveryPolicy.EnableProfilePlanB { t.Fatal("expected MSI fixture to enable profile plan-b") } } func TestBuildAcquisitionPlan_Fixture_MSI_CG480_CopyMatchesSameProfiles(t *testing.T) { originalSignals := loadProfileFixtureSignals(t, "msi-cg480.json") copySignals := loadProfileFixtureSignals(t, "msi-cg480-copy.json") originalMatch := MatchProfiles(originalSignals) copyMatch := MatchProfiles(copySignals) originalPlan := BuildAcquisitionPlan(originalSignals) copyPlan := BuildAcquisitionPlan(copySignals) originalResolved := ResolveAcquisitionPlan(originalMatch, originalPlan, discoveredResourcesFromSignals(originalSignals), originalSignals) copyResolved := ResolveAcquisitionPlan(copyMatch, copyPlan, discoveredResourcesFromSignals(copySignals), copySignals) assertSameProfileNames(t, originalMatch, copyMatch) if originalPlan.Tuning.PrefetchWorkers != copyPlan.Tuning.PrefetchWorkers { t.Fatalf("expected same MSI prefetch worker tuning, got %d vs %d", originalPlan.Tuning.PrefetchWorkers, copyPlan.Tuning.PrefetchWorkers) } if containsString(originalResolved.SeedPaths, "/redfish/v1/Chassis/GPU1") != containsString(copyResolved.SeedPaths, "/redfish/v1/Chassis/GPU1") { t.Fatal("expected same MSI GPU chassis seed presence in both fixtures") } } func TestBuildAcquisitionPlan_Fixture_MSI_CG290(t *testing.T) { signals := loadProfileFixtureSignals(t, "msi-cg290.json") match := MatchProfiles(signals) plan := BuildAcquisitionPlan(signals) resolved := ResolveAcquisitionPlan(match, plan, discoveredResourcesFromSignals(signals), signals) if match.Mode != ModeMatched { t.Fatalf("expected matched mode, got %q", match.Mode) } assertProfileSelected(t, match, "msi") assertProfileSelected(t, match, "ami-family") assertProfileNotSelected(t, match, "hgx-topology") if plan.Tuning.PrefetchWorkers < 6 { t.Fatalf("expected MSI prefetch worker tuning, got %d", plan.Tuning.PrefetchWorkers) } if !containsString(resolved.SeedPaths, "/redfish/v1/Chassis/GPU1") { t.Fatalf("expected MSI chassis GPU seed path") } } func TestBuildAcquisitionPlan_Fixture_Supermicro_HGX(t *testing.T) { signals := loadProfileFixtureSignals(t, "supermicro-hgx.json") match := MatchProfiles(signals) plan := BuildAcquisitionPlan(signals) discovered := discoveredResourcesFromSignals(signals) discovered.SystemPaths = dedupeSorted(append(discovered.SystemPaths, "/redfish/v1/Systems/HGX_Baseboard_0")) resolved := ResolveAcquisitionPlan(match, plan, discovered, signals) if match.Mode != ModeMatched { t.Fatalf("expected matched mode, got %q", match.Mode) } assertProfileSelected(t, match, "supermicro") assertProfileSelected(t, match, "hgx-topology") assertProfileNotSelected(t, match, "msi") if plan.Tuning.SnapshotMaxDocuments < 180000 { t.Fatalf("expected widened HGX snapshot cap, got %d", plan.Tuning.SnapshotMaxDocuments) } if plan.Tuning.NVMePostProbeEnabled == nil || *plan.Tuning.NVMePostProbeEnabled { t.Fatal("expected HGX fixture to disable NVMe post-probe") } if !containsString(resolved.SeedPaths, "/redfish/v1/Systems/HGX_Baseboard_0/Processors") { t.Fatal("expected HGX baseboard processors seed path") } if !containsString(resolved.CriticalPaths, "/redfish/v1/Systems/HGX_Baseboard_0/Processors") { t.Fatal("expected HGX baseboard processors critical path") } if !containsString(resolved.Plan.PlanBPaths, "/redfish/v1/Systems/HGX_Baseboard_0/Processors") { t.Fatal("expected HGX baseboard processors plan-b path") } if plan.Tuning.ETABaseline.SnapshotSeconds < 300 { t.Fatalf("expected HGX snapshot eta baseline, got %d", plan.Tuning.ETABaseline.SnapshotSeconds) } if !plan.Tuning.PostProbePolicy.EnableDirectNVMEDiskBayProbe { t.Fatal("expected HGX fixture to retain Supermicro direct NVMe disk bay probe policy") } if !containsString(plan.ScopedPaths.SystemCriticalSuffixes, "/Storage/IntelVROC/Drives") { t.Fatal("expected HGX fixture to inherit generic IntelVROC scoped critical suffix") } if !containsString(plan.ScopedPaths.ChassisCriticalSuffixes, "/Assembly") { t.Fatal("expected HGX fixture to inherit generic chassis critical suffixes") } if !containsString(plan.Tuning.PrefetchPolicy.ExcludeContains, "/Assembly") { t.Fatal("expected HGX fixture to inherit generic assembly prefetch exclusion") } if !plan.Tuning.RecoveryPolicy.EnableProfilePlanB { t.Fatal("expected HGX fixture to enable profile plan-b") } } func TestBuildAcquisitionPlan_Fixture_Supermicro_OAM_NoHGX(t *testing.T) { signals := loadProfileFixtureSignals(t, "supermicro-oam-amd.json") match := MatchProfiles(signals) plan := BuildAcquisitionPlan(signals) resolved := ResolveAcquisitionPlan(match, plan, discoveredResourcesFromSignals(signals), signals) if match.Mode != ModeMatched { t.Fatalf("expected matched mode, got %q", match.Mode) } assertProfileSelected(t, match, "supermicro") assertProfileNotSelected(t, match, "hgx-topology") assertProfileNotSelected(t, match, "msi") if containsString(resolved.SeedPaths, "/redfish/v1/Systems/HGX_Baseboard_0/Processors") { t.Fatal("did not expect HGX baseboard processors seed path for OAM fixture") } if containsString(resolved.CriticalPaths, "/redfish/v1/Systems/HGX_Baseboard_0/Processors") { t.Fatal("did not expect HGX baseboard processors critical path for OAM fixture") } if !containsString(resolved.CriticalPaths, "/redfish/v1/UpdateService/Oem/Supermicro/FirmwareInventory") { t.Fatal("expected Supermicro firmware critical path") } if !containsString(resolved.Plan.PlanBPaths, "/redfish/v1/UpdateService/Oem/Supermicro/FirmwareInventory") { t.Fatal("expected Supermicro firmware plan-b path") } if plan.Tuning.SnapshotMaxDocuments != 150000 { t.Fatalf("expected generic supermicro snapshot cap, got %d", plan.Tuning.SnapshotMaxDocuments) } if plan.Tuning.NVMePostProbeEnabled != nil { t.Fatal("did not expect HGX NVMe tuning for OAM fixture") } if plan.Tuning.ETABaseline.SnapshotSeconds < 180 { t.Fatalf("expected Supermicro snapshot eta baseline, got %d", plan.Tuning.ETABaseline.SnapshotSeconds) } if !plan.Tuning.PostProbePolicy.EnableDirectNVMEDiskBayProbe { t.Fatal("expected Supermicro OAM fixture to use direct NVMe disk bay probe policy") } if !plan.Tuning.PostProbePolicy.EnableNumericCollectionProbe { t.Fatal("expected Supermicro OAM fixture to inherit generic numeric post-probe policy") } if !containsString(plan.ScopedPaths.SystemSeedSuffixes, "/Storage/IntelVROC") { t.Fatal("expected Supermicro OAM fixture to inherit generic IntelVROC scoped seed suffix") } if !plan.Tuning.RecoveryPolicy.EnableProfilePlanB { t.Fatal("expected Supermicro OAM fixture to enable profile plan-b") } } func TestBuildAcquisitionPlan_Fixture_Dell_R750(t *testing.T) { signals := loadProfileFixtureSignals(t, "dell-r750.json") match := MatchProfiles(signals) plan := BuildAcquisitionPlan(signals) resolved := ResolveAcquisitionPlan(match, plan, DiscoveredResources{ SystemPaths: []string{"/redfish/v1/Systems/System.Embedded.1"}, ChassisPaths: []string{"/redfish/v1/Chassis/System.Embedded.1"}, ManagerPaths: []string{"/redfish/v1/Managers/1", "/redfish/v1/Managers/iDRAC.Embedded.1"}, }, signals) if match.Mode != ModeMatched { t.Fatalf("expected matched mode, got %q", match.Mode) } assertProfileSelected(t, match, "dell") assertProfileNotSelected(t, match, "supermicro") assertProfileNotSelected(t, match, "hgx-topology") assertProfileNotSelected(t, match, "msi") if !plan.Tuning.RecoveryPolicy.EnableProfilePlanB { t.Fatal("expected dell fixture to enable profile plan-b") } if !containsString(resolved.SeedPaths, "/redfish/v1/Managers/iDRAC.Embedded.1") { t.Fatal("expected Dell refinement to add iDRAC manager seed path") } if !containsString(resolved.CriticalPaths, "/redfish/v1/Managers/iDRAC.Embedded.1") { t.Fatal("expected Dell refinement to add iDRAC manager critical path") } directives := ResolveAnalysisPlan(match, nil, DiscoveredResources{}, signals).Directives if !directives.EnableGenericGraphicsControllerDedup { t.Fatal("expected dell fixture to enable graphics controller dedup") } } func TestBuildAcquisitionPlan_Fixture_AMI_Generic(t *testing.T) { signals := loadProfileFixtureSignals(t, "ami-generic.json") match := MatchProfiles(signals) plan := BuildAcquisitionPlan(signals) if match.Mode != ModeMatched { t.Fatalf("expected matched mode, got %q", match.Mode) } assertProfileSelected(t, match, "ami-family") assertProfileNotSelected(t, match, "msi") assertProfileNotSelected(t, match, "supermicro") assertProfileNotSelected(t, match, "dell") assertProfileNotSelected(t, match, "hgx-topology") if plan.Tuning.PrefetchEnabled == nil || !*plan.Tuning.PrefetchEnabled { t.Fatal("expected ami-family fixture to force prefetch enabled") } if !containsString(plan.SeedPaths, "/redfish/v1/Oem/Ami") { t.Fatal("expected ami-family fixture seed path /redfish/v1/Oem/Ami") } if !containsString(plan.SeedPaths, "/redfish/v1/Oem/Ami/InventoryData/Status") { t.Fatal("expected ami-family fixture seed path /redfish/v1/Oem/Ami/InventoryData/Status") } if !containsString(plan.CriticalPaths, "/redfish/v1/UpdateService") { t.Fatal("expected ami-family fixture to inherit generic critical path") } directives := ResolveAnalysisPlan(match, nil, DiscoveredResources{}, signals).Directives if !directives.EnableGenericGraphicsControllerDedup { t.Fatal("expected ami-family fixture to enable graphics controller dedup") } } func TestBuildAcquisitionPlan_Fixture_UnknownVendor(t *testing.T) { signals := loadProfileFixtureSignals(t, "unknown-vendor.json") match := MatchProfiles(signals) plan := BuildAcquisitionPlan(signals) resolved := ResolveAcquisitionPlan(match, plan, DiscoveredResources{ SystemPaths: []string{"/redfish/v1/Systems/1"}, ChassisPaths: []string{"/redfish/v1/Chassis/1"}, ManagerPaths: []string{"/redfish/v1/Managers/1"}, }, signals) if match.Mode != ModeFallback { t.Fatalf("expected fallback mode for unknown vendor, got %q", match.Mode) } if len(match.Profiles) == 0 { t.Fatal("expected fallback to aggregate profiles") } for _, profile := range match.Profiles { if !profile.SafeForFallback() { t.Fatalf("fallback mode included non-safe profile %q", profile.Name()) } } if plan.Tuning.SnapshotMaxDocuments < 180000 { t.Fatalf("expected fallback to widen snapshot cap, got %d", plan.Tuning.SnapshotMaxDocuments) } if plan.Tuning.PrefetchEnabled == nil || !*plan.Tuning.PrefetchEnabled { t.Fatal("expected fallback fixture to force prefetch enabled") } if !containsString(resolved.CriticalPaths, "/redfish/v1/Systems/1") { t.Fatal("expected fallback resolved critical paths to include discovered system") } analysisPlan := ResolveAnalysisPlan(match, nil, DiscoveredResources{}, signals) if !analysisPlan.Directives.EnableProcessorGPUFallback { t.Fatal("expected fallback fixture to enable processor GPU fallback") } if !analysisPlan.Directives.EnableStorageEnclosureRecovery { t.Fatal("expected fallback fixture to enable storage enclosure recovery") } if !analysisPlan.Directives.EnableGenericGraphicsControllerDedup { t.Fatal("expected fallback fixture to enable graphics controller dedup") } } func TestBuildAcquisitionPlan_Fixture_xFusion_G5500V7(t *testing.T) { signals := loadProfileFixtureSignals(t, "xfusion-g5500v7.json") match := MatchProfiles(signals) plan := BuildAcquisitionPlan(signals) resolved := ResolveAcquisitionPlan(match, plan, DiscoveredResources{ SystemPaths: []string{"/redfish/v1/Systems/1"}, ChassisPaths: []string{"/redfish/v1/Chassis/1"}, ManagerPaths: []string{"/redfish/v1/Managers/1"}, }, signals) if match.Mode != ModeMatched { t.Fatalf("expected matched mode for xFusion, got %q", match.Mode) } assertProfileSelected(t, match, "xfusion") assertProfileNotSelected(t, match, "supermicro") assertProfileNotSelected(t, match, "hgx-topology") assertProfileNotSelected(t, match, "msi") assertProfileNotSelected(t, match, "dell") if plan.Tuning.SnapshotMaxDocuments > 150000 { t.Fatalf("expected xfusion snapshot cap <= 150000, got %d", plan.Tuning.SnapshotMaxDocuments) } if plan.Tuning.PrefetchEnabled == nil || !*plan.Tuning.PrefetchEnabled { t.Fatal("expected xfusion fixture to enable prefetch") } if plan.Tuning.ETABaseline.SnapshotSeconds <= 0 { t.Fatal("expected xfusion snapshot eta baseline") } if !containsString(resolved.CriticalPaths, "/redfish/v1/Systems/1") { t.Fatal("expected system path in critical paths") } analysisPlan := ResolveAnalysisPlan(match, map[string]interface{}{ "/redfish/v1/Systems/1/Processors/Gpu1": map[string]interface{}{"ProcessorType": "GPU"}, }, DiscoveredResources{ SystemPaths: []string{"/redfish/v1/Systems/1"}, }, signals) if !analysisPlan.Directives.EnableProcessorGPUFallback { t.Fatal("expected xfusion analysis to enable processor GPU fallback when GPU processors present") } if !analysisPlan.Directives.EnableGenericGraphicsControllerDedup { t.Fatal("expected xfusion analysis to enable graphics controller dedup") } } func loadProfileFixtureSignals(t *testing.T, fixtureName string) MatchSignals { t.Helper() path := filepath.Join("testdata", fixtureName) data, err := os.ReadFile(path) if err != nil { t.Fatalf("read fixture %s: %v", path, err) } var signals MatchSignals if err := json.Unmarshal(data, &signals); err != nil { t.Fatalf("decode fixture %s: %v", path, err) } return normalizeSignals(signals) } func assertProfileSelected(t *testing.T, match MatchResult, want string) { t.Helper() for _, profile := range match.Profiles { if profile.Name() == want { return } } t.Fatalf("expected profile %q in %v", want, profileNames(match)) } func assertProfileNotSelected(t *testing.T, match MatchResult, want string) { t.Helper() for _, profile := range match.Profiles { if profile.Name() == want { t.Fatalf("did not expect profile %q in %v", want, profileNames(match)) } } } func profileNames(match MatchResult) []string { out := make([]string, 0, len(match.Profiles)) for _, profile := range match.Profiles { out = append(out, profile.Name()) } return out } func assertSameProfileNames(t *testing.T, left, right MatchResult) { t.Helper() leftNames := profileNames(left) rightNames := profileNames(right) if len(leftNames) != len(rightNames) { t.Fatalf("profile stack size differs: %v vs %v", leftNames, rightNames) } for i := range leftNames { if leftNames[i] != rightNames[i] { t.Fatalf("profile stack differs: %v vs %v", leftNames, rightNames) } } } func containsString(items []string, want string) bool { for _, item := range items { if item == want { return true } } return false } func discoveredResourcesFromSignals(signals MatchSignals) DiscoveredResources { var discovered DiscoveredResources for _, hint := range signals.ResourceHints { memberPath := discoveredMemberPath(hint) switch { case strings.HasPrefix(memberPath, "/redfish/v1/Systems/"): discovered.SystemPaths = append(discovered.SystemPaths, memberPath) case strings.HasPrefix(memberPath, "/redfish/v1/Chassis/"): discovered.ChassisPaths = append(discovered.ChassisPaths, memberPath) case strings.HasPrefix(memberPath, "/redfish/v1/Managers/"): discovered.ManagerPaths = append(discovered.ManagerPaths, memberPath) } } discovered.SystemPaths = dedupeSorted(discovered.SystemPaths) discovered.ChassisPaths = dedupeSorted(discovered.ChassisPaths) discovered.ManagerPaths = dedupeSorted(discovered.ManagerPaths) return discovered } func discoveredMemberPath(path string) string { path = strings.TrimSpace(path) if path == "" { return "" } parts := strings.Split(strings.Trim(path, "/"), "/") if len(parts) < 4 || parts[0] != "redfish" || parts[1] != "v1" { return "" } switch parts[2] { case "Systems", "Chassis", "Managers": return "/" + strings.Join(parts[:4], "/") default: return "" } }