@@ -23,21 +23,21 @@ import (
23
23
"github.com/stretchr/testify/require"
24
24
)
25
25
26
+ var defaultTestFeatures = map [Feature ]FeatureSpec {
27
+ "TestAlpha" : {
28
+ Default : false ,
29
+ LockToDefault : false ,
30
+ PreRelease : "Alpha" ,
31
+ },
32
+ "TestBeta" : {
33
+ Default : true ,
34
+ LockToDefault : false ,
35
+ PreRelease : "Beta" ,
36
+ },
37
+ }
38
+
26
39
func TestEnvVarFeatureGates (t * testing.T ) {
27
- defaultTestFeatures := map [Feature ]FeatureSpec {
28
- "TestAlpha" : {
29
- Default : false ,
30
- LockToDefault : false ,
31
- PreRelease : "Alpha" ,
32
- },
33
- "TestBeta" : {
34
- Default : true ,
35
- LockToDefault : false ,
36
- PreRelease : "Beta" ,
37
- },
38
- }
39
40
expectedDefaultFeaturesState := map [Feature ]bool {"TestAlpha" : false , "TestBeta" : true }
40
-
41
41
copyExpectedStateMap := func (toCopy map [Feature ]bool ) map [Feature ]bool {
42
42
m := map [Feature ]bool {}
43
43
for k , v := range toCopy {
@@ -47,11 +47,14 @@ func TestEnvVarFeatureGates(t *testing.T) {
47
47
}
48
48
49
49
scenarios := []struct {
50
- name string
51
- features map [Feature ]FeatureSpec
52
- envVariables map [string ]string
53
- expectedFeaturesState map [Feature ]bool
54
- expectedInternalEnabledFeatureState map [Feature ]bool
50
+ name string
51
+ features map [Feature ]FeatureSpec
52
+ envVariables map [string ]string
53
+ setMethodFeatures map [Feature ]bool
54
+
55
+ expectedFeaturesState map [Feature ]bool
56
+ expectedInternalEnabledViaEnvVarFeatureState map [Feature ]bool
57
+ expectedInternalEnabledViaSetMethodFeatureState map [Feature ]bool
55
58
}{
56
59
{
57
60
name : "can add empty features" ,
@@ -76,7 +79,7 @@ func TestEnvVarFeatureGates(t *testing.T) {
76
79
expectedDefaultFeaturesStateCopy ["TestAlpha" ] = true
77
80
return expectedDefaultFeaturesStateCopy
78
81
}(),
79
- expectedInternalEnabledFeatureState : map [Feature ]bool {"TestAlpha" : true },
82
+ expectedInternalEnabledViaEnvVarFeatureState : map [Feature ]bool {"TestAlpha" : true },
80
83
},
81
84
{
82
85
name : "incorrect env var value gets ignored" ,
@@ -111,9 +114,25 @@ func TestEnvVarFeatureGates(t *testing.T) {
111
114
PreRelease : "Alpha" ,
112
115
},
113
116
},
114
- envVariables : map [string ]string {"KUBE_FEATURE_TestAlpha" : "True" },
115
- expectedFeaturesState : map [Feature ]bool {"TestAlpha" : true },
116
- expectedInternalEnabledFeatureState : map [Feature ]bool {"TestAlpha" : true },
117
+ envVariables : map [string ]string {"KUBE_FEATURE_TestAlpha" : "True" },
118
+ expectedFeaturesState : map [Feature ]bool {"TestAlpha" : true },
119
+ expectedInternalEnabledViaEnvVarFeatureState : map [Feature ]bool {"TestAlpha" : true },
120
+ },
121
+ {
122
+ name : "setting a feature via the Set method works" ,
123
+ features : defaultTestFeatures ,
124
+ setMethodFeatures : map [Feature ]bool {"TestAlpha" : true },
125
+ expectedFeaturesState : map [Feature ]bool {"TestAlpha" : true },
126
+ expectedInternalEnabledViaSetMethodFeatureState : map [Feature ]bool {"TestAlpha" : true },
127
+ },
128
+ {
129
+ name : "setting a feature via the Set method wins" ,
130
+ features : defaultTestFeatures ,
131
+ setMethodFeatures : map [Feature ]bool {"TestAlpha" : false },
132
+ envVariables : map [string ]string {"KUBE_FEATURE_TestAlpha" : "True" },
133
+ expectedFeaturesState : map [Feature ]bool {"TestAlpha" : false },
134
+ expectedInternalEnabledViaEnvVarFeatureState : map [Feature ]bool {"TestAlpha" : true },
135
+ expectedInternalEnabledViaSetMethodFeatureState : map [Feature ]bool {"TestAlpha" : false },
117
136
},
118
137
}
119
138
for _ , scenario := range scenarios {
@@ -123,20 +142,33 @@ func TestEnvVarFeatureGates(t *testing.T) {
123
142
}
124
143
target := newEnvVarFeatureGates (scenario .features )
125
144
145
+ for k , v := range scenario .setMethodFeatures {
146
+ err := target .Set (k , v )
147
+ require .NoError (t , err )
148
+ }
126
149
for expectedFeature , expectedValue := range scenario .expectedFeaturesState {
127
150
actualValue := target .Enabled (expectedFeature )
128
151
require .Equal (t , actualValue , expectedValue , "expected feature=%v, to be=%v, not=%v" , expectedFeature , expectedValue , actualValue )
129
152
}
130
153
131
- enabledInternalMap := target .enabled .Load ().(map [Feature ]bool )
132
- require .Len (t , enabledInternalMap , len (scenario .expectedInternalEnabledFeatureState ))
133
-
134
- for expectedFeature , expectedInternalPresence := range scenario .expectedInternalEnabledFeatureState {
135
- featureInternalValue , featureSet := enabledInternalMap [expectedFeature ]
136
- require .Equal (t , expectedInternalPresence , featureSet , "feature %v present = %v, expected = %v" , expectedFeature , featureSet , expectedInternalPresence )
154
+ enabledViaEnvVarInternalMap := target .enabledViaEnvVar .Load ().(map [Feature ]bool )
155
+ require .Len (t , enabledViaEnvVarInternalMap , len (scenario .expectedInternalEnabledViaEnvVarFeatureState ))
156
+ for expectedFeatureName , expectedFeatureValue := range scenario .expectedInternalEnabledViaEnvVarFeatureState {
157
+ actualFeatureValue , wasExpectedFeatureFound := enabledViaEnvVarInternalMap [expectedFeatureName ]
158
+ if ! wasExpectedFeatureFound {
159
+ t .Errorf ("feature %v has not been found in enabledViaEnvVarInternalMap" , expectedFeatureName )
160
+ }
161
+ require .Equal (t , expectedFeatureValue , actualFeatureValue , "feature %v has incorrect value = %v, expected = %v" , expectedFeatureName , actualFeatureValue , expectedFeatureValue )
162
+ }
137
163
138
- expectedFeatureInternalValue := scenario .expectedFeaturesState [expectedFeature ]
139
- require .Equal (t , expectedFeatureInternalValue , featureInternalValue )
164
+ enabledViaSetMethodInternalMap := target .enabledViaSetMethod
165
+ require .Len (t , enabledViaSetMethodInternalMap , len (scenario .expectedInternalEnabledViaSetMethodFeatureState ))
166
+ for expectedFeatureName , expectedFeatureValue := range scenario .expectedInternalEnabledViaSetMethodFeatureState {
167
+ actualFeatureValue , wasExpectedFeatureFound := enabledViaSetMethodInternalMap [expectedFeatureName ]
168
+ if ! wasExpectedFeatureFound {
169
+ t .Errorf ("feature %v has not been found in enabledViaSetMethod" , expectedFeatureName )
170
+ }
171
+ require .Equal (t , expectedFeatureValue , actualFeatureValue , "feature %v has incorrect value = %v, expected = %v" , expectedFeatureName , actualFeatureValue , expectedFeatureValue )
140
172
}
141
173
})
142
174
}
@@ -154,3 +186,48 @@ func TestHasAlreadyReadEnvVar(t *testing.T) {
154
186
_ = target .getEnabledMapFromEnvVar ()
155
187
require .True (t , target .hasAlreadyReadEnvVar ())
156
188
}
189
+
190
+ func TestEnvVarFeatureGatesSetNegative (t * testing.T ) {
191
+ scenarios := []struct {
192
+ name string
193
+ features map [Feature ]FeatureSpec
194
+ featureName Feature
195
+ featureValue bool
196
+
197
+ expectedErr func (string ) error
198
+ }{
199
+ {
200
+ name : "empty feature name returns an error" ,
201
+ features : defaultTestFeatures ,
202
+ expectedErr : func (callSiteName string ) error {
203
+ return fmt .Errorf ("feature %q is not registered in FeatureGates %q" , "" , callSiteName )
204
+ },
205
+ },
206
+ {
207
+ name : "setting unknown feature returns an error" ,
208
+ features : defaultTestFeatures ,
209
+ featureName : "Unknown" ,
210
+ expectedErr : func (callSiteName string ) error {
211
+ return fmt .Errorf ("feature %q is not registered in FeatureGates %q" , "Unknown" , callSiteName )
212
+ },
213
+ },
214
+ {
215
+ name : "setting locked feature returns an error" ,
216
+ features : map [Feature ]FeatureSpec {"LockedFeature" : {LockToDefault : true , Default : true }},
217
+ featureName : "LockedFeature" ,
218
+ featureValue : false ,
219
+ expectedErr : func (_ string ) error {
220
+ return fmt .Errorf ("cannot set feature gate %q to %v, feature is locked to %v" , "LockedFeature" , false , true )
221
+ },
222
+ },
223
+ }
224
+
225
+ for _ , scenario := range scenarios {
226
+ t .Run (scenario .name , func (t * testing.T ) {
227
+ target := newEnvVarFeatureGates (scenario .features )
228
+
229
+ err := target .Set (scenario .featureName , scenario .featureValue )
230
+ require .Equal (t , scenario .expectedErr (target .callSiteName ), err )
231
+ })
232
+ }
233
+ }
0 commit comments