Skip to content

Commit c88b47c

Browse files
committed
test(recipe): add conformance recipe invariant tests
Add unit tests that verify conformance-critical recipes resolve with all required CNCF components and conformance checks. This catches regressions at PR time (no cluster needed) when components or checks are accidentally removed from recipe overlays. Tests cover both H100 kind recipes: - h100-kind-inference-dynamo: 14 components, 10 conformance checks - h100-kind-training: 12 components, 9 conformance checks Each test verifies: required components present, conformance validation configured, all required checks declared, and K8s >= 1.34 DRA constraint.
1 parent 308b381 commit c88b47c

File tree

1 file changed

+171
-0
lines changed

1 file changed

+171
-0
lines changed

pkg/recipe/conformance_test.go

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
// Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// conformance_test.go verifies that conformance-critical recipes contain
16+
// all CNCF-required components and conformance checks. These tests catch
17+
// regressions at PR time (no cluster needed) — e.g., a component removal
18+
// or a conformance check accidentally dropped from an overlay.
19+
//
20+
// Area of Concern: Recipe-level conformance guarantees
21+
// - Required components present in resolved recipe
22+
// - Conformance validation checks declared in overlay chain
23+
// - DRA constraint (K8s >= 1.34) present for all conformance recipes
24+
25+
package recipe
26+
27+
import (
28+
"context"
29+
"strings"
30+
"testing"
31+
)
32+
33+
func TestConformanceRecipeInvariants(t *testing.T) {
34+
tests := []struct {
35+
name string
36+
criteria func() *Criteria
37+
requiredComponents []string
38+
requiredChecks []string
39+
}{
40+
{
41+
name: "h100-kind-inference-dynamo",
42+
criteria: func() *Criteria {
43+
c := NewCriteria()
44+
c.Service = CriteriaServiceKind
45+
c.Accelerator = CriteriaAcceleratorH100
46+
c.Intent = CriteriaIntentInference
47+
c.Platform = CriteriaPlatformDynamo
48+
return c
49+
},
50+
requiredComponents: []string{
51+
"cert-manager",
52+
"gpu-operator",
53+
"kube-prometheus-stack",
54+
"prometheus-adapter",
55+
"nvidia-dra-driver-gpu",
56+
"kai-scheduler",
57+
"kgateway-crds",
58+
"kgateway",
59+
"dynamo-crds",
60+
"dynamo-platform",
61+
},
62+
requiredChecks: []string{
63+
"platform-health",
64+
"gpu-operator-health",
65+
"dra-support",
66+
"accelerator-metrics",
67+
"ai-service-metrics",
68+
"inference-gateway",
69+
"robust-controller",
70+
"secure-accelerator-access",
71+
"pod-autoscaling",
72+
"cluster-autoscaling",
73+
},
74+
},
75+
{
76+
name: "h100-kind-training",
77+
criteria: func() *Criteria {
78+
c := NewCriteria()
79+
c.Service = CriteriaServiceKind
80+
c.Accelerator = CriteriaAcceleratorH100
81+
c.Intent = CriteriaIntentTraining
82+
return c
83+
},
84+
requiredComponents: []string{
85+
"cert-manager",
86+
"gpu-operator",
87+
"kube-prometheus-stack",
88+
"prometheus-adapter",
89+
"nvidia-dra-driver-gpu",
90+
"kai-scheduler",
91+
"dynamo-crds",
92+
"dynamo-platform",
93+
},
94+
requiredChecks: []string{
95+
"platform-health",
96+
"gpu-operator-health",
97+
"dra-support",
98+
"accelerator-metrics",
99+
"ai-service-metrics",
100+
"gang-scheduling",
101+
"robust-controller",
102+
"pod-autoscaling",
103+
"cluster-autoscaling",
104+
},
105+
},
106+
}
107+
108+
for _, tt := range tests {
109+
t.Run(tt.name, func(t *testing.T) {
110+
ctx := context.Background()
111+
builder := NewBuilder()
112+
criteria := tt.criteria()
113+
114+
result, err := builder.BuildFromCriteria(ctx, criteria)
115+
if err != nil {
116+
t.Fatalf("BuildFromCriteria failed: %v", err)
117+
}
118+
if result == nil {
119+
t.Fatal("Recipe result is nil")
120+
}
121+
122+
// 1. All required components present
123+
for _, name := range tt.requiredComponents {
124+
if comp := result.GetComponentRef(name); comp == nil {
125+
t.Errorf("Required component %q not found in resolved recipe", name)
126+
}
127+
}
128+
129+
// 2. Conformance validation configured
130+
if result.Validation == nil {
131+
t.Fatal("result.Validation is nil")
132+
}
133+
if result.Validation.Conformance == nil {
134+
t.Fatal("result.Validation.Conformance is nil")
135+
}
136+
137+
// 3. All required conformance checks present
138+
checkSet := make(map[string]bool)
139+
for _, c := range result.Validation.Conformance.Checks {
140+
checkSet[c] = true
141+
}
142+
for _, check := range tt.requiredChecks {
143+
if !checkSet[check] {
144+
t.Errorf("Required conformance check %q not found (have: %v)",
145+
check, result.Validation.Conformance.Checks)
146+
}
147+
}
148+
149+
// 4. No fewer checks than expected (guards against accidental removal)
150+
if len(result.Validation.Conformance.Checks) < len(tt.requiredChecks) {
151+
t.Errorf("Conformance checks count = %d, want >= %d",
152+
len(result.Validation.Conformance.Checks), len(tt.requiredChecks))
153+
}
154+
155+
// 5. DRA constraint present (K8s >= 1.34 required for DRA GA)
156+
var hasDRAConstraint bool
157+
for _, c := range result.Constraints {
158+
if c.Name == "K8s.server.version" && strings.Contains(c.Value, "1.34") {
159+
hasDRAConstraint = true
160+
break
161+
}
162+
}
163+
if !hasDRAConstraint {
164+
t.Error("Missing K8s >= 1.34 constraint (required for DRA GA)")
165+
}
166+
167+
t.Logf("Recipe %s: %d components, %d conformance checks",
168+
tt.name, len(result.ComponentRefs), len(result.Validation.Conformance.Checks))
169+
})
170+
}
171+
}

0 commit comments

Comments
 (0)