...

Source file src/k8s.io/kubernetes/pkg/registry/flowcontrol/prioritylevelconfiguration/strategy_test.go

Documentation: k8s.io/kubernetes/pkg/registry/flowcontrol/prioritylevelconfiguration

     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  }
   213  

View as plain text