features_test.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. Copyright 2017 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package features
  14. import (
  15. "reflect"
  16. "testing"
  17. "k8s.io/component-base/featuregate"
  18. "k8s.io/kubernetes/cmd/kubeadm/app/constants"
  19. )
  20. func TestKnownFeatures(t *testing.T) {
  21. var someFeatures = FeatureList{
  22. "feature2": {FeatureSpec: featuregate.FeatureSpec{Default: true, PreRelease: featuregate.Alpha}},
  23. "feature1": {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.Beta}},
  24. "feature3": {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.GA}},
  25. "hidden": {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.GA}, HiddenInHelpText: true},
  26. }
  27. r := KnownFeatures(&someFeatures)
  28. if len(r) != 3 {
  29. t.Errorf("KnownFeatures returned %d values, expected 3", len(r))
  30. }
  31. // check the first value is feature1 (the list should be sorted); prerelease and default should be present
  32. f1 := "feature1=true|false (BETA - default=false)"
  33. if r[0] != f1 {
  34. t.Errorf("KnownFeatures returned %s values, expected %s", r[0], f1)
  35. }
  36. // check the second value is feature2; prerelease and default should be present
  37. f2 := "feature2=true|false (ALPHA - default=true)"
  38. if r[1] != f2 {
  39. t.Errorf("KnownFeatures returned %s values, expected %s", r[1], f2)
  40. }
  41. // check the second value is feature3; prerelease should not be shown for GA features; default should be present
  42. f3 := "feature3=true|false (default=false)"
  43. if r[2] != f3 {
  44. t.Errorf("KnownFeatures returned %s values, expected %s", r[2], f3)
  45. }
  46. }
  47. func TestNewFeatureGate(t *testing.T) {
  48. var someFeatures = FeatureList{
  49. "feature1": {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.Beta}},
  50. "feature2": {FeatureSpec: featuregate.FeatureSpec{Default: true, PreRelease: featuregate.Alpha}},
  51. "deprecated": {FeatureSpec: featuregate.FeatureSpec{Default: true, PreRelease: featuregate.Deprecated}},
  52. }
  53. var tests = []struct {
  54. value string
  55. expectedError bool
  56. expectedFeaturesGate map[string]bool
  57. }{
  58. { //invalid value (missing =)
  59. value: "invalidValue",
  60. expectedError: true,
  61. },
  62. { //invalid value (missing =)
  63. value: "feature1=true,invalidValue",
  64. expectedError: true,
  65. },
  66. { //invalid value (not a boolean)
  67. value: "feature1=notABoolean",
  68. expectedError: true,
  69. },
  70. { //invalid value (not a boolean)
  71. value: "feature1=true,feature2=notABoolean",
  72. expectedError: true,
  73. },
  74. { //unrecognized feature-gate key
  75. value: "unknownFeature=false",
  76. expectedError: true,
  77. },
  78. { //unrecognized feature-gate key
  79. value: "feature1=true,unknownFeature=false",
  80. expectedError: true,
  81. },
  82. { //deprecated feature-gate key
  83. value: "deprecated=true",
  84. expectedError: true,
  85. },
  86. { //one feature
  87. value: "feature1=true",
  88. expectedError: false,
  89. expectedFeaturesGate: map[string]bool{"feature1": true},
  90. },
  91. { //two features
  92. value: "feature1=true,feature2=false",
  93. expectedError: false,
  94. expectedFeaturesGate: map[string]bool{"feature1": true, "feature2": false},
  95. },
  96. }
  97. for _, test := range tests {
  98. t.Run(test.value, func(t *testing.T) {
  99. r, err := NewFeatureGate(&someFeatures, test.value)
  100. if !test.expectedError && err != nil {
  101. t.Errorf("NewFeatureGate failed when not expected: %v", err)
  102. return
  103. } else if test.expectedError && err == nil {
  104. t.Error("NewFeatureGate didn't failed when expected")
  105. return
  106. }
  107. if !reflect.DeepEqual(r, test.expectedFeaturesGate) {
  108. t.Errorf("NewFeatureGate returned a unexpected value")
  109. }
  110. })
  111. }
  112. }
  113. func TestValidateVersion(t *testing.T) {
  114. var someFeatures = FeatureList{
  115. "feature1": {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.Beta}},
  116. "feature2": {FeatureSpec: featuregate.FeatureSpec{Default: true, PreRelease: featuregate.Alpha}, MinimumVersion: constants.MinimumControlPlaneVersion.WithPreRelease("alpha.1")},
  117. }
  118. var tests = []struct {
  119. name string
  120. requestedVersion string
  121. requestedFeatures map[string]bool
  122. expectedError bool
  123. }{
  124. {
  125. name: "no min version",
  126. requestedFeatures: map[string]bool{"feature1": true},
  127. expectedError: false,
  128. },
  129. {
  130. name: "min version but correct value given",
  131. requestedFeatures: map[string]bool{"feature2": true},
  132. requestedVersion: constants.MinimumControlPlaneVersion.String(),
  133. expectedError: false,
  134. },
  135. {
  136. name: "min version and incorrect value given",
  137. requestedFeatures: map[string]bool{"feature2": true},
  138. requestedVersion: "v1.11.2",
  139. expectedError: true,
  140. },
  141. }
  142. for _, test := range tests {
  143. t.Run(test.name, func(t *testing.T) {
  144. err := ValidateVersion(someFeatures, test.requestedFeatures, test.requestedVersion)
  145. if !test.expectedError && err != nil {
  146. t.Errorf("ValidateVersion failed when not expected: %v", err)
  147. return
  148. } else if test.expectedError && err == nil {
  149. t.Error("ValidateVersion didn't failed when expected")
  150. return
  151. }
  152. })
  153. }
  154. }
  155. // TestEnabledDefaults tests that Enabled returns the default values for
  156. // each feature gate when no feature gates are specified.
  157. func TestEnabledDefaults(t *testing.T) {
  158. for featureName, feature := range InitFeatureGates {
  159. featureList := make(map[string]bool)
  160. enabled := Enabled(featureList, featureName)
  161. if enabled != feature.Default {
  162. t.Errorf("Enabled returned %v instead of default value %v for feature %s", enabled, feature.Default, featureName)
  163. }
  164. }
  165. }
  166. func TestCheckDeprecatedFlags(t *testing.T) {
  167. dummyMessage := "dummy message"
  168. var someFeatures = FeatureList{
  169. "feature1": {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.Beta}},
  170. "deprecated": {FeatureSpec: featuregate.FeatureSpec{Default: true, PreRelease: featuregate.Deprecated}, DeprecationMessage: dummyMessage},
  171. }
  172. var tests = []struct {
  173. name string
  174. features map[string]bool
  175. expectedMsg map[string]string
  176. }{
  177. {
  178. name: "deprecated feature",
  179. features: map[string]bool{"deprecated": true},
  180. expectedMsg: map[string]string{"deprecated": dummyMessage},
  181. },
  182. {
  183. name: "valid feature",
  184. features: map[string]bool{"feature1": true},
  185. expectedMsg: map[string]string{},
  186. },
  187. }
  188. for _, test := range tests {
  189. t.Run(test.name, func(t *testing.T) {
  190. msg := CheckDeprecatedFlags(&someFeatures, test.features)
  191. if !reflect.DeepEqual(test.expectedMsg, msg) {
  192. t.Error("CheckDeprecatedFlags didn't returned expected message")
  193. }
  194. })
  195. }
  196. }