Skip to content

Commit 5cfdc22

Browse files
committed
validate if measurements and dependencies are registered before running tests
1 parent f581a11 commit 5cfdc22

File tree

4 files changed

+108
-22
lines changed

4 files changed

+108
-22
lines changed

clusterloader2/api/validation.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ import (
2525
"k8s.io/perf-tests/clusterloader2/pkg/errors"
2626
)
2727

28+
var (
29+
RegisteredDependencies = make(map[string]bool)
30+
RegisteredMeasurements = make(map[string]bool)
31+
)
32+
2833
// ConfigValidator contains metadata for config validation.
2934
type ConfigValidator struct {
3035
configDir string
@@ -231,6 +236,19 @@ func (v *ConfigValidator) validateMeasurement(m *Measurement, fldPath *field.Pat
231236
if len(m.Instances) == 0 && m.Identifier == "" {
232237
allErrs = append(allErrs, field.Invalid(fldPath.Child("Identifier"), m.Identifier, " and Instances cannot be both empty"))
233238
}
239+
allErrs = append(allErrs, v.validateMeasurementMethod(m.Method, fldPath.Child("method"))...)
240+
241+
return allErrs
242+
}
243+
244+
func (v *ConfigValidator) validateMeasurementMethod(method string, fldPath *field.Path) field.ErrorList {
245+
allErrs := field.ErrorList{}
246+
if method == "" {
247+
allErrs = append(allErrs, field.Required(fldPath, "method is required"))
248+
}
249+
if !RegisteredMeasurements[method] {
250+
allErrs = append(allErrs, field.Invalid(fldPath, method, "measurement method is not registered"))
251+
}
234252
return allErrs
235253
}
236254

@@ -306,12 +324,21 @@ func (v *ConfigValidator) validateDependency(d *Dependency, fldPath *field.Path)
306324
if d.Name == "" {
307325
allErrs = append(allErrs, field.Required(fldPath.Child("name"), "name is required"))
308326
}
309-
if d.Method == "" {
310-
allErrs = append(allErrs, field.Required(fldPath.Child("method"), "method is required"))
311-
}
312327
if d.Timeout < 0 {
313328
allErrs = append(allErrs, field.Invalid(fldPath.Child("timeout"), d.Timeout, "timeout cannot be negative"))
314329
}
330+
allErrs = append(allErrs, v.validateDependencyMethod(d.Method, fldPath.Child("method"))...)
331+
return allErrs
332+
}
333+
334+
func (v *ConfigValidator) validateDependencyMethod(method string, fldPath *field.Path) field.ErrorList {
335+
allErrs := field.ErrorList{}
336+
if method == "" {
337+
allErrs = append(allErrs, field.Required(fldPath, "method is required"))
338+
}
339+
if !RegisteredDependencies[method] {
340+
allErrs = append(allErrs, field.Invalid(fldPath, method, "dependency method is not registered"))
341+
}
315342
return allErrs
316343
}
317344

clusterloader2/api/validation_test.go

Lines changed: 72 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -302,20 +302,24 @@ func TestVerifyPhase(t *testing.T) {
302302

303303
func TestVerifyMeasurement(t *testing.T) {
304304
for _, test := range []struct {
305-
name string
306-
input Measurement
307-
expected bool
305+
name string
306+
input Measurement
307+
expected bool
308+
registered bool
308309
}{
309310
{
310311
name: "Identifier specified only",
311312
input: Measurement{
313+
Method: "TestMethod1",
312314
Identifier: "Measurement",
313315
},
314-
expected: true,
316+
expected: true,
317+
registered: true,
315318
},
316319
{
317320
name: "Instances specified only",
318321
input: Measurement{
322+
Method: "TestMethod2",
319323
Instances: []*MeasurementInstanceConfig{
320324
{
321325
Identifier: "Measurement1",
@@ -325,11 +329,13 @@ func TestVerifyMeasurement(t *testing.T) {
325329
},
326330
},
327331
},
328-
expected: true,
332+
expected: true,
333+
registered: true,
329334
},
330335
{
331336
name: "Both identifier and instances specified",
332337
input: Measurement{
338+
Method: "TestMethod3",
333339
Identifier: "Measurement",
334340
Instances: []*MeasurementInstanceConfig{
335341
{
@@ -340,15 +346,37 @@ func TestVerifyMeasurement(t *testing.T) {
340346
},
341347
},
342348
},
343-
expected: false,
349+
expected: false,
350+
registered: true,
344351
},
345352
{
346-
name: "Identifier and instances empty",
347-
input: Measurement{},
348-
expected: false,
353+
name: "Identifier and instances empty",
354+
input: Measurement{Method: "TestMethod4"},
355+
expected: false,
356+
registered: true,
357+
},
358+
{
359+
name: "Measurement not registered",
360+
input: Measurement{
361+
Method: "UnregisteredMethod",
362+
Identifier: "Measurement",
363+
},
364+
expected: false,
365+
registered: false,
366+
},
367+
{
368+
name: "Missing method",
369+
input: Measurement{
370+
Identifier: "Measurement",
371+
},
372+
expected: false,
373+
registered: false,
349374
},
350375
} {
351376
t.Run(test.name, func(t *testing.T) {
377+
if test.registered {
378+
RegisteredMeasurements[test.input.Method] = true
379+
}
352380
v := NewConfigValidator("", &Config{})
353381
got := isValid(v.validateMeasurement(&test.input, field.NewPath("")))
354382
if test.expected != got {
@@ -360,9 +388,10 @@ func TestVerifyMeasurement(t *testing.T) {
360388

361389
func TestVerifyDependency(t *testing.T) {
362390
for _, test := range []struct {
363-
name string
364-
input Dependency
365-
expected bool
391+
name string
392+
input Dependency
393+
expected bool
394+
registered bool
366395
}{
367396
{
368397
name: "Valid dependency - name and method specified",
@@ -374,7 +403,8 @@ func TestVerifyDependency(t *testing.T) {
374403
"param1": "value1",
375404
},
376405
},
377-
expected: true,
406+
expected: true,
407+
registered: true,
378408
},
379409
{
380410
name: "Valid dependency - zero timeout",
@@ -383,15 +413,17 @@ func TestVerifyDependency(t *testing.T) {
383413
Method: "TestMethod",
384414
Timeout: Duration(0),
385415
},
386-
expected: true,
416+
expected: true,
417+
registered: true,
387418
},
388419
{
389420
name: "Valid dependency - minimal fields",
390421
input: Dependency{
391422
Name: "test-dependency",
392423
Method: "TestMethod",
393424
},
394-
expected: true,
425+
expected: true,
426+
registered: true,
395427
},
396428
{
397429
name: "Invalid dependency - negative timeout",
@@ -400,21 +432,24 @@ func TestVerifyDependency(t *testing.T) {
400432
Method: "TestMethod",
401433
Timeout: Duration(-1),
402434
},
403-
expected: false,
435+
expected: false,
436+
registered: true,
404437
},
405438
{
406439
name: "Invalid dependency - missing name",
407440
input: Dependency{
408441
Method: "TestMethod",
409442
},
410-
expected: false,
443+
expected: false,
444+
registered: true,
411445
},
412446
{
413447
name: "Invalid dependency - missing method",
414448
input: Dependency{
415449
Name: "test-dependency",
416450
},
417-
expected: false,
451+
expected: false,
452+
registered: true,
418453
},
419454
{
420455
name: "Invalid dependency - both name and method missing",
@@ -423,11 +458,24 @@ func TestVerifyDependency(t *testing.T) {
423458
"param1": "value1",
424459
},
425460
},
426-
expected: false,
461+
expected: false,
462+
registered: true,
463+
},
464+
{
465+
name: "Invalid dependency - method not registered",
466+
input: Dependency{
467+
Name: "test-dependency",
468+
Method: "UnregisteredMethod",
469+
},
470+
expected: false,
471+
registered: false,
427472
},
428473
} {
429474
t.Run(test.name, func(t *testing.T) {
430475
v := NewConfigValidator("", &Config{})
476+
if test.registered {
477+
RegisteredDependencies[test.input.Method] = true
478+
}
431479
got := isValid(v.validateDependency(&test.input, field.NewPath("")))
432480
if test.expected != got {
433481
t.Errorf("wanted: %v, got: %v", test.expected, got)
@@ -490,6 +538,11 @@ func TestVerifyStep(t *testing.T) {
490538
} {
491539
t.Run(test.name, func(t *testing.T) {
492540
v := NewConfigValidator("", &Config{})
541+
if len(test.input.Measurements) > 0 {
542+
for _, m := range test.input.Measurements {
543+
RegisteredMeasurements[m.Method] = true
544+
}
545+
}
493546
got := isValid(v.validateStep(&test.input, field.NewPath("")))
494547
if test.expected != got {
495548
t.Errorf("wanted: %v, got: %v", test.expected, got)

clusterloader2/pkg/dependency/factory.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ package dependency
1919
import (
2020
"fmt"
2121
"sync"
22+
23+
"k8s.io/perf-tests/clusterloader2/api"
2224
)
2325

2426
// factory is a default global factory instance.
@@ -44,6 +46,7 @@ func (df *dependencyFactory) register(methodName string, createFunc createDepend
4446
return fmt.Errorf("dependency with method %v already exists", methodName)
4547
}
4648
df.createFuncs[methodName] = createFunc
49+
api.RegisteredDependencies[methodName] = true
4750
return nil
4851
}
4952

clusterloader2/pkg/measurement/factory.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ package measurement
1919
import (
2020
"fmt"
2121
"sync"
22+
23+
"k8s.io/perf-tests/clusterloader2/api"
2224
)
2325

2426
// Factory is a default global factory instance.
@@ -44,6 +46,7 @@ func (mc *measurementFactory) register(methodName string, createFunc createMeasu
4446
return fmt.Errorf("measurement with method %v already exists", methodName)
4547
}
4648
mc.createFuncs[methodName] = createFunc
49+
api.RegisteredMeasurements[methodName] = true
4750
return nil
4851
}
4952

0 commit comments

Comments
 (0)