k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/cmd/kubeadm/app/features/features_test.go (about) 1 /* 2 Copyright 2017 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 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 // check the first value is feature1 (the list should be sorted); prerelease and default should be present 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 // check the second value is feature2; prerelease and default should be present 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 // check the second value is feature3; prerelease should not be shown for GA features; default should be present 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 { //invalid value (missing =) 71 value: "invalidValue", 72 expectedError: true, 73 }, 74 { //invalid value (missing =) 75 value: "feature1=true,invalidValue", 76 expectedError: true, 77 }, 78 { //invalid value (not a boolean) 79 value: "feature1=notABoolean", 80 expectedError: true, 81 }, 82 { //invalid value (not a boolean) 83 value: "feature1=true,feature2=notABoolean", 84 expectedError: true, 85 }, 86 { //unrecognized feature-gate key 87 value: "unknownFeature=false", 88 expectedError: true, 89 }, 90 { //unrecognized feature-gate key 91 value: "feature1=true,unknownFeature=false", 92 expectedError: true, 93 }, 94 { //deprecated feature-gate key 95 value: "deprecated=true", 96 expectedError: false, 97 expectedFeaturesGate: map[string]bool{"deprecated": true}, 98 }, 99 { //one feature 100 value: "feature1=true", 101 expectedError: false, 102 expectedFeaturesGate: map[string]bool{"feature1": true}, 103 }, 104 { //two features 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 // TestEnabledDefaults tests that Enabled returns the default values for 176 // each feature gate when no feature gates are specified. 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 }