k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/registry/flowcontrol/prioritylevelconfiguration/strategy_test.go (about) 1 /* 2 Copyright 2023 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 prioritylevelconfiguration 18 19 import ( 20 "context" 21 "testing" 22 23 flowcontrolv1 "k8s.io/api/flowcontrol/v1" 24 flowcontrolv1beta3 "k8s.io/api/flowcontrol/v1beta3" 25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 "k8s.io/apimachinery/pkg/runtime" 27 "k8s.io/apimachinery/pkg/util/validation/field" 28 "k8s.io/kubernetes/pkg/apis/flowcontrol" 29 "k8s.io/utils/ptr" 30 31 "github.com/google/go-cmp/cmp" 32 ) 33 34 func TestPriorityLevelConfigurationValidation(t *testing.T) { 35 v1ObjFn := func(v *int32) *flowcontrolv1.PriorityLevelConfiguration { 36 return &flowcontrolv1.PriorityLevelConfiguration{ 37 ObjectMeta: metav1.ObjectMeta{ 38 Name: "foo", 39 }, 40 Spec: flowcontrolv1.PriorityLevelConfigurationSpec{ 41 Type: flowcontrolv1.PriorityLevelEnablementLimited, 42 Limited: &flowcontrolv1.LimitedPriorityLevelConfiguration{ 43 NominalConcurrencyShares: v, 44 LimitResponse: flowcontrolv1.LimitResponse{ 45 Type: flowcontrolv1.LimitResponseTypeReject}, 46 }, 47 }, 48 } 49 } 50 v1beta3ObjFn := func(v int32, isZero bool) *flowcontrolv1beta3.PriorityLevelConfiguration { 51 obj := &flowcontrolv1beta3.PriorityLevelConfiguration{ 52 ObjectMeta: metav1.ObjectMeta{ 53 Name: "foo", 54 }, 55 Spec: flowcontrolv1beta3.PriorityLevelConfigurationSpec{ 56 Type: flowcontrolv1beta3.PriorityLevelEnablementLimited, 57 Limited: &flowcontrolv1beta3.LimitedPriorityLevelConfiguration{ 58 NominalConcurrencyShares: v, 59 LimitResponse: flowcontrolv1beta3.LimitResponse{ 60 Type: flowcontrolv1beta3.LimitResponseTypeReject}, 61 }, 62 }, 63 } 64 if isZero && v == 0 { 65 obj.ObjectMeta.Annotations = map[string]string{} 66 obj.ObjectMeta.Annotations[flowcontrolv1beta3.PriorityLevelPreserveZeroConcurrencySharesKey] = "" 67 } 68 return obj 69 } 70 internalObjFn := func(v int32) *flowcontrol.PriorityLevelConfiguration { 71 return &flowcontrol.PriorityLevelConfiguration{ 72 ObjectMeta: metav1.ObjectMeta{ 73 Name: "foo", 74 }, 75 Spec: flowcontrol.PriorityLevelConfigurationSpec{ 76 Type: flowcontrol.PriorityLevelEnablementLimited, 77 Limited: &flowcontrol.LimitedPriorityLevelConfiguration{ 78 NominalConcurrencyShares: v, 79 LimitResponse: flowcontrol.LimitResponse{ 80 Type: flowcontrol.LimitResponseTypeReject}, 81 }, 82 }, 83 } 84 } 85 v1SchemeFn := func(t *testing.T) *runtime.Scheme { 86 scheme := runtime.NewScheme() 87 if err := flowcontrolv1.AddToScheme(scheme); err != nil { 88 t.Fatalf("Failed to add to scheme: %v", err) 89 } 90 return scheme 91 } 92 v1beta3SchemeFn := func(t *testing.T) *runtime.Scheme { 93 scheme := runtime.NewScheme() 94 if err := flowcontrolv1beta3.AddToScheme(scheme); err != nil { 95 t.Fatalf("Failed to add to scheme: %v", err) 96 } 97 return scheme 98 } 99 100 tests := []struct { 101 name string 102 obj runtime.Object 103 old *flowcontrol.PriorityLevelConfiguration // for UPDATE only 104 scheme *runtime.Scheme 105 errExpected field.ErrorList 106 }{ 107 { 108 name: "v1, create, zero value, no error expected", 109 obj: v1ObjFn(ptr.To(int32(0))), 110 scheme: v1SchemeFn(t), 111 errExpected: nil, 112 }, 113 { 114 name: "v1, create, unset, no error expected", 115 obj: v1ObjFn(nil), 116 scheme: v1SchemeFn(t), 117 errExpected: nil, 118 }, 119 { 120 name: "v1, create, non-zero, no error expected", 121 obj: v1ObjFn(ptr.To(int32(1))), 122 scheme: v1SchemeFn(t), 123 errExpected: nil, 124 }, 125 { 126 name: "v1beta3, create, zero value, no error expected", 127 obj: v1beta3ObjFn(0, true), 128 scheme: v1beta3SchemeFn(t), 129 errExpected: nil, 130 }, 131 { 132 name: "v1beta3, create, zero value without annotation, no error expected", 133 obj: v1beta3ObjFn(0, false), 134 scheme: v1beta3SchemeFn(t), 135 errExpected: nil, 136 }, 137 { 138 name: "v1beta3, create, non-zero, no error expected", 139 obj: v1beta3ObjFn(1, false), 140 scheme: v1beta3SchemeFn(t), 141 errExpected: nil, 142 }, 143 144 // the following use cases cover UPDATE 145 { 146 name: "v1, update, zero value, existing has non-zero, no error expected", 147 obj: v1ObjFn(ptr.To(int32(0))), 148 old: internalObjFn(1), 149 scheme: v1SchemeFn(t), 150 errExpected: nil, 151 }, 152 { 153 name: "v1, update, zero value, existing has zero, no error expected", 154 obj: v1ObjFn(ptr.To(int32(0))), 155 old: internalObjFn(0), 156 scheme: v1SchemeFn(t), 157 errExpected: nil, 158 }, 159 { 160 name: "v1, update, non-zero value, existing has zero, no error expected", 161 obj: v1ObjFn(ptr.To(int32(1))), 162 old: internalObjFn(0), 163 scheme: v1SchemeFn(t), 164 errExpected: nil, 165 }, 166 { 167 name: "v1beta3, update, zero value, existing has non-zero, no error expected", 168 obj: v1beta3ObjFn(0, true), 169 old: internalObjFn(1), 170 scheme: v1beta3SchemeFn(t), 171 errExpected: nil, 172 }, 173 { 174 name: "v1beta3, update, zero value, existing has zero, no error expected", 175 obj: v1beta3ObjFn(0, true), 176 old: internalObjFn(0), 177 scheme: v1beta3SchemeFn(t), 178 errExpected: nil, 179 }, 180 { 181 name: "v1beta3, update, non-zero value, existing has zero, no error expected", 182 obj: v1beta3ObjFn(1, false), 183 old: internalObjFn(0), 184 scheme: v1beta3SchemeFn(t), 185 errExpected: nil, 186 }, 187 } 188 189 for _, test := range tests { 190 t.Run(test.name, func(t *testing.T) { 191 scheme := test.scheme 192 scheme.Default(test.obj) 193 194 ctx := context.TODO() 195 internal := &flowcontrol.PriorityLevelConfiguration{} 196 if err := scheme.Convert(test.obj, internal, ctx); err != nil { 197 t.Errorf("Expected no error while converting to internal type: %v", err) 198 } 199 200 err := func(obj, old *flowcontrol.PriorityLevelConfiguration) field.ErrorList { 201 if old == nil { 202 return Strategy.Validate(ctx, obj) // for create operation 203 } 204 return Strategy.ValidateUpdate(ctx, obj, old) // for update operation 205 }(internal, test.old) 206 207 if !cmp.Equal(test.errExpected, err) { 208 t.Errorf("Expected error: %v, diff: %s", test.errExpected, cmp.Diff(test.errExpected, err)) 209 } 210 }) 211 } 212 }