1
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
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
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)
203 }
204 return Strategy.ValidateUpdate(ctx, obj, old)
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 }
213
View as plain text