...
1
16
17 package testing
18
19 import (
20 "fmt"
21 "strings"
22 "sync"
23 "testing"
24
25 "k8s.io/component-base/featuregate"
26 )
27
28 var (
29 overrideLock sync.Mutex
30 featureFlagOverride map[featuregate.Feature]string
31 )
32
33 func init() {
34 featureFlagOverride = map[featuregate.Feature]string{}
35 }
36
37
38
39
40
41
42
43
44
45
46
47 func SetFeatureGateDuringTest(tb testing.TB, gate featuregate.FeatureGate, f featuregate.Feature, value bool) func() {
48 tb.Helper()
49 detectParallelOverrideCleanup := detectParallelOverride(tb, f)
50 originalValue := gate.Enabled(f)
51
52
53 var cleanups []func()
54 if f == "AllAlpha" || f == "AllBeta" {
55
56 for k, v := range gate.(featuregate.MutableFeatureGate).GetAll() {
57 if k == "AllAlpha" || k == "AllBeta" {
58 continue
59 }
60 if (f == "AllAlpha" && v.PreRelease == featuregate.Alpha) || (f == "AllBeta" && v.PreRelease == featuregate.Beta) {
61 cleanups = append(cleanups, SetFeatureGateDuringTest(tb, gate, k, value))
62 }
63 }
64 }
65
66 if err := gate.(featuregate.MutableFeatureGate).Set(fmt.Sprintf("%s=%v", f, value)); err != nil {
67 tb.Errorf("error setting %s=%v: %v", f, value, err)
68 }
69
70 tb.Cleanup(func() {
71 tb.Helper()
72 detectParallelOverrideCleanup()
73 if err := gate.(featuregate.MutableFeatureGate).Set(fmt.Sprintf("%s=%v", f, originalValue)); err != nil {
74 tb.Errorf("error restoring %s=%v: %v", f, originalValue, err)
75 }
76 for _, cleanup := range cleanups {
77 cleanup()
78 }
79 })
80 return func() {}
81 }
82
83 func detectParallelOverride(tb testing.TB, f featuregate.Feature) func() {
84 tb.Helper()
85 overrideLock.Lock()
86 defer overrideLock.Unlock()
87 beforeOverrideTestName := featureFlagOverride[f]
88 if beforeOverrideTestName != "" && !sameTestOrSubtest(tb, beforeOverrideTestName) {
89 tb.Fatalf("Detected parallel setting of a feature gate by both %q and %q", beforeOverrideTestName, tb.Name())
90 }
91 featureFlagOverride[f] = tb.Name()
92
93 return func() {
94 tb.Helper()
95 overrideLock.Lock()
96 defer overrideLock.Unlock()
97 if afterOverrideTestName := featureFlagOverride[f]; afterOverrideTestName != tb.Name() {
98 tb.Fatalf("Detected parallel setting of a feature gate between both %q and %q", afterOverrideTestName, tb.Name())
99 }
100 featureFlagOverride[f] = beforeOverrideTestName
101 }
102 }
103
104 func sameTestOrSubtest(tb testing.TB, testName string) bool {
105
106 return tb.Name() == testName || strings.HasPrefix(tb.Name(), testName+"/")
107 }
108
View as plain text