1
16
17 package features
18
19 import (
20 "reflect"
21 "testing"
22
23 "k8s.io/apimachinery/pkg/util/version"
24 "k8s.io/component-base/featuregate"
25 )
26
27 func TestKnownFeatures(t *testing.T) {
28 var someFeatures = FeatureList{
29 "feature2": {FeatureSpec: featuregate.FeatureSpec{Default: true, PreRelease: featuregate.Alpha}},
30 "feature1": {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.Beta}},
31 "feature3": {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.GA}},
32 "hidden": {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.GA}, HiddenInHelpText: true},
33 }
34
35 r := KnownFeatures(&someFeatures)
36
37 if len(r) != 3 {
38 t.Errorf("KnownFeatures returned %d values, expected 3", len(r))
39 }
40
41
42 f1 := "feature1=true|false (BETA - default=false)"
43 if r[0] != f1 {
44 t.Errorf("KnownFeatures returned %s values, expected %s", r[0], f1)
45 }
46
47 f2 := "feature2=true|false (ALPHA - default=true)"
48 if r[1] != f2 {
49 t.Errorf("KnownFeatures returned %s values, expected %s", r[1], f2)
50 }
51
52 f3 := "feature3=true|false (default=false)"
53 if r[2] != f3 {
54 t.Errorf("KnownFeatures returned %s values, expected %s", r[2], f3)
55 }
56 }
57
58 func TestNewFeatureGate(t *testing.T) {
59 var someFeatures = FeatureList{
60 "feature1": {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.Beta}},
61 "feature2": {FeatureSpec: featuregate.FeatureSpec{Default: true, PreRelease: featuregate.Alpha}},
62 "deprecated": {FeatureSpec: featuregate.FeatureSpec{Default: true, PreRelease: featuregate.Deprecated}},
63 }
64
65 var tests = []struct {
66 value string
67 expectedError bool
68 expectedFeaturesGate map[string]bool
69 }{
70 {
71 value: "invalidValue",
72 expectedError: true,
73 },
74 {
75 value: "feature1=true,invalidValue",
76 expectedError: true,
77 },
78 {
79 value: "feature1=notABoolean",
80 expectedError: true,
81 },
82 {
83 value: "feature1=true,feature2=notABoolean",
84 expectedError: true,
85 },
86 {
87 value: "unknownFeature=false",
88 expectedError: true,
89 },
90 {
91 value: "feature1=true,unknownFeature=false",
92 expectedError: true,
93 },
94 {
95 value: "deprecated=true",
96 expectedError: false,
97 expectedFeaturesGate: map[string]bool{"deprecated": true},
98 },
99 {
100 value: "feature1=true",
101 expectedError: false,
102 expectedFeaturesGate: map[string]bool{"feature1": true},
103 },
104 {
105 value: "feature1=true,feature2=false",
106 expectedError: false,
107 expectedFeaturesGate: map[string]bool{"feature1": true, "feature2": false},
108 },
109 }
110
111 for _, test := range tests {
112 t.Run(test.value, func(t *testing.T) {
113 r, err := NewFeatureGate(&someFeatures, test.value)
114
115 if !test.expectedError && err != nil {
116 t.Errorf("NewFeatureGate failed when not expected: %v", err)
117 return
118 } else if test.expectedError && err == nil {
119 t.Error("NewFeatureGate didn't failed when expected")
120 return
121 }
122
123 if !reflect.DeepEqual(r, test.expectedFeaturesGate) {
124 t.Errorf("NewFeatureGate returned a unexpected value")
125 }
126 })
127 }
128 }
129
130 func TestValidateVersion(t *testing.T) {
131 var someFeatures = FeatureList{
132 "feature1": {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.Beta}},
133 "feature2": {FeatureSpec: featuregate.FeatureSpec{Default: true, PreRelease: featuregate.Alpha}, MinimumVersion: version.MustParseSemantic("v1.17.0").WithPreRelease("alpha.1")},
134 }
135
136 var tests = []struct {
137 name string
138 requestedVersion string
139 requestedFeatures map[string]bool
140 expectedError bool
141 }{
142 {
143 name: "no min version",
144 requestedFeatures: map[string]bool{"feature1": true},
145 expectedError: false,
146 },
147 {
148 name: "min version but correct value given",
149 requestedFeatures: map[string]bool{"feature2": true},
150 requestedVersion: "v1.17.0",
151 expectedError: false,
152 },
153 {
154 name: "min version and incorrect value given",
155 requestedFeatures: map[string]bool{"feature2": true},
156 requestedVersion: "v1.11.2",
157 expectedError: true,
158 },
159 }
160
161 for _, test := range tests {
162 t.Run(test.name, func(t *testing.T) {
163 err := ValidateVersion(someFeatures, test.requestedFeatures, test.requestedVersion)
164 if !test.expectedError && err != nil {
165 t.Errorf("ValidateVersion failed when not expected: %v", err)
166 return
167 } else if test.expectedError && err == nil {
168 t.Error("ValidateVersion didn't failed when expected")
169 return
170 }
171 })
172 }
173 }
174
175
176
177 func TestEnabledDefaults(t *testing.T) {
178 for featureName, feature := range InitFeatureGates {
179 featureList := make(map[string]bool)
180
181 enabled := Enabled(featureList, featureName)
182 if enabled != feature.Default {
183 t.Errorf("Enabled returned %v instead of default value %v for feature %s", enabled, feature.Default, featureName)
184 }
185 }
186 }
187
188 func TestCheckDeprecatedFlags(t *testing.T) {
189 dummyMessage := "dummy message"
190 var someFeatures = FeatureList{
191 "feature1": {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.Beta}},
192 "deprecated": {FeatureSpec: featuregate.FeatureSpec{Default: true, PreRelease: featuregate.Deprecated}, DeprecationMessage: dummyMessage},
193 }
194
195 var tests = []struct {
196 name string
197 features map[string]bool
198 expectedMsg map[string]string
199 }{
200 {
201 name: "deprecated feature",
202 features: map[string]bool{"deprecated": true},
203 expectedMsg: map[string]string{"deprecated": dummyMessage},
204 },
205 {
206 name: "valid feature",
207 features: map[string]bool{"feature1": true},
208 expectedMsg: map[string]string{},
209 },
210 {
211 name: "invalid feature",
212 features: map[string]bool{"feature2": true},
213 expectedMsg: map[string]string{"feature2": "Unknown feature gate flag: feature2"},
214 },
215 }
216
217 for _, test := range tests {
218 t.Run(test.name, func(t *testing.T) {
219 msg := CheckDeprecatedFlags(&someFeatures, test.features)
220 if !reflect.DeepEqual(test.expectedMsg, msg) {
221 t.Errorf("CheckDeprecatedFlags() = %v, want %v", msg, test.expectedMsg)
222 }
223 })
224 }
225 }
226
227 func TestSupports(t *testing.T) {
228 tests := []struct {
229 name string
230 featureName string
231 want bool
232 }{
233 {
234 name: "the feature is not supported",
235 featureName: "foo",
236 want: false,
237 },
238 {
239 name: "the feature is supported",
240 featureName: PublicKeysECDSA,
241 want: true,
242 },
243 }
244 for _, test := range tests {
245 t.Run(test.name, func(t *testing.T) {
246 if got := Supports(InitFeatureGates, test.featureName); got != test.want {
247 t.Errorf("Supports() = %v, want %v", got, test.want)
248 }
249 })
250 }
251 }
252
View as plain text