github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/pkg/api/validation/objectmeta_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 validation
    18  
    19  import (
    20  	"math/rand"
    21  	"reflect"
    22  	"strings"
    23  	"testing"
    24  	"time"
    25  
    26  	metav1 "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/apis/meta/v1"
    27  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/util/validation/field"
    28  )
    29  
    30  const (
    31  	maxLengthErrMsg = "must be no more than"
    32  	namePartErrMsg  = "name part must consist of"
    33  	nameErrMsg      = "a qualified name must consist of"
    34  )
    35  
    36  // Ensure custom name functions are allowed
    37  func TestValidateObjectMetaCustomName(t *testing.T) {
    38  	errs := ValidateObjectMeta(
    39  		&metav1.ObjectMeta{Name: "test", GenerateName: "foo"},
    40  		false,
    41  		func(s string, prefix bool) []string {
    42  			if s == "test" {
    43  				return nil
    44  			}
    45  			return []string{"name-gen"}
    46  		},
    47  		field.NewPath("field"))
    48  	if len(errs) != 1 {
    49  		t.Fatalf("unexpected errors: %v", errs)
    50  	}
    51  	if !strings.Contains(errs[0].Error(), "name-gen") {
    52  		t.Errorf("unexpected error message: %v", errs)
    53  	}
    54  }
    55  
    56  // Ensure namespace names follow dns label format
    57  func TestValidateObjectMetaNamespaces(t *testing.T) {
    58  	errs := ValidateObjectMeta(
    59  		&metav1.ObjectMeta{Name: "test", Namespace: "foo.bar"},
    60  		true,
    61  		func(s string, prefix bool) []string {
    62  			return nil
    63  		},
    64  		field.NewPath("field"))
    65  	if len(errs) != 1 {
    66  		t.Fatalf("unexpected errors: %v", errs)
    67  	}
    68  	if !strings.Contains(errs[0].Error(), `Invalid value: "foo.bar"`) {
    69  		t.Errorf("unexpected error message: %v", errs)
    70  	}
    71  	maxLength := 63
    72  	letters := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
    73  	b := make([]rune, maxLength+1)
    74  	for i := range b {
    75  		b[i] = letters[rand.Intn(len(letters))]
    76  	}
    77  	errs = ValidateObjectMeta(
    78  		&metav1.ObjectMeta{Name: "test", Namespace: string(b)},
    79  		true,
    80  		func(s string, prefix bool) []string {
    81  			return nil
    82  		},
    83  		field.NewPath("field"))
    84  	if len(errs) != 2 {
    85  		t.Fatalf("unexpected errors: %v", errs)
    86  	}
    87  	if !strings.Contains(errs[0].Error(), "Invalid value") || !strings.Contains(errs[1].Error(), "Invalid value") {
    88  		t.Errorf("unexpected error message: %v", errs)
    89  	}
    90  }
    91  
    92  func TestValidateObjectMetaOwnerReferences(t *testing.T) {
    93  	trueVar := true
    94  	falseVar := false
    95  	testCases := []struct {
    96  		description          string
    97  		ownerReferences      []metav1.OwnerReference
    98  		expectError          bool
    99  		expectedErrorMessage string
   100  	}{
   101  		{
   102  			description: "simple success - third party extension.",
   103  			ownerReferences: []metav1.OwnerReference{
   104  				{
   105  					APIVersion: "customresourceVersion",
   106  					Kind:       "customresourceKind",
   107  					Name:       "name",
   108  					UID:        "1",
   109  				},
   110  			},
   111  			expectError:          false,
   112  			expectedErrorMessage: "",
   113  		},
   114  		{
   115  			description: "simple failures - event shouldn't be set as an owner",
   116  			ownerReferences: []metav1.OwnerReference{
   117  				{
   118  					APIVersion: "v1",
   119  					Kind:       "Event",
   120  					Name:       "name",
   121  					UID:        "1",
   122  				},
   123  			},
   124  			expectError:          true,
   125  			expectedErrorMessage: "is disallowed from being an owner",
   126  		},
   127  		{
   128  			description: "simple controller ref success - one reference with Controller set",
   129  			ownerReferences: []metav1.OwnerReference{
   130  				{
   131  					APIVersion: "customresourceVersion",
   132  					Kind:       "customresourceKind",
   133  					Name:       "name",
   134  					UID:        "1",
   135  					Controller: &falseVar,
   136  				},
   137  				{
   138  					APIVersion: "customresourceVersion",
   139  					Kind:       "customresourceKind",
   140  					Name:       "name",
   141  					UID:        "2",
   142  					Controller: &trueVar,
   143  				},
   144  				{
   145  					APIVersion: "customresourceVersion",
   146  					Kind:       "customresourceKind",
   147  					Name:       "name",
   148  					UID:        "3",
   149  					Controller: &falseVar,
   150  				},
   151  				{
   152  					APIVersion: "customresourceVersion",
   153  					Kind:       "customresourceKind",
   154  					Name:       "name",
   155  					UID:        "4",
   156  				},
   157  			},
   158  			expectError:          false,
   159  			expectedErrorMessage: "",
   160  		},
   161  		{
   162  			description: "simple controller ref failure - two references with Controller set",
   163  			ownerReferences: []metav1.OwnerReference{
   164  				{
   165  					APIVersion: "customresourceVersion",
   166  					Kind:       "customresourceKind1",
   167  					Name:       "name",
   168  					UID:        "1",
   169  					Controller: &falseVar,
   170  				},
   171  				{
   172  					APIVersion: "customresourceVersion",
   173  					Kind:       "customresourceKind2",
   174  					Name:       "name",
   175  					UID:        "2",
   176  					Controller: &trueVar,
   177  				},
   178  				{
   179  					APIVersion: "customresourceVersion",
   180  					Kind:       "customresourceKind3",
   181  					Name:       "name",
   182  					UID:        "3",
   183  					Controller: &trueVar,
   184  				},
   185  				{
   186  					APIVersion: "customresourceVersion",
   187  					Kind:       "customresourceKind4",
   188  					Name:       "name",
   189  					UID:        "4",
   190  				},
   191  			},
   192  			expectError:          true,
   193  			expectedErrorMessage: "Only one reference can have Controller set to true. Found \"true\" in references for customresourceKind2/name and customresourceKind3/name",
   194  		},
   195  	}
   196  
   197  	for _, tc := range testCases {
   198  		errs := ValidateObjectMeta(
   199  			&metav1.ObjectMeta{Name: "test", Namespace: "test", OwnerReferences: tc.ownerReferences},
   200  			true,
   201  			func(s string, prefix bool) []string {
   202  				return nil
   203  			},
   204  			field.NewPath("field"))
   205  		if len(errs) != 0 && !tc.expectError {
   206  			t.Errorf("unexpected error: %v in test case %v", errs, tc.description)
   207  		}
   208  		if len(errs) == 0 && tc.expectError {
   209  			t.Errorf("expect error in test case %v", tc.description)
   210  		}
   211  		if len(errs) != 0 && !strings.Contains(errs[0].Error(), tc.expectedErrorMessage) {
   212  			t.Errorf("unexpected error message: %v in test case %v", errs, tc.description)
   213  		}
   214  	}
   215  }
   216  
   217  func TestValidateObjectMetaUpdateIgnoresCreationTimestamp(t *testing.T) {
   218  	if errs := ValidateObjectMetaUpdate(
   219  		&metav1.ObjectMeta{Name: "test", ResourceVersion: "1"},
   220  		&metav1.ObjectMeta{Name: "test", ResourceVersion: "1", CreationTimestamp: metav1.NewTime(time.Unix(10, 0))},
   221  		field.NewPath("field"),
   222  	); len(errs) != 1 {
   223  		t.Fatalf("unexpected errors: %v", errs)
   224  	}
   225  	if errs := ValidateObjectMetaUpdate(
   226  		&metav1.ObjectMeta{Name: "test", ResourceVersion: "1", CreationTimestamp: metav1.NewTime(time.Unix(10, 0))},
   227  		&metav1.ObjectMeta{Name: "test", ResourceVersion: "1"},
   228  		field.NewPath("field"),
   229  	); len(errs) != 1 {
   230  		t.Fatalf("unexpected errors: %v", errs)
   231  	}
   232  	if errs := ValidateObjectMetaUpdate(
   233  		&metav1.ObjectMeta{Name: "test", ResourceVersion: "1", CreationTimestamp: metav1.NewTime(time.Unix(10, 0))},
   234  		&metav1.ObjectMeta{Name: "test", ResourceVersion: "1", CreationTimestamp: metav1.NewTime(time.Unix(11, 0))},
   235  		field.NewPath("field"),
   236  	); len(errs) != 1 {
   237  		t.Fatalf("unexpected errors: %v", errs)
   238  	}
   239  }
   240  
   241  func TestValidateFinalizersUpdate(t *testing.T) {
   242  	testcases := map[string]struct {
   243  		Old         metav1.ObjectMeta
   244  		New         metav1.ObjectMeta
   245  		ExpectedErr string
   246  	}{
   247  		"invalid adding finalizers": {
   248  			Old:         metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &metav1.Time{}, Finalizers: []string{"x/a"}},
   249  			New:         metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &metav1.Time{}, Finalizers: []string{"x/a", "y/b"}},
   250  			ExpectedErr: "y/b",
   251  		},
   252  		"invalid changing finalizers": {
   253  			Old:         metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &metav1.Time{}, Finalizers: []string{"x/a"}},
   254  			New:         metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &metav1.Time{}, Finalizers: []string{"x/b"}},
   255  			ExpectedErr: "x/b",
   256  		},
   257  		"valid removing finalizers": {
   258  			Old:         metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &metav1.Time{}, Finalizers: []string{"x/a", "y/b"}},
   259  			New:         metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &metav1.Time{}, Finalizers: []string{"x/a"}},
   260  			ExpectedErr: "",
   261  		},
   262  		"valid adding finalizers for objects not being deleted": {
   263  			Old:         metav1.ObjectMeta{Name: "test", ResourceVersion: "1", Finalizers: []string{"x/a"}},
   264  			New:         metav1.ObjectMeta{Name: "test", ResourceVersion: "1", Finalizers: []string{"x/a", "y/b"}},
   265  			ExpectedErr: "",
   266  		},
   267  	}
   268  	for name, tc := range testcases {
   269  		errs := ValidateObjectMetaUpdate(&tc.New, &tc.Old, field.NewPath("field"))
   270  		if len(errs) == 0 {
   271  			if len(tc.ExpectedErr) != 0 {
   272  				t.Errorf("case: %q, expected error to contain %q", name, tc.ExpectedErr)
   273  			}
   274  		} else if e, a := tc.ExpectedErr, errs.ToAggregate().Error(); !strings.Contains(a, e) {
   275  			t.Errorf("case: %q, expected error to contain %q, got error %q", name, e, a)
   276  		}
   277  	}
   278  }
   279  
   280  func TestValidateFinalizersPreventConflictingFinalizers(t *testing.T) {
   281  	testcases := map[string]struct {
   282  		ObjectMeta  metav1.ObjectMeta
   283  		ExpectedErr string
   284  	}{
   285  		"conflicting finalizers": {
   286  			ObjectMeta:  metav1.ObjectMeta{Name: "test", ResourceVersion: "1", Finalizers: []string{metav1.FinalizerOrphanDependents, metav1.FinalizerDeleteDependents}},
   287  			ExpectedErr: "cannot be both set",
   288  		},
   289  	}
   290  	for name, tc := range testcases {
   291  		errs := ValidateObjectMeta(&tc.ObjectMeta, false, NameIsDNSSubdomain, field.NewPath("field"))
   292  		if len(errs) == 0 {
   293  			if len(tc.ExpectedErr) != 0 {
   294  				t.Errorf("case: %q, expected error to contain %q", name, tc.ExpectedErr)
   295  			}
   296  		} else if e, a := tc.ExpectedErr, errs.ToAggregate().Error(); !strings.Contains(a, e) {
   297  			t.Errorf("case: %q, expected error to contain %q, got error %q", name, e, a)
   298  		}
   299  	}
   300  }
   301  
   302  func TestValidateObjectMetaUpdatePreventsDeletionFieldMutation(t *testing.T) {
   303  	now := metav1.NewTime(time.Unix(1000, 0).UTC())
   304  	later := metav1.NewTime(time.Unix(2000, 0).UTC())
   305  	gracePeriodShort := int64(30)
   306  	gracePeriodLong := int64(40)
   307  
   308  	testcases := map[string]struct {
   309  		Old          metav1.ObjectMeta
   310  		New          metav1.ObjectMeta
   311  		ExpectedNew  metav1.ObjectMeta
   312  		ExpectedErrs []string
   313  	}{
   314  		"valid without deletion fields": {
   315  			Old:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1"},
   316  			New:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1"},
   317  			ExpectedNew:  metav1.ObjectMeta{Name: "test", ResourceVersion: "1"},
   318  			ExpectedErrs: []string{},
   319  		},
   320  		"valid with deletion fields": {
   321  			Old:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now, DeletionGracePeriodSeconds: &gracePeriodShort},
   322  			New:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now, DeletionGracePeriodSeconds: &gracePeriodShort},
   323  			ExpectedNew:  metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now, DeletionGracePeriodSeconds: &gracePeriodShort},
   324  			ExpectedErrs: []string{},
   325  		},
   326  
   327  		"invalid set deletionTimestamp": {
   328  			Old:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1"},
   329  			New:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now},
   330  			ExpectedNew:  metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now},
   331  			ExpectedErrs: []string{"field.deletionTimestamp: Invalid value: 1970-01-01 00:16:40 +0000 UTC: field is immutable"},
   332  		},
   333  		"invalid clear deletionTimestamp": {
   334  			Old:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now},
   335  			New:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1"},
   336  			ExpectedNew:  metav1.ObjectMeta{Name: "test", ResourceVersion: "1"},
   337  			ExpectedErrs: []string{"field.deletionTimestamp: Invalid value: \"null\": field is immutable"},
   338  		},
   339  		"invalid change deletionTimestamp": {
   340  			Old:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now},
   341  			New:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &later},
   342  			ExpectedNew:  metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &later},
   343  			ExpectedErrs: []string{"field.deletionTimestamp: Invalid value: 1970-01-01 00:33:20 +0000 UTC: field is immutable"},
   344  		},
   345  
   346  		"invalid set deletionGracePeriodSeconds": {
   347  			Old:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1"},
   348  			New:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort},
   349  			ExpectedNew:  metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort},
   350  			ExpectedErrs: []string{"field.deletionGracePeriodSeconds: Invalid value: 30: field is immutable"},
   351  		},
   352  		"invalid clear deletionGracePeriodSeconds": {
   353  			Old:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort},
   354  			New:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1"},
   355  			ExpectedNew:  metav1.ObjectMeta{Name: "test", ResourceVersion: "1"},
   356  			ExpectedErrs: []string{"field.deletionGracePeriodSeconds: Invalid value: \"null\": field is immutable"},
   357  		},
   358  		"invalid change deletionGracePeriodSeconds": {
   359  			Old:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort},
   360  			New:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodLong},
   361  			ExpectedNew:  metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodLong},
   362  			ExpectedErrs: []string{"field.deletionGracePeriodSeconds: Invalid value: 40: field is immutable"},
   363  		},
   364  	}
   365  
   366  	for k, tc := range testcases {
   367  		errs := ValidateObjectMetaUpdate(&tc.New, &tc.Old, field.NewPath("field"))
   368  		if len(errs) != len(tc.ExpectedErrs) {
   369  			t.Logf("%s: Expected: %#v", k, tc.ExpectedErrs)
   370  			t.Logf("%s: Got: %#v", k, errs)
   371  			t.Errorf("%s: expected %d errors, got %d", k, len(tc.ExpectedErrs), len(errs))
   372  			continue
   373  		}
   374  		for i := range errs {
   375  			if errs[i].Error() != tc.ExpectedErrs[i] {
   376  				t.Errorf("%s: error #%d: expected %q, got %q", k, i, tc.ExpectedErrs[i], errs[i].Error())
   377  			}
   378  		}
   379  		if !reflect.DeepEqual(tc.New, tc.ExpectedNew) {
   380  			t.Errorf("%s: Expected after validation:\n%#v\ngot\n%#v", k, tc.ExpectedNew, tc.New)
   381  		}
   382  	}
   383  }
   384  
   385  func TestObjectMetaGenerationUpdate(t *testing.T) {
   386  	testcases := map[string]struct {
   387  		Old          metav1.ObjectMeta
   388  		New          metav1.ObjectMeta
   389  		ExpectedErrs []string
   390  	}{
   391  		"invalid generation change - decremented": {
   392  			Old:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1", Generation: 5},
   393  			New:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1", Generation: 4},
   394  			ExpectedErrs: []string{"field.generation: Invalid value: 4: must not be decremented"},
   395  		},
   396  		"valid generation change - incremented by one": {
   397  			Old:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1", Generation: 1},
   398  			New:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1", Generation: 2},
   399  			ExpectedErrs: []string{},
   400  		},
   401  		"valid generation field - not updated": {
   402  			Old:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1", Generation: 5},
   403  			New:          metav1.ObjectMeta{Name: "test", ResourceVersion: "1", Generation: 5},
   404  			ExpectedErrs: []string{},
   405  		},
   406  	}
   407  
   408  	for k, tc := range testcases {
   409  		errList := []string{}
   410  		errs := ValidateObjectMetaUpdate(&tc.New, &tc.Old, field.NewPath("field"))
   411  		if len(errs) != len(tc.ExpectedErrs) {
   412  			t.Logf("%s: Expected: %#v", k, tc.ExpectedErrs)
   413  			for _, err := range errs {
   414  				errList = append(errList, err.Error())
   415  			}
   416  			t.Logf("%s: Got: %#v", k, errList)
   417  			t.Errorf("%s: expected %d errors, got %d", k, len(tc.ExpectedErrs), len(errs))
   418  			continue
   419  		}
   420  		for i := range errList {
   421  			if errList[i] != tc.ExpectedErrs[i] {
   422  				t.Errorf("%s: error #%d: expected %q, got %q", k, i, tc.ExpectedErrs[i], errList[i])
   423  			}
   424  		}
   425  	}
   426  }
   427  
   428  // Ensure trailing slash is allowed in generate name
   429  func TestValidateObjectMetaTrimsTrailingSlash(t *testing.T) {
   430  	errs := ValidateObjectMeta(
   431  		&metav1.ObjectMeta{Name: "test", GenerateName: "foo-"},
   432  		false,
   433  		NameIsDNSSubdomain,
   434  		field.NewPath("field"))
   435  	if len(errs) != 0 {
   436  		t.Fatalf("unexpected errors: %v", errs)
   437  	}
   438  }
   439  
   440  func TestValidateAnnotations(t *testing.T) {
   441  	successCases := []map[string]string{
   442  		{"simple": "bar"},
   443  		{"now-with-dashes": "bar"},
   444  		{"1-starts-with-num": "bar"},
   445  		{"1234": "bar"},
   446  		{"simple/simple": "bar"},
   447  		{"now-with-dashes/simple": "bar"},
   448  		{"now-with-dashes/now-with-dashes": "bar"},
   449  		{"now.with.dots/simple": "bar"},
   450  		{"now-with.dashes-and.dots/simple": "bar"},
   451  		{"1-num.2-num/3-num": "bar"},
   452  		{"1234/5678": "bar"},
   453  		{"1.2.3.4/5678": "bar"},
   454  		{"UpperCase123": "bar"},
   455  		{"a": strings.Repeat("b", TotalAnnotationSizeLimitB-1)},
   456  		{
   457  			"a": strings.Repeat("b", TotalAnnotationSizeLimitB/2-1),
   458  			"c": strings.Repeat("d", TotalAnnotationSizeLimitB/2-1),
   459  		},
   460  	}
   461  	for i := range successCases {
   462  		errs := ValidateAnnotations(successCases[i], field.NewPath("field"))
   463  		if len(errs) != 0 {
   464  			t.Errorf("case[%d] expected success, got %#v", i, errs)
   465  		}
   466  	}
   467  
   468  	nameErrorCases := []struct {
   469  		annotations map[string]string
   470  		expect      string
   471  	}{
   472  		{map[string]string{"nospecialchars^=@": "bar"}, namePartErrMsg},
   473  		{map[string]string{"cantendwithadash-": "bar"}, namePartErrMsg},
   474  		{map[string]string{"only/one/slash": "bar"}, nameErrMsg},
   475  		{map[string]string{strings.Repeat("a", 254): "bar"}, maxLengthErrMsg},
   476  	}
   477  	for i := range nameErrorCases {
   478  		errs := ValidateAnnotations(nameErrorCases[i].annotations, field.NewPath("field"))
   479  		if len(errs) != 1 {
   480  			t.Errorf("case[%d]: expected failure", i)
   481  		} else {
   482  			if !strings.Contains(errs[0].Detail, nameErrorCases[i].expect) {
   483  				t.Errorf("case[%d]: error details do not include %q: %q", i, nameErrorCases[i].expect, errs[0].Detail)
   484  			}
   485  		}
   486  	}
   487  	totalSizeErrorCases := []map[string]string{
   488  		{"a": strings.Repeat("b", TotalAnnotationSizeLimitB)},
   489  		{
   490  			"a": strings.Repeat("b", TotalAnnotationSizeLimitB/2),
   491  			"c": strings.Repeat("d", TotalAnnotationSizeLimitB/2),
   492  		},
   493  	}
   494  	for i := range totalSizeErrorCases {
   495  		errs := ValidateAnnotations(totalSizeErrorCases[i], field.NewPath("field"))
   496  		if len(errs) != 1 {
   497  			t.Errorf("case[%d] expected failure", i)
   498  		}
   499  	}
   500  }