k8s.io/apiserver@v0.31.1/pkg/registry/rest/resttest/resttest.go (about)

     1  /*
     2  Copyright 2014 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 resttest
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"fmt"
    23  	"reflect"
    24  	"strings"
    25  	"testing"
    26  	"time"
    27  
    28  	apiequality "k8s.io/apimachinery/pkg/api/equality"
    29  	"k8s.io/apimachinery/pkg/api/errors"
    30  	"k8s.io/apimachinery/pkg/api/meta"
    31  	"k8s.io/apimachinery/pkg/api/validation/path"
    32  	metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
    33  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    34  	"k8s.io/apimachinery/pkg/conversion"
    35  	"k8s.io/apimachinery/pkg/fields"
    36  	"k8s.io/apimachinery/pkg/labels"
    37  	"k8s.io/apimachinery/pkg/runtime"
    38  	"k8s.io/apimachinery/pkg/types"
    39  	"k8s.io/apimachinery/pkg/util/wait"
    40  	genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
    41  	"k8s.io/apiserver/pkg/registry/rest"
    42  )
    43  
    44  // TODO(apelisse): Tests in this file should be more hermertic by always
    45  // removing objects that they create. That would avoid name-collisions.
    46  
    47  type Tester struct {
    48  	*testing.T
    49  	storage             rest.Storage
    50  	clusterScope        bool
    51  	createOnUpdate      bool
    52  	generatesName       bool
    53  	returnDeletedObject bool
    54  	namer               func(int) string
    55  }
    56  
    57  func New(t *testing.T, storage rest.Storage) *Tester {
    58  	return &Tester{
    59  		T:       t,
    60  		storage: storage,
    61  		namer:   defaultNamer,
    62  	}
    63  }
    64  
    65  func defaultNamer(i int) string {
    66  	return fmt.Sprintf("foo%d", i)
    67  }
    68  
    69  // Namer allows providing a custom name maker
    70  // By default "foo%d" is used
    71  func (t *Tester) Namer(namer func(int) string) *Tester {
    72  	t.namer = namer
    73  	return t
    74  }
    75  
    76  func (t *Tester) ClusterScope() *Tester {
    77  	t.clusterScope = true
    78  	return t
    79  }
    80  
    81  func (t *Tester) AllowCreateOnUpdate() *Tester {
    82  	t.createOnUpdate = true
    83  	return t
    84  }
    85  
    86  func (t *Tester) GeneratesName() *Tester {
    87  	t.generatesName = true
    88  	return t
    89  }
    90  
    91  func (t *Tester) ReturnDeletedObject() *Tester {
    92  	t.returnDeletedObject = true
    93  	return t
    94  }
    95  
    96  // TestNamespace returns the namespace that will be used when creating contexts.
    97  // Returns NamespaceNone for cluster-scoped objects.
    98  func (t *Tester) TestNamespace() string {
    99  	if t.clusterScope {
   100  		return metav1.NamespaceNone
   101  	}
   102  	return "test"
   103  }
   104  
   105  // TestContext returns a namespaced context that will be used when making storage calls.
   106  // Namespace is determined by TestNamespace()
   107  func (t *Tester) TestContext() context.Context {
   108  	return genericapirequest.WithNamespace(genericapirequest.NewContext(), t.TestNamespace())
   109  }
   110  
   111  func (t *Tester) getObjectMetaOrFail(obj runtime.Object) metav1.Object {
   112  	objMeta, err := meta.Accessor(obj)
   113  	if err != nil {
   114  		t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, obj)
   115  	}
   116  	return objMeta
   117  }
   118  
   119  func (t *Tester) setObjectMeta(obj runtime.Object, name string) {
   120  	meta := t.getObjectMetaOrFail(obj)
   121  	meta.SetName(name)
   122  	if t.clusterScope {
   123  		meta.SetNamespace(metav1.NamespaceNone)
   124  	} else {
   125  		meta.SetNamespace(genericapirequest.NamespaceValue(t.TestContext()))
   126  	}
   127  	meta.SetGenerateName("")
   128  	meta.SetGeneration(1)
   129  }
   130  
   131  type AssignFunc func([]runtime.Object) []runtime.Object
   132  type EmitFunc func(runtime.Object, string) error
   133  type GetFunc func(context.Context, runtime.Object) (runtime.Object, error)
   134  type InitWatchFunc func()
   135  type InjectErrFunc func(err error)
   136  type IsErrorFunc func(err error) bool
   137  type CreateFunc func(context.Context, runtime.Object) error
   138  type SetRVFunc func(uint64)
   139  type UpdateFunc func(runtime.Object) runtime.Object
   140  
   141  // Test creating an object.
   142  func (t *Tester) TestCreate(valid runtime.Object, createFn CreateFunc, getFn GetFunc, invalid ...runtime.Object) {
   143  	dryRunOpts := metav1.CreateOptions{DryRun: []string{metav1.DryRunAll}}
   144  	opts := metav1.CreateOptions{}
   145  	t.testCreateHasMetadata(valid.DeepCopyObject())
   146  	if !t.generatesName {
   147  		t.testCreateGeneratesName(valid.DeepCopyObject())
   148  	}
   149  	t.testCreateDryRun(valid.DeepCopyObject(), getFn)
   150  	t.testCreateDryRunEquals(valid.DeepCopyObject())
   151  	t.testCreateEquals(valid.DeepCopyObject(), getFn)
   152  	t.testCreateAlreadyExisting(valid.DeepCopyObject(), createFn, dryRunOpts)
   153  	t.testCreateAlreadyExisting(valid.DeepCopyObject(), createFn, opts)
   154  	if t.clusterScope {
   155  		t.testCreateDiscardsObjectNamespace(valid.DeepCopyObject(), dryRunOpts)
   156  		t.testCreateDiscardsObjectNamespace(valid.DeepCopyObject(), opts)
   157  		t.testCreateIgnoresContextNamespace(valid.DeepCopyObject(), dryRunOpts)
   158  		t.testCreateIgnoresContextNamespace(valid.DeepCopyObject(), opts)
   159  		t.testCreateIgnoresMismatchedNamespace(valid.DeepCopyObject(), dryRunOpts)
   160  		t.testCreateIgnoresMismatchedNamespace(valid.DeepCopyObject(), opts)
   161  		t.testCreateResetsUserData(valid.DeepCopyObject(), dryRunOpts)
   162  		t.testCreateResetsUserData(valid.DeepCopyObject(), opts)
   163  	} else {
   164  		t.testCreateRejectsMismatchedNamespace(valid.DeepCopyObject(), dryRunOpts)
   165  		t.testCreateRejectsMismatchedNamespace(valid.DeepCopyObject(), opts)
   166  	}
   167  	t.testCreateInvokesValidation(dryRunOpts, invalid...)
   168  	t.testCreateInvokesValidation(opts, invalid...)
   169  	t.testCreateValidatesNames(valid.DeepCopyObject(), dryRunOpts)
   170  	t.testCreateValidatesNames(valid.DeepCopyObject(), opts)
   171  }
   172  
   173  // Test updating an object.
   174  func (t *Tester) TestUpdate(valid runtime.Object, createFn CreateFunc, getFn GetFunc, updateFn UpdateFunc, invalidUpdateFn ...UpdateFunc) {
   175  	dryRunOpts := metav1.UpdateOptions{DryRun: []string{metav1.DryRunAll}}
   176  	opts := metav1.UpdateOptions{}
   177  	t.testUpdateEquals(valid.DeepCopyObject(), createFn, getFn, updateFn)
   178  	t.testUpdateFailsOnVersionTooOld(valid.DeepCopyObject(), createFn, getFn)
   179  	t.testUpdateOnNotFound(valid.DeepCopyObject(), dryRunOpts)
   180  	t.testUpdateOnNotFound(valid.DeepCopyObject(), opts)
   181  	if !t.clusterScope {
   182  		t.testUpdateRejectsMismatchedNamespace(valid.DeepCopyObject(), createFn, getFn)
   183  	}
   184  	t.testUpdateInvokesValidation(valid.DeepCopyObject(), createFn, invalidUpdateFn...)
   185  	t.testUpdateWithWrongUID(valid.DeepCopyObject(), createFn, getFn, dryRunOpts)
   186  	t.testUpdateWithWrongUID(valid.DeepCopyObject(), createFn, getFn, opts)
   187  	t.testUpdateRetrievesOldObject(valid.DeepCopyObject(), createFn, getFn)
   188  	t.testUpdatePropagatesUpdatedObjectError(valid.DeepCopyObject(), createFn, getFn, dryRunOpts)
   189  	t.testUpdatePropagatesUpdatedObjectError(valid.DeepCopyObject(), createFn, getFn, opts)
   190  	t.testUpdateIgnoreGenerationUpdates(valid.DeepCopyObject(), createFn, getFn)
   191  }
   192  
   193  // Test deleting an object.
   194  func (t *Tester) TestDelete(valid runtime.Object, createFn CreateFunc, getFn GetFunc, isNotFoundFn IsErrorFunc) {
   195  	dryRunOpts := metav1.DeleteOptions{DryRun: []string{metav1.DryRunAll}}
   196  	opts := metav1.DeleteOptions{}
   197  	t.testDeleteNonExist(valid.DeepCopyObject(), dryRunOpts)
   198  	t.testDeleteNonExist(valid.DeepCopyObject(), opts)
   199  	t.testDeleteNoGraceful(valid.DeepCopyObject(), createFn, getFn, isNotFoundFn, true)
   200  	t.testDeleteNoGraceful(valid.DeepCopyObject(), createFn, getFn, isNotFoundFn, false)
   201  	t.testDeleteWithUID(valid.DeepCopyObject(), createFn, getFn, isNotFoundFn, dryRunOpts)
   202  	t.testDeleteWithUID(valid.DeepCopyObject(), createFn, getFn, isNotFoundFn, opts)
   203  	t.testDeleteWithResourceVersion(valid.DeepCopyObject(), createFn, getFn, isNotFoundFn, dryRunOpts)
   204  	t.testDeleteWithResourceVersion(valid.DeepCopyObject(), createFn, getFn, isNotFoundFn, opts)
   205  }
   206  
   207  // Test gracefully deleting an object.
   208  func (t *Tester) TestDeleteGraceful(valid runtime.Object, createFn CreateFunc, getFn GetFunc, expectedGrace int64) {
   209  	t.testDeleteDryRunGracefulHasdefault(valid.DeepCopyObject(), createFn, expectedGrace)
   210  	t.testDeleteGracefulHasDefault(valid.DeepCopyObject(), createFn, getFn, expectedGrace)
   211  	t.testDeleteGracefulWithValue(valid.DeepCopyObject(), createFn, getFn, expectedGrace)
   212  	t.testDeleteGracefulUsesZeroOnNil(valid.DeepCopyObject(), createFn, expectedGrace)
   213  	t.testDeleteGracefulExtend(valid.DeepCopyObject(), createFn, getFn, expectedGrace)
   214  	t.testDeleteGracefulShorten(valid.DeepCopyObject(), createFn, getFn, expectedGrace)
   215  	t.testDeleteGracefulImmediate(valid.DeepCopyObject(), createFn, getFn, expectedGrace)
   216  }
   217  
   218  // Test getting object.
   219  func (t *Tester) TestGet(valid runtime.Object) {
   220  	t.testGetFound(valid.DeepCopyObject())
   221  	t.testGetNotFound(valid.DeepCopyObject())
   222  	t.testGetMimatchedNamespace(valid.DeepCopyObject())
   223  	if !t.clusterScope {
   224  		t.testGetDifferentNamespace(valid.DeepCopyObject())
   225  	}
   226  }
   227  
   228  // Test listing objects.
   229  func (t *Tester) TestList(valid runtime.Object, assignFn AssignFunc) {
   230  	t.testListNotFound(assignFn)
   231  	t.testListFound(valid.DeepCopyObject(), assignFn)
   232  	t.testListMatchLabels(valid.DeepCopyObject(), assignFn)
   233  	t.testListTableConversion(valid.DeepCopyObject(), assignFn)
   234  }
   235  
   236  // Test watching objects.
   237  func (t *Tester) TestWatch(
   238  	valid runtime.Object, emitFn EmitFunc,
   239  	labelsPass, labelsFail []labels.Set, fieldsPass, fieldsFail []fields.Set, actions []string) {
   240  	t.testWatchLabels(valid.DeepCopyObject(), emitFn, labelsPass, labelsFail, actions)
   241  	t.testWatchFields(valid.DeepCopyObject(), emitFn, fieldsPass, fieldsFail, actions)
   242  }
   243  
   244  // =============================================================================
   245  // Creation tests.
   246  
   247  func (t *Tester) delete(ctx context.Context, obj runtime.Object) error {
   248  	objectMeta, err := meta.Accessor(obj)
   249  	if err != nil {
   250  		return err
   251  	}
   252  	deleter, ok := t.storage.(rest.GracefulDeleter)
   253  	if !ok {
   254  		return fmt.Errorf("Expected deleting storage, got %v", t.storage)
   255  	}
   256  	_, _, err = deleter.Delete(ctx, objectMeta.GetName(), rest.ValidateAllObjectFunc, nil)
   257  	return err
   258  }
   259  
   260  func (t *Tester) testCreateAlreadyExisting(obj runtime.Object, createFn CreateFunc, opts metav1.CreateOptions) {
   261  	ctx := t.TestContext()
   262  
   263  	foo := obj.DeepCopyObject()
   264  	t.setObjectMeta(foo, t.namer(1))
   265  	if err := createFn(ctx, foo); err != nil {
   266  		t.Errorf("unexpected error: %v", err)
   267  	}
   268  	defer t.delete(ctx, foo)
   269  
   270  	_, err := t.storage.(rest.Creater).Create(ctx, foo, rest.ValidateAllObjectFunc, &opts)
   271  	if !errors.IsAlreadyExists(err) {
   272  		t.Errorf("expected already exists err, got %v", err)
   273  	}
   274  }
   275  
   276  func (t *Tester) testCreateDryRun(obj runtime.Object, getFn GetFunc) {
   277  	ctx := t.TestContext()
   278  
   279  	foo := obj.DeepCopyObject()
   280  	t.setObjectMeta(foo, t.namer(2))
   281  
   282  	_, err := t.storage.(rest.Creater).Create(ctx, foo, rest.ValidateAllObjectFunc, &metav1.CreateOptions{DryRun: []string{metav1.DryRunAll}})
   283  	if err != nil {
   284  		t.Errorf("unexpected error: %v", err)
   285  	}
   286  
   287  	_, err = getFn(ctx, foo)
   288  	if !errors.IsNotFound(err) {
   289  		t.Errorf("Expected NotFound error, got '%v'", err)
   290  	}
   291  }
   292  
   293  func (t *Tester) testCreateDryRunEquals(obj runtime.Object) {
   294  	ctx := t.TestContext()
   295  
   296  	foo := obj.DeepCopyObject()
   297  	t.setObjectMeta(foo, t.namer(2))
   298  
   299  	createdFake, err := t.storage.(rest.Creater).Create(ctx, foo, rest.ValidateAllObjectFunc, &metav1.CreateOptions{DryRun: []string{metav1.DryRunAll}})
   300  	if err != nil {
   301  		t.Errorf("unexpected error: %v", err)
   302  	}
   303  
   304  	created, err := t.storage.(rest.Creater).Create(ctx, foo, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
   305  	if err != nil {
   306  		t.Errorf("unexpected error: %v", err)
   307  	}
   308  	defer t.delete(ctx, created)
   309  
   310  	// Set resource version which might be unset in created object.
   311  	createdMeta := t.getObjectMetaOrFail(created)
   312  	createdFakeMeta := t.getObjectMetaOrFail(createdFake)
   313  	createdMeta.SetCreationTimestamp(createdFakeMeta.GetCreationTimestamp())
   314  	createdFakeMeta.SetResourceVersion("")
   315  	createdMeta.SetResourceVersion("")
   316  	createdMeta.SetUID(createdFakeMeta.GetUID())
   317  
   318  	if e, a := created, createdFake; !apiequality.Semantic.DeepEqual(e, a) {
   319  		t.Errorf("unexpected obj: %#v, expected %#v", e, a)
   320  	}
   321  }
   322  
   323  func (t *Tester) testCreateEquals(obj runtime.Object, getFn GetFunc) {
   324  	ctx := t.TestContext()
   325  
   326  	foo := obj.DeepCopyObject()
   327  	t.setObjectMeta(foo, t.namer(2))
   328  
   329  	created, err := t.storage.(rest.Creater).Create(ctx, foo, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
   330  	if err != nil {
   331  		t.Errorf("unexpected error: %v", err)
   332  	}
   333  	defer t.delete(ctx, created)
   334  
   335  	got, err := getFn(ctx, foo)
   336  	if err != nil {
   337  		t.Errorf("unexpected error: %v", err)
   338  	}
   339  
   340  	// Set resource version which might be unset in created object.
   341  	createdMeta := t.getObjectMetaOrFail(created)
   342  	gotMeta := t.getObjectMetaOrFail(got)
   343  	createdMeta.SetResourceVersion(gotMeta.GetResourceVersion())
   344  
   345  	if e, a := created, got; !apiequality.Semantic.DeepEqual(e, a) {
   346  		t.Errorf("unexpected obj: %#v, expected %#v", e, a)
   347  	}
   348  }
   349  
   350  func (t *Tester) testCreateDiscardsObjectNamespace(valid runtime.Object, opts metav1.CreateOptions) {
   351  	objectMeta := t.getObjectMetaOrFail(valid)
   352  
   353  	// Ignore non-empty namespace in object meta
   354  	objectMeta.SetNamespace("not-default")
   355  
   356  	// Ideally, we'd get an error back here, but at least verify the namespace wasn't persisted
   357  	created, err := t.storage.(rest.Creater).Create(t.TestContext(), valid.DeepCopyObject(), rest.ValidateAllObjectFunc, &opts)
   358  	if err != nil {
   359  		t.Fatalf("Unexpected error: %v", err)
   360  	}
   361  	defer t.delete(t.TestContext(), created)
   362  	createdObjectMeta := t.getObjectMetaOrFail(created)
   363  	if createdObjectMeta.GetNamespace() != metav1.NamespaceNone {
   364  		t.Errorf("Expected empty namespace on created object, got '%v'", createdObjectMeta.GetNamespace())
   365  	}
   366  }
   367  
   368  func (t *Tester) testCreateGeneratesName(valid runtime.Object) {
   369  	objectMeta := t.getObjectMetaOrFail(valid)
   370  	objectMeta.SetName("")
   371  	objectMeta.SetGenerateName("test-")
   372  
   373  	created, err := t.storage.(rest.Creater).Create(t.TestContext(), valid, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
   374  	if err != nil {
   375  		t.Fatalf("Unexpected error: %v", err)
   376  	}
   377  	defer t.delete(t.TestContext(), created)
   378  	createdMeta := t.getObjectMetaOrFail(created)
   379  	if createdMeta.GetName() == "test-" || !strings.HasPrefix(createdMeta.GetName(), "test-") {
   380  		t.Errorf("unexpected name: %#v", valid)
   381  	}
   382  }
   383  
   384  func (t *Tester) testCreateHasMetadata(valid runtime.Object) {
   385  	objectMeta := t.getObjectMetaOrFail(valid)
   386  	objectMeta.SetName(t.namer(1))
   387  	objectMeta.SetNamespace(t.TestNamespace())
   388  
   389  	obj, err := t.storage.(rest.Creater).Create(t.TestContext(), valid, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
   390  	if err != nil {
   391  		t.Fatalf("Unexpected error: %v", err)
   392  	}
   393  	if obj == nil {
   394  		t.Fatalf("Unexpected object from result: %#v", obj)
   395  	}
   396  	defer t.delete(t.TestContext(), obj)
   397  	createdMeta := t.getObjectMetaOrFail(obj)
   398  	if !metav1.HasObjectMetaSystemFieldValues(createdMeta) {
   399  		t.Errorf("storage did not populate object meta field values")
   400  	}
   401  }
   402  
   403  func (t *Tester) testCreateIgnoresContextNamespace(valid runtime.Object, opts metav1.CreateOptions) {
   404  	// Ignore non-empty namespace in context
   405  	ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), "not-default2")
   406  
   407  	// Ideally, we'd get an error back here, but at least verify the namespace wasn't persisted
   408  	created, err := t.storage.(rest.Creater).Create(ctx, valid.DeepCopyObject(), rest.ValidateAllObjectFunc, &opts)
   409  	if err != nil {
   410  		t.Fatalf("Unexpected error: %v", err)
   411  	}
   412  	defer t.delete(ctx, created)
   413  	createdObjectMeta := t.getObjectMetaOrFail(created)
   414  	if createdObjectMeta.GetNamespace() != metav1.NamespaceNone {
   415  		t.Errorf("Expected empty namespace on created object, got '%v'", createdObjectMeta.GetNamespace())
   416  	}
   417  }
   418  
   419  func (t *Tester) testCreateIgnoresMismatchedNamespace(valid runtime.Object, opts metav1.CreateOptions) {
   420  	objectMeta := t.getObjectMetaOrFail(valid)
   421  
   422  	// Ignore non-empty namespace in object meta
   423  	objectMeta.SetNamespace("not-default")
   424  	ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), "not-default2")
   425  
   426  	// Ideally, we'd get an error back here, but at least verify the namespace wasn't persisted
   427  	created, err := t.storage.(rest.Creater).Create(ctx, valid.DeepCopyObject(), rest.ValidateAllObjectFunc, &opts)
   428  	if err != nil {
   429  		t.Fatalf("Unexpected error: %v", err)
   430  	}
   431  	defer t.delete(ctx, created)
   432  	createdObjectMeta := t.getObjectMetaOrFail(created)
   433  	if createdObjectMeta.GetNamespace() != metav1.NamespaceNone {
   434  		t.Errorf("Expected empty namespace on created object, got '%v'", createdObjectMeta.GetNamespace())
   435  	}
   436  }
   437  
   438  func (t *Tester) testCreateValidatesNames(valid runtime.Object, opts metav1.CreateOptions) {
   439  	for _, invalidName := range path.NameMayNotBe {
   440  		objCopy := valid.DeepCopyObject()
   441  		objCopyMeta := t.getObjectMetaOrFail(objCopy)
   442  		objCopyMeta.SetName(invalidName)
   443  
   444  		ctx := t.TestContext()
   445  		_, err := t.storage.(rest.Creater).Create(ctx, objCopy, rest.ValidateAllObjectFunc, &opts)
   446  		if !errors.IsInvalid(err) {
   447  			t.Errorf("%s: Expected to get an invalid resource error, got '%v'", invalidName, err)
   448  		}
   449  	}
   450  
   451  	for _, invalidSuffix := range path.NameMayNotContain {
   452  		objCopy := valid.DeepCopyObject()
   453  		objCopyMeta := t.getObjectMetaOrFail(objCopy)
   454  		objCopyMeta.SetName(objCopyMeta.GetName() + invalidSuffix)
   455  
   456  		ctx := t.TestContext()
   457  		_, err := t.storage.(rest.Creater).Create(ctx, objCopy, rest.ValidateAllObjectFunc, &opts)
   458  		if !errors.IsInvalid(err) {
   459  			t.Errorf("%s: Expected to get an invalid resource error, got '%v'", invalidSuffix, err)
   460  		}
   461  	}
   462  }
   463  
   464  func (t *Tester) testCreateInvokesValidation(opts metav1.CreateOptions, invalid ...runtime.Object) {
   465  	for i, obj := range invalid {
   466  		ctx := t.TestContext()
   467  		_, err := t.storage.(rest.Creater).Create(ctx, obj, rest.ValidateAllObjectFunc, &opts)
   468  		if !errors.IsInvalid(err) {
   469  			t.Errorf("%d: Expected to get an invalid resource error, got %v", i, err)
   470  		}
   471  	}
   472  }
   473  
   474  func (t *Tester) testCreateRejectsMismatchedNamespace(valid runtime.Object, opts metav1.CreateOptions) {
   475  	objectMeta := t.getObjectMetaOrFail(valid)
   476  	objectMeta.SetNamespace("not-default")
   477  
   478  	_, err := t.storage.(rest.Creater).Create(t.TestContext(), valid, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
   479  	if err == nil {
   480  		t.Errorf("Expected an error, but we didn't get one")
   481  	} else if !strings.Contains(err.Error(), "does not match the namespace sent on the request") {
   482  		t.Errorf("Expected 'does not match the namespace sent on the request' error, got '%v'", err.Error())
   483  	}
   484  }
   485  
   486  func (t *Tester) testCreateResetsUserData(valid runtime.Object, opts metav1.CreateOptions) {
   487  	objectMeta := t.getObjectMetaOrFail(valid)
   488  	now := metav1.Now()
   489  	objectMeta.SetUID("bad-uid")
   490  	objectMeta.SetCreationTimestamp(now)
   491  
   492  	obj, err := t.storage.(rest.Creater).Create(t.TestContext(), valid, rest.ValidateAllObjectFunc, &opts)
   493  	if err != nil {
   494  		t.Fatalf("Unexpected error: %v", err)
   495  	}
   496  	if obj == nil {
   497  		t.Fatalf("Unexpected object from result: %#v", obj)
   498  	}
   499  	defer t.delete(t.TestContext(), obj)
   500  	createdMeta := t.getObjectMetaOrFail(obj)
   501  	if createdMeta.GetUID() == "bad-uid" || createdMeta.GetCreationTimestamp() == now {
   502  		t.Errorf("ObjectMeta did not reset basic fields: %#v", objectMeta)
   503  	}
   504  }
   505  
   506  // =============================================================================
   507  // Update tests.
   508  
   509  func (t *Tester) testUpdateEquals(obj runtime.Object, createFn CreateFunc, getFn GetFunc, updateFn UpdateFunc) {
   510  	ctx := t.TestContext()
   511  
   512  	foo := obj.DeepCopyObject()
   513  	t.setObjectMeta(foo, t.namer(2))
   514  	if err := createFn(ctx, foo); err != nil {
   515  		t.Errorf("unexpected error: %v", err)
   516  	}
   517  
   518  	toUpdate, err := getFn(ctx, foo)
   519  	if err != nil {
   520  		t.Errorf("unexpected error: %v", err)
   521  	}
   522  	toUpdate = updateFn(toUpdate)
   523  	toUpdateMeta := t.getObjectMetaOrFail(toUpdate)
   524  	updated, created, err := t.storage.(rest.Updater).Update(ctx, toUpdateMeta.GetName(), rest.DefaultUpdatedObjectInfo(toUpdate), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{})
   525  	if err != nil {
   526  		t.Errorf("unexpected error: %v", err)
   527  	}
   528  	if created {
   529  		t.Errorf("unexpected creation")
   530  	}
   531  	got, err := getFn(ctx, foo)
   532  	if err != nil {
   533  		t.Errorf("unexpected error: %v", err)
   534  	}
   535  	// Set resource version which might be unset in created object.
   536  	updatedMeta := t.getObjectMetaOrFail(updated)
   537  	gotMeta := t.getObjectMetaOrFail(got)
   538  	updatedMeta.SetResourceVersion(gotMeta.GetResourceVersion())
   539  
   540  	if e, a := updated, got; !apiequality.Semantic.DeepEqual(e, a) {
   541  		t.Errorf("unexpected obj: %#v, expected %#v", e, a)
   542  	}
   543  }
   544  
   545  func (t *Tester) testUpdateFailsOnVersionTooOld(obj runtime.Object, createFn CreateFunc, getFn GetFunc) {
   546  	ctx := t.TestContext()
   547  
   548  	foo := obj.DeepCopyObject()
   549  	t.setObjectMeta(foo, t.namer(3))
   550  
   551  	if err := createFn(ctx, foo); err != nil {
   552  		t.Errorf("unexpected error: %v", err)
   553  	}
   554  
   555  	storedFoo, err := getFn(ctx, foo)
   556  	if err != nil {
   557  		t.Errorf("unexpected error: %v", err)
   558  	}
   559  
   560  	older := storedFoo.DeepCopyObject()
   561  	olderMeta := t.getObjectMetaOrFail(older)
   562  	olderMeta.SetResourceVersion("1")
   563  
   564  	_, _, err = t.storage.(rest.Updater).Update(t.TestContext(), olderMeta.GetName(), rest.DefaultUpdatedObjectInfo(older), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{})
   565  	if err == nil {
   566  		t.Errorf("Expected an error, but we didn't get one")
   567  	} else if !errors.IsConflict(err) {
   568  		t.Errorf("Expected Conflict error, got '%v'", err)
   569  	}
   570  }
   571  
   572  func (t *Tester) testUpdateInvokesValidation(obj runtime.Object, createFn CreateFunc, invalidUpdateFn ...UpdateFunc) {
   573  	ctx := t.TestContext()
   574  
   575  	foo := obj.DeepCopyObject()
   576  	t.setObjectMeta(foo, t.namer(4))
   577  	if err := createFn(ctx, foo); err != nil {
   578  		t.Errorf("unexpected error: %v", err)
   579  	}
   580  
   581  	for _, update := range invalidUpdateFn {
   582  		toUpdate := update(foo.DeepCopyObject())
   583  		toUpdateMeta := t.getObjectMetaOrFail(toUpdate)
   584  		got, created, err := t.storage.(rest.Updater).Update(t.TestContext(), toUpdateMeta.GetName(), rest.DefaultUpdatedObjectInfo(toUpdate), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{})
   585  		if got != nil || created {
   586  			t.Errorf("expected nil object and no creation for object: %v", toUpdate)
   587  		}
   588  		if !errors.IsInvalid(err) && !errors.IsBadRequest(err) {
   589  			t.Errorf("expected invalid or bad request error, got %v", err)
   590  		}
   591  	}
   592  }
   593  
   594  func (t *Tester) testUpdateWithWrongUID(obj runtime.Object, createFn CreateFunc, getFn GetFunc, opts metav1.UpdateOptions) {
   595  	ctx := t.TestContext()
   596  	foo := obj.DeepCopyObject()
   597  	t.setObjectMeta(foo, t.namer(5))
   598  	objectMeta := t.getObjectMetaOrFail(foo)
   599  	objectMeta.SetUID(types.UID("UID0000"))
   600  	if err := createFn(ctx, foo); err != nil {
   601  		t.Errorf("unexpected error: %v", err)
   602  	}
   603  	defer t.delete(ctx, foo)
   604  	objectMeta.SetUID(types.UID("UID1111"))
   605  
   606  	obj, created, err := t.storage.(rest.Updater).Update(ctx, objectMeta.GetName(), rest.DefaultUpdatedObjectInfo(foo), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &opts)
   607  	if created || obj != nil {
   608  		t.Errorf("expected nil object and no creation for object: %v", foo)
   609  	}
   610  	if err == nil || !errors.IsConflict(err) {
   611  		t.Errorf("unexpected error: %v", err)
   612  	}
   613  }
   614  
   615  func (t *Tester) testUpdateRetrievesOldObject(obj runtime.Object, createFn CreateFunc, getFn GetFunc) {
   616  	ctx := t.TestContext()
   617  	foo := obj.DeepCopyObject()
   618  	t.setObjectMeta(foo, t.namer(6))
   619  	objectMeta := t.getObjectMetaOrFail(foo)
   620  	objectMeta.SetAnnotations(map[string]string{"A": "1"})
   621  	if err := createFn(ctx, foo); err != nil {
   622  		t.Errorf("unexpected error: %v", err)
   623  		return
   624  	}
   625  
   626  	storedFoo, err := getFn(ctx, foo)
   627  	if err != nil {
   628  		t.Errorf("unexpected error: %v", err)
   629  		return
   630  	}
   631  
   632  	storedFooWithUpdates := storedFoo.DeepCopyObject()
   633  	objectMeta = t.getObjectMetaOrFail(storedFooWithUpdates)
   634  	objectMeta.SetAnnotations(map[string]string{"A": "2"})
   635  
   636  	// Make sure a custom transform is called, and sees the expected updatedObject and oldObject
   637  	// This tests the mechanism used to pass the old and new object to admission
   638  	calledUpdatedObject := 0
   639  	noopTransform := func(_ context.Context, updatedObject runtime.Object, oldObject runtime.Object) (runtime.Object, error) {
   640  		if !reflect.DeepEqual(storedFoo, oldObject) {
   641  			t.Errorf("Expected\n\t%#v\ngot\n\t%#v", storedFoo, oldObject)
   642  		}
   643  		if !reflect.DeepEqual(storedFooWithUpdates, updatedObject) {
   644  			t.Errorf("Expected\n\t%#v\ngot\n\t%#v", storedFooWithUpdates, updatedObject)
   645  		}
   646  		calledUpdatedObject++
   647  		return updatedObject, nil
   648  	}
   649  
   650  	updatedObj, created, err := t.storage.(rest.Updater).Update(ctx, objectMeta.GetName(), rest.DefaultUpdatedObjectInfo(storedFooWithUpdates, noopTransform), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{})
   651  	if err != nil {
   652  		t.Errorf("unexpected error: %v", err)
   653  		return
   654  	}
   655  	if created {
   656  		t.Errorf("expected no creation for object")
   657  		return
   658  	}
   659  	if updatedObj == nil {
   660  		t.Errorf("expected non-nil object from update")
   661  		return
   662  	}
   663  	if calledUpdatedObject != 1 {
   664  		t.Errorf("expected UpdatedObject() to be called 1 time, was called %d", calledUpdatedObject)
   665  		return
   666  	}
   667  }
   668  
   669  func (t *Tester) testUpdatePropagatesUpdatedObjectError(obj runtime.Object, createFn CreateFunc, getFn GetFunc, opts metav1.UpdateOptions) {
   670  	ctx := t.TestContext()
   671  	foo := obj.DeepCopyObject()
   672  	name := t.namer(7)
   673  	t.setObjectMeta(foo, name)
   674  	if err := createFn(ctx, foo); err != nil {
   675  		t.Errorf("unexpected error: %v", err)
   676  		return
   677  	}
   678  	defer t.delete(ctx, foo)
   679  
   680  	// Make sure our transform is called, and sees the expected updatedObject and oldObject
   681  	propagateErr := fmt.Errorf("custom updated object error for %v", foo)
   682  	noopTransform := func(_ context.Context, updatedObject runtime.Object, oldObject runtime.Object) (runtime.Object, error) {
   683  		return nil, propagateErr
   684  	}
   685  
   686  	_, _, err := t.storage.(rest.Updater).Update(ctx, name, rest.DefaultUpdatedObjectInfo(foo, noopTransform), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &opts)
   687  	if err != propagateErr {
   688  		t.Errorf("expected propagated error, got %#v", err)
   689  	}
   690  }
   691  
   692  func (t *Tester) testUpdateIgnoreGenerationUpdates(obj runtime.Object, createFn CreateFunc, getFn GetFunc) {
   693  	ctx := t.TestContext()
   694  
   695  	foo := obj.DeepCopyObject()
   696  	name := t.namer(8)
   697  	t.setObjectMeta(foo, name)
   698  
   699  	if err := createFn(ctx, foo); err != nil {
   700  		t.Errorf("unexpected error: %v", err)
   701  	}
   702  
   703  	storedFoo, err := getFn(ctx, foo)
   704  	if err != nil {
   705  		t.Errorf("unexpected error: %v", err)
   706  	}
   707  
   708  	older := storedFoo.DeepCopyObject()
   709  	olderMeta := t.getObjectMetaOrFail(older)
   710  	olderMeta.SetGeneration(2)
   711  
   712  	_, _, err = t.storage.(rest.Updater).Update(t.TestContext(), olderMeta.GetName(), rest.DefaultUpdatedObjectInfo(older), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{})
   713  	if err != nil {
   714  		t.Errorf("Unexpected error: %v", err)
   715  	}
   716  
   717  	updatedFoo, err := getFn(ctx, older)
   718  	if err != nil {
   719  		t.Errorf("unexpected error: %v", err)
   720  	}
   721  	if exp, got := int64(1), t.getObjectMetaOrFail(updatedFoo).GetGeneration(); exp != got {
   722  		t.Errorf("Unexpected generation update: expected %d, got %d", exp, got)
   723  	}
   724  }
   725  
   726  func (t *Tester) testUpdateOnNotFound(obj runtime.Object, opts metav1.UpdateOptions) {
   727  	t.setObjectMeta(obj, t.namer(0))
   728  	_, created, err := t.storage.(rest.Updater).Update(t.TestContext(), t.namer(0), rest.DefaultUpdatedObjectInfo(obj), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &opts)
   729  	if t.createOnUpdate {
   730  		if err != nil {
   731  			t.Errorf("creation allowed on updated, but got an error: %v", err)
   732  		}
   733  		if !created {
   734  			t.Errorf("creation allowed on update, but object not created")
   735  		}
   736  	} else {
   737  		if err == nil {
   738  			t.Errorf("Expected an error, but we didn't get one")
   739  		} else if !errors.IsNotFound(err) {
   740  			t.Errorf("Expected NotFound error, got '%v'", err)
   741  		}
   742  	}
   743  }
   744  
   745  func (t *Tester) testUpdateRejectsMismatchedNamespace(obj runtime.Object, createFn CreateFunc, getFn GetFunc) {
   746  	ctx := t.TestContext()
   747  
   748  	foo := obj.DeepCopyObject()
   749  	t.setObjectMeta(foo, t.namer(1))
   750  	if err := createFn(ctx, foo); err != nil {
   751  		t.Errorf("unexpected error: %v", err)
   752  	}
   753  
   754  	storedFoo, err := getFn(ctx, foo)
   755  	if err != nil {
   756  		t.Errorf("unexpected error: %v", err)
   757  	}
   758  
   759  	objectMeta := t.getObjectMetaOrFail(storedFoo)
   760  	objectMeta.SetName(t.namer(1))
   761  	objectMeta.SetNamespace("not-default")
   762  
   763  	obj, updated, err := t.storage.(rest.Updater).Update(t.TestContext(), "foo1", rest.DefaultUpdatedObjectInfo(storedFoo), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{})
   764  	if obj != nil || updated {
   765  		t.Errorf("expected nil object and not updated")
   766  	}
   767  	if err == nil {
   768  		t.Errorf("expected an error, but didn't get one")
   769  	} else if !strings.Contains(err.Error(), "does not match the namespace sent on the request") {
   770  		t.Errorf("expected 'does not match the namespace sent on the request' error, got '%v'", err.Error())
   771  	}
   772  }
   773  
   774  // =============================================================================
   775  // Deletion tests.
   776  
   777  func (t *Tester) testDeleteNoGraceful(obj runtime.Object, createFn CreateFunc, getFn GetFunc, isNotFoundFn IsErrorFunc, dryRun bool) {
   778  	ctx := t.TestContext()
   779  
   780  	foo := obj.DeepCopyObject()
   781  	t.setObjectMeta(foo, t.namer(1))
   782  	if err := createFn(ctx, foo); err != nil {
   783  		t.Errorf("unexpected error: %v", err)
   784  	}
   785  	defer t.delete(ctx, foo)
   786  	objectMeta := t.getObjectMetaOrFail(foo)
   787  	opts := metav1.NewDeleteOptions(10)
   788  	if dryRun {
   789  		opts.DryRun = []string{metav1.DryRunAll}
   790  	}
   791  	obj, wasDeleted, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), rest.ValidateAllObjectFunc, opts)
   792  	if err != nil {
   793  		t.Errorf("unexpected error: %v", err)
   794  	}
   795  	if !wasDeleted {
   796  		t.Errorf("unexpected, object %s should have been deleted immediately", objectMeta.GetName())
   797  	}
   798  	if !t.returnDeletedObject {
   799  		if status, ok := obj.(*metav1.Status); !ok {
   800  			t.Errorf("expected status of delete, got %v", status)
   801  		} else if status.Status != metav1.StatusSuccess {
   802  			t.Errorf("expected success, got: %v", status.Status)
   803  		}
   804  	}
   805  
   806  	_, err = getFn(ctx, foo)
   807  	if !dryRun && (err == nil || !isNotFoundFn(err)) {
   808  		t.Errorf("unexpected error: %v", err)
   809  	} else if dryRun && isNotFoundFn(err) {
   810  		t.Error("object should not have been removed in dry-run")
   811  	}
   812  }
   813  
   814  func (t *Tester) testDeleteNonExist(obj runtime.Object, opts metav1.DeleteOptions) {
   815  	objectMeta := t.getObjectMetaOrFail(obj)
   816  
   817  	_, _, err := t.storage.(rest.GracefulDeleter).Delete(t.TestContext(), objectMeta.GetName(), rest.ValidateAllObjectFunc, &opts)
   818  	if err == nil || !errors.IsNotFound(err) {
   819  		t.Errorf("unexpected error: %v", err)
   820  	}
   821  
   822  }
   823  
   824  // This test the fast-fail path. We test that the precondition gets verified
   825  // again before deleting the object in tests of pkg/storage/etcd.
   826  func (t *Tester) testDeleteWithUID(obj runtime.Object, createFn CreateFunc, getFn GetFunc, isNotFoundFn IsErrorFunc, opts metav1.DeleteOptions) {
   827  	ctx := t.TestContext()
   828  
   829  	foo := obj.DeepCopyObject()
   830  	t.setObjectMeta(foo, t.namer(1))
   831  	objectMeta := t.getObjectMetaOrFail(foo)
   832  	objectMeta.SetUID(types.UID("UID0000"))
   833  	if err := createFn(ctx, foo); err != nil {
   834  		t.Errorf("unexpected error: %v", err)
   835  	}
   836  	opts.Preconditions = metav1.NewPreconditionDeleteOptions("UID1111").Preconditions
   837  	_, _, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), rest.ValidateAllObjectFunc, &opts)
   838  	if err == nil || !errors.IsConflict(err) {
   839  		t.Errorf("unexpected error: %v", err)
   840  	}
   841  
   842  	obj, _, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), rest.ValidateAllObjectFunc, metav1.NewPreconditionDeleteOptions("UID0000"))
   843  	if err != nil {
   844  		t.Errorf("unexpected error: %v", err)
   845  	}
   846  
   847  	if !t.returnDeletedObject {
   848  		if status, ok := obj.(*metav1.Status); !ok {
   849  			t.Errorf("expected status of delete, got %v", status)
   850  		} else if status.Status != metav1.StatusSuccess {
   851  			t.Errorf("expected success, got: %v", status.Status)
   852  		}
   853  	}
   854  
   855  	_, err = getFn(ctx, foo)
   856  	if err == nil || !isNotFoundFn(err) {
   857  		t.Errorf("unexpected error: %v", err)
   858  	}
   859  }
   860  
   861  // This test the fast-fail path. We test that the precondition gets verified
   862  // again before deleting the object in tests of pkg/storage/etcd.
   863  func (t *Tester) testDeleteWithResourceVersion(obj runtime.Object, createFn CreateFunc, getFn GetFunc, isNotFoundFn IsErrorFunc, opts metav1.DeleteOptions) {
   864  	ctx := t.TestContext()
   865  
   866  	foo := obj.DeepCopyObject()
   867  	t.setObjectMeta(foo, t.namer(1))
   868  	if err := createFn(ctx, foo); err != nil {
   869  		t.Errorf("unexpected error: %v", err)
   870  	}
   871  	newObj, err := getFn(ctx, foo)
   872  	if err != nil {
   873  		t.Errorf("unexpected error: %v", err)
   874  	}
   875  	objectMeta := t.getObjectMetaOrFail(newObj)
   876  
   877  	opts.Preconditions = metav1.NewRVDeletionPrecondition("wrongVersion").Preconditions
   878  	_, wasDeleted, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), rest.ValidateAllObjectFunc, &opts)
   879  	if err == nil || !errors.IsConflict(err) {
   880  		t.Errorf("unexpected error: %v", err)
   881  	}
   882  	if wasDeleted {
   883  		t.Errorf("unexpected, object %s should not have been deleted immediately", objectMeta.GetName())
   884  	}
   885  	obj, _, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), rest.ValidateAllObjectFunc, metav1.NewRVDeletionPrecondition(objectMeta.GetResourceVersion()))
   886  	if err != nil {
   887  		t.Errorf("unexpected error: %v", err)
   888  	}
   889  
   890  	if !t.returnDeletedObject {
   891  		if status, ok := obj.(*metav1.Status); !ok {
   892  			t.Errorf("expected status of delete, got %v", status)
   893  		} else if status.Status != metav1.StatusSuccess {
   894  			t.Errorf("expected success, got: %v", status.Status)
   895  		}
   896  	}
   897  
   898  	_, err = getFn(ctx, foo)
   899  	if err == nil || !isNotFoundFn(err) {
   900  		t.Errorf("unexpected error: %v", err)
   901  	}
   902  }
   903  
   904  // =============================================================================
   905  // Graceful Deletion tests.
   906  
   907  func (t *Tester) testDeleteDryRunGracefulHasdefault(obj runtime.Object, createFn CreateFunc, expectedGrace int64) {
   908  	ctx := t.TestContext()
   909  
   910  	foo := obj.DeepCopyObject()
   911  	t.setObjectMeta(foo, t.namer(1))
   912  	defer t.delete(ctx, foo)
   913  	if err := createFn(ctx, foo); err != nil {
   914  		t.Errorf("unexpected error: %v", err)
   915  	}
   916  	objectMeta := t.getObjectMetaOrFail(foo)
   917  	object, wasDeleted, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), rest.ValidateAllObjectFunc, &metav1.DeleteOptions{DryRun: []string{metav1.DryRunAll}})
   918  	if err != nil {
   919  		t.Errorf("unexpected error: %v", err)
   920  	}
   921  	if wasDeleted {
   922  		t.Errorf("unexpected, object %s should not have been deleted immediately", objectMeta.GetName())
   923  	}
   924  	objectMeta = t.getObjectMetaOrFail(object)
   925  	if objectMeta.GetDeletionTimestamp() == nil || objectMeta.GetDeletionGracePeriodSeconds() == nil || *objectMeta.GetDeletionGracePeriodSeconds() != expectedGrace {
   926  		t.Errorf("unexpected deleted meta: %#v", objectMeta)
   927  	}
   928  	_, _, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), rest.ValidateAllObjectFunc, &metav1.DeleteOptions{})
   929  	if err != nil {
   930  		t.Errorf("unexpected error: %v", err)
   931  	}
   932  }
   933  
   934  func (t *Tester) testDeleteGracefulHasDefault(obj runtime.Object, createFn CreateFunc, getFn GetFunc, expectedGrace int64) {
   935  	ctx := t.TestContext()
   936  
   937  	foo := obj.DeepCopyObject()
   938  	t.setObjectMeta(foo, t.namer(1))
   939  	if err := createFn(ctx, foo); err != nil {
   940  		t.Errorf("unexpected error: %v", err)
   941  	}
   942  	objectMeta := t.getObjectMetaOrFail(foo)
   943  	generation := objectMeta.GetGeneration()
   944  	_, wasDeleted, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), rest.ValidateAllObjectFunc, &metav1.DeleteOptions{})
   945  	if err != nil {
   946  		t.Errorf("unexpected error: %v", err)
   947  	}
   948  	if wasDeleted {
   949  		t.Errorf("unexpected, object %s should not have been deleted immediately", objectMeta.GetName())
   950  	}
   951  	if _, err := getFn(ctx, foo); err != nil {
   952  		t.Fatalf("did not gracefully delete resource: %v", err)
   953  	}
   954  
   955  	object, err := t.storage.(rest.Getter).Get(ctx, objectMeta.GetName(), &metav1.GetOptions{})
   956  	if err != nil {
   957  		t.Fatalf("unexpected error, object should exist: %v", err)
   958  	}
   959  	objectMeta = t.getObjectMetaOrFail(object)
   960  	if objectMeta.GetDeletionTimestamp() == nil || objectMeta.GetDeletionGracePeriodSeconds() == nil || *objectMeta.GetDeletionGracePeriodSeconds() != expectedGrace {
   961  		t.Errorf("unexpected deleted meta: %#v", objectMeta)
   962  	}
   963  	if generation >= objectMeta.GetGeneration() {
   964  		t.Error("Generation wasn't bumped when deletion timestamp was set")
   965  	}
   966  }
   967  
   968  func (t *Tester) testDeleteGracefulWithValue(obj runtime.Object, createFn CreateFunc, getFn GetFunc, expectedGrace int64) {
   969  	ctx := t.TestContext()
   970  
   971  	foo := obj.DeepCopyObject()
   972  	t.setObjectMeta(foo, t.namer(2))
   973  	if err := createFn(ctx, foo); err != nil {
   974  		t.Errorf("unexpected error: %v", err)
   975  	}
   976  	objectMeta := t.getObjectMetaOrFail(foo)
   977  	generation := objectMeta.GetGeneration()
   978  	_, wasDeleted, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), rest.ValidateAllObjectFunc, metav1.NewDeleteOptions(expectedGrace+2))
   979  	if err != nil {
   980  		t.Errorf("unexpected error: %v", err)
   981  	}
   982  	if wasDeleted {
   983  		t.Errorf("unexpected, object %s should not have been deleted immediately", objectMeta.GetName())
   984  	}
   985  	if _, err := getFn(ctx, foo); err != nil {
   986  		t.Fatalf("did not gracefully delete resource: %v", err)
   987  	}
   988  
   989  	object, err := t.storage.(rest.Getter).Get(ctx, objectMeta.GetName(), &metav1.GetOptions{})
   990  	if err != nil {
   991  		t.Errorf("unexpected error, object should exist: %v", err)
   992  	}
   993  	objectMeta = t.getObjectMetaOrFail(object)
   994  	if objectMeta.GetDeletionTimestamp() == nil || objectMeta.GetDeletionGracePeriodSeconds() == nil || *objectMeta.GetDeletionGracePeriodSeconds() != expectedGrace+2 {
   995  		t.Errorf("unexpected deleted meta: %#v", objectMeta)
   996  	}
   997  	if generation >= objectMeta.GetGeneration() {
   998  		t.Error("Generation wasn't bumped when deletion timestamp was set")
   999  	}
  1000  }
  1001  
  1002  func (t *Tester) testDeleteGracefulExtend(obj runtime.Object, createFn CreateFunc, getFn GetFunc, expectedGrace int64) {
  1003  	ctx := t.TestContext()
  1004  
  1005  	foo := obj.DeepCopyObject()
  1006  	t.setObjectMeta(foo, t.namer(3))
  1007  	if err := createFn(ctx, foo); err != nil {
  1008  		t.Errorf("unexpected error: %v", err)
  1009  	}
  1010  	objectMeta := t.getObjectMetaOrFail(foo)
  1011  	generation := objectMeta.GetGeneration()
  1012  	_, wasDeleted, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), rest.ValidateAllObjectFunc, metav1.NewDeleteOptions(expectedGrace))
  1013  	if err != nil {
  1014  		t.Errorf("unexpected error: %v", err)
  1015  	}
  1016  	if wasDeleted {
  1017  		t.Errorf("unexpected, object %s should not have been deleted immediately", objectMeta.GetName())
  1018  	}
  1019  	if _, err := getFn(ctx, foo); err != nil {
  1020  		t.Fatalf("did not gracefully delete resource: %v", err)
  1021  	}
  1022  
  1023  	// second delete duration is ignored
  1024  	_, wasDeleted, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), rest.ValidateAllObjectFunc, metav1.NewDeleteOptions(expectedGrace+2))
  1025  	if err != nil {
  1026  		t.Errorf("unexpected error: %v", err)
  1027  	}
  1028  	if wasDeleted {
  1029  		t.Errorf("unexpected, object %s should not have been deleted immediately", objectMeta.GetName())
  1030  	}
  1031  	object, err := t.storage.(rest.Getter).Get(ctx, objectMeta.GetName(), &metav1.GetOptions{})
  1032  	if err != nil {
  1033  		t.Errorf("unexpected error, object should exist: %v", err)
  1034  	}
  1035  	objectMeta = t.getObjectMetaOrFail(object)
  1036  	if objectMeta.GetDeletionTimestamp() == nil || objectMeta.GetDeletionGracePeriodSeconds() == nil || *objectMeta.GetDeletionGracePeriodSeconds() != expectedGrace {
  1037  		t.Errorf("unexpected deleted meta: %#v", objectMeta)
  1038  	}
  1039  	if generation >= objectMeta.GetGeneration() {
  1040  		t.Error("Generation wasn't bumped when deletion timestamp was set")
  1041  	}
  1042  }
  1043  
  1044  func (t *Tester) testDeleteGracefulImmediate(obj runtime.Object, createFn CreateFunc, getFn GetFunc, expectedGrace int64) {
  1045  	ctx := t.TestContext()
  1046  
  1047  	foo := obj.DeepCopyObject()
  1048  	t.setObjectMeta(foo, "foo4")
  1049  	if err := createFn(ctx, foo); err != nil {
  1050  		t.Errorf("unexpected error: %v", err)
  1051  	}
  1052  	objectMeta := t.getObjectMetaOrFail(foo)
  1053  	generation := objectMeta.GetGeneration()
  1054  	_, wasDeleted, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), rest.ValidateAllObjectFunc, metav1.NewDeleteOptions(expectedGrace))
  1055  	if err != nil {
  1056  		t.Errorf("unexpected error: %v", err)
  1057  	}
  1058  	if wasDeleted {
  1059  		t.Errorf("unexpected, object %s should not have been deleted immediately", objectMeta.GetName())
  1060  	}
  1061  	if _, err := getFn(ctx, foo); err != nil {
  1062  		t.Fatalf("did not gracefully delete resource: %v", err)
  1063  	}
  1064  
  1065  	// second delete is immediate, resource is deleted
  1066  	out, wasDeleted, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), rest.ValidateAllObjectFunc, metav1.NewDeleteOptions(0))
  1067  	if err != nil {
  1068  		t.Errorf("unexpected error: %v", err)
  1069  	}
  1070  	if !wasDeleted {
  1071  		t.Errorf("unexpected, object %s should have been deleted immediately", objectMeta.GetName())
  1072  	}
  1073  	_, err = t.storage.(rest.Getter).Get(ctx, objectMeta.GetName(), &metav1.GetOptions{})
  1074  	if !errors.IsNotFound(err) {
  1075  		t.Errorf("unexpected error, object should be deleted immediately: %v", err)
  1076  	}
  1077  	objectMeta = t.getObjectMetaOrFail(out)
  1078  	// the second delete shouldn't update the object, so the objectMeta.GetDeletionGracePeriodSeconds() should eqaul to the value set in the first delete.
  1079  	if objectMeta.GetDeletionTimestamp() == nil || objectMeta.GetDeletionGracePeriodSeconds() == nil || *objectMeta.GetDeletionGracePeriodSeconds() != 0 {
  1080  		t.Errorf("unexpected deleted meta: %#v", objectMeta)
  1081  	}
  1082  	if generation >= objectMeta.GetGeneration() {
  1083  		t.Error("Generation wasn't bumped when deletion timestamp was set")
  1084  	}
  1085  }
  1086  
  1087  func (t *Tester) testDeleteGracefulUsesZeroOnNil(obj runtime.Object, createFn CreateFunc, expectedGrace int64) {
  1088  	ctx := t.TestContext()
  1089  
  1090  	foo := obj.DeepCopyObject()
  1091  	t.setObjectMeta(foo, t.namer(5))
  1092  	if err := createFn(ctx, foo); err != nil {
  1093  		t.Errorf("unexpected error: %v", err)
  1094  	}
  1095  	objectMeta := t.getObjectMetaOrFail(foo)
  1096  	_, wasDeleted, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), rest.ValidateAllObjectFunc, nil)
  1097  	if err != nil {
  1098  		t.Errorf("unexpected error: %v", err)
  1099  	}
  1100  	if !wasDeleted {
  1101  		t.Errorf("unexpected, object %s should have been deleted immediately", objectMeta.GetName())
  1102  	}
  1103  	if _, err := t.storage.(rest.Getter).Get(ctx, objectMeta.GetName(), &metav1.GetOptions{}); !errors.IsNotFound(err) {
  1104  		t.Errorf("unexpected error, object should not exist: %v", err)
  1105  	}
  1106  }
  1107  
  1108  // Regression test for bug discussed in #27539
  1109  func (t *Tester) testDeleteGracefulShorten(obj runtime.Object, createFn CreateFunc, getFn GetFunc, expectedGrace int64) {
  1110  	ctx := t.TestContext()
  1111  
  1112  	foo := obj.DeepCopyObject()
  1113  	t.setObjectMeta(foo, t.namer(6))
  1114  	if err := createFn(ctx, foo); err != nil {
  1115  		t.Errorf("unexpected error: %v", err)
  1116  	}
  1117  	bigGrace := int64(time.Hour)
  1118  	if expectedGrace > bigGrace {
  1119  		bigGrace = 2 * expectedGrace
  1120  	}
  1121  	objectMeta := t.getObjectMetaOrFail(foo)
  1122  	_, wasDeleted, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), rest.ValidateAllObjectFunc, metav1.NewDeleteOptions(bigGrace))
  1123  	if err != nil {
  1124  		t.Errorf("unexpected error: %v", err)
  1125  	}
  1126  	if wasDeleted {
  1127  		t.Errorf("unexpected, object %s should not have been deleted immediately", objectMeta.GetName())
  1128  	}
  1129  	object, err := getFn(ctx, foo)
  1130  	if err != nil {
  1131  		t.Fatalf("did not gracefully delete resource: %v", err)
  1132  	}
  1133  	objectMeta = t.getObjectMetaOrFail(object)
  1134  	deletionTimestamp := *objectMeta.GetDeletionTimestamp()
  1135  
  1136  	// second delete duration is ignored
  1137  	_, wasDeleted, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), rest.ValidateAllObjectFunc, metav1.NewDeleteOptions(expectedGrace))
  1138  	if err != nil {
  1139  		t.Errorf("unexpected error: %v", err)
  1140  	}
  1141  	if wasDeleted {
  1142  		t.Errorf("unexpected, object %s should not have been deleted immediately", objectMeta.GetName())
  1143  	}
  1144  	object, err = t.storage.(rest.Getter).Get(ctx, objectMeta.GetName(), &metav1.GetOptions{})
  1145  	if err != nil {
  1146  		t.Errorf("unexpected error, object should exist: %v", err)
  1147  	}
  1148  	objectMeta = t.getObjectMetaOrFail(object)
  1149  	if objectMeta.GetDeletionTimestamp() == nil || objectMeta.GetDeletionGracePeriodSeconds() == nil ||
  1150  		*objectMeta.GetDeletionGracePeriodSeconds() != expectedGrace || !objectMeta.GetDeletionTimestamp().Before(&deletionTimestamp) {
  1151  		t.Errorf("unexpected deleted meta: %#v", objectMeta)
  1152  	}
  1153  }
  1154  
  1155  // =============================================================================
  1156  // Get tests.
  1157  
  1158  // testGetDifferentNamespace ensures same-name objects in different namespaces do not clash
  1159  func (t *Tester) testGetDifferentNamespace(obj runtime.Object) {
  1160  	if t.clusterScope {
  1161  		t.Fatalf("the test does not work in cluster-scope")
  1162  	}
  1163  
  1164  	objMeta := t.getObjectMetaOrFail(obj)
  1165  	objMeta.SetName(t.namer(5))
  1166  
  1167  	ctx1 := genericapirequest.WithNamespace(genericapirequest.NewContext(), "bar3")
  1168  	objMeta.SetNamespace(genericapirequest.NamespaceValue(ctx1))
  1169  	_, err := t.storage.(rest.Creater).Create(ctx1, obj, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
  1170  	if err != nil {
  1171  		t.Errorf("unexpected error: %v", err)
  1172  	}
  1173  
  1174  	ctx2 := genericapirequest.WithNamespace(genericapirequest.NewContext(), "bar4")
  1175  	objMeta.SetNamespace(genericapirequest.NamespaceValue(ctx2))
  1176  	_, err = t.storage.(rest.Creater).Create(ctx2, obj, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
  1177  	if err != nil {
  1178  		t.Errorf("unexpected error: %v", err)
  1179  	}
  1180  
  1181  	got1, err := t.storage.(rest.Getter).Get(ctx1, objMeta.GetName(), &metav1.GetOptions{})
  1182  	if err != nil {
  1183  		t.Errorf("unexpected error: %v", err)
  1184  	}
  1185  	got1Meta := t.getObjectMetaOrFail(got1)
  1186  	if got1Meta.GetName() != objMeta.GetName() {
  1187  		t.Errorf("unexpected name of object: %#v, expected: %s", got1, objMeta.GetName())
  1188  	}
  1189  	if got1Meta.GetNamespace() != genericapirequest.NamespaceValue(ctx1) {
  1190  		t.Errorf("unexpected namespace of object: %#v, expected: %s", got1, genericapirequest.NamespaceValue(ctx1))
  1191  	}
  1192  
  1193  	got2, err := t.storage.(rest.Getter).Get(ctx2, objMeta.GetName(), &metav1.GetOptions{})
  1194  	if err != nil {
  1195  		t.Errorf("unexpected error: %v", err)
  1196  	}
  1197  	got2Meta := t.getObjectMetaOrFail(got2)
  1198  	if got2Meta.GetName() != objMeta.GetName() {
  1199  		t.Errorf("unexpected name of object: %#v, expected: %s", got2, objMeta.GetName())
  1200  	}
  1201  	if got2Meta.GetNamespace() != genericapirequest.NamespaceValue(ctx2) {
  1202  		t.Errorf("unexpected namespace of object: %#v, expected: %s", got2, genericapirequest.NamespaceValue(ctx2))
  1203  	}
  1204  }
  1205  
  1206  func (t *Tester) testGetFound(obj runtime.Object) {
  1207  	ctx := t.TestContext()
  1208  	t.setObjectMeta(obj, t.namer(1))
  1209  
  1210  	existing, err := t.storage.(rest.Creater).Create(ctx, obj, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
  1211  	if err != nil {
  1212  		t.Errorf("unexpected error: %v", err)
  1213  	}
  1214  	existingMeta := t.getObjectMetaOrFail(existing)
  1215  
  1216  	got, err := t.storage.(rest.Getter).Get(ctx, t.namer(1), &metav1.GetOptions{})
  1217  	if err != nil {
  1218  		t.Errorf("unexpected error: %v", err)
  1219  	}
  1220  	gotMeta := t.getObjectMetaOrFail(got)
  1221  	gotMeta.SetResourceVersion(existingMeta.GetResourceVersion())
  1222  	if e, a := existing, got; !apiequality.Semantic.DeepEqual(e, a) {
  1223  		t.Errorf("unexpected obj: %#v, expected %#v", e, a)
  1224  	}
  1225  }
  1226  
  1227  func (t *Tester) testGetMimatchedNamespace(obj runtime.Object) {
  1228  	ctx1 := genericapirequest.WithNamespace(genericapirequest.NewContext(), "bar1")
  1229  	ctx2 := genericapirequest.WithNamespace(genericapirequest.NewContext(), "bar2")
  1230  	objMeta := t.getObjectMetaOrFail(obj)
  1231  	objMeta.SetName(t.namer(4))
  1232  	objMeta.SetNamespace(genericapirequest.NamespaceValue(ctx1))
  1233  	_, err := t.storage.(rest.Creater).Create(ctx1, obj, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
  1234  	if err != nil {
  1235  		t.Errorf("unexpected error: %v", err)
  1236  	}
  1237  	_, err = t.storage.(rest.Getter).Get(ctx2, t.namer(4), &metav1.GetOptions{})
  1238  	if t.clusterScope {
  1239  		if err != nil {
  1240  			t.Errorf("unexpected error: %v", err)
  1241  		}
  1242  	} else {
  1243  		if !errors.IsNotFound(err) {
  1244  			t.Errorf("unexpected error returned: %#v", err)
  1245  		}
  1246  	}
  1247  }
  1248  
  1249  func (t *Tester) testGetNotFound(obj runtime.Object) {
  1250  	ctx := t.TestContext()
  1251  	t.setObjectMeta(obj, t.namer(2))
  1252  	_, err := t.storage.(rest.Creater).Create(ctx, obj, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
  1253  	if err != nil {
  1254  		t.Errorf("unexpected error: %v", err)
  1255  	}
  1256  	_, err = t.storage.(rest.Getter).Get(ctx, t.namer(3), &metav1.GetOptions{})
  1257  	if !errors.IsNotFound(err) {
  1258  		t.Errorf("unexpected error returned: %#v", err)
  1259  	}
  1260  }
  1261  
  1262  // =============================================================================
  1263  // List tests.
  1264  
  1265  func listToItems(listObj runtime.Object) ([]runtime.Object, error) {
  1266  	v, err := conversion.EnforcePtr(listObj)
  1267  	if err != nil {
  1268  		return nil, fmt.Errorf("unexpected error: %v", err)
  1269  	}
  1270  	items := v.FieldByName("Items")
  1271  	if !items.IsValid() {
  1272  		return nil, fmt.Errorf("unexpected Items field in %v", listObj)
  1273  	}
  1274  	if items.Type().Kind() != reflect.Slice {
  1275  		return nil, fmt.Errorf("unexpected Items field type: %v", items.Type().Kind())
  1276  	}
  1277  	result := make([]runtime.Object, items.Len())
  1278  	for i := 0; i < items.Len(); i++ {
  1279  		result[i] = items.Index(i).Addr().Interface().(runtime.Object)
  1280  	}
  1281  	return result, nil
  1282  }
  1283  
  1284  func (t *Tester) testListFound(obj runtime.Object, assignFn AssignFunc) {
  1285  	ctx := t.TestContext()
  1286  
  1287  	foo1 := obj.DeepCopyObject()
  1288  	t.setObjectMeta(foo1, t.namer(1))
  1289  	foo2 := obj.DeepCopyObject()
  1290  	t.setObjectMeta(foo2, t.namer(2))
  1291  
  1292  	existing := assignFn([]runtime.Object{foo1, foo2})
  1293  
  1294  	listObj, err := t.storage.(rest.Lister).List(ctx, nil)
  1295  	if err != nil {
  1296  		t.Errorf("unexpected error: %v", err)
  1297  	}
  1298  	items, err := listToItems(listObj)
  1299  	if err != nil {
  1300  		t.Errorf("unexpected error: %v", err)
  1301  	}
  1302  	if len(items) != len(existing) {
  1303  		t.Errorf("unexpected number of items: %v", len(items))
  1304  	}
  1305  	if !apiequality.Semantic.DeepEqual(existing, items) {
  1306  		t.Errorf("expected: %#v, got: %#v", existing, items)
  1307  	}
  1308  }
  1309  
  1310  func (t *Tester) testListMatchLabels(obj runtime.Object, assignFn AssignFunc) {
  1311  	ctx := t.TestContext()
  1312  	testLabels := map[string]string{"key": "value"}
  1313  
  1314  	foo3 := obj.DeepCopyObject()
  1315  	t.setObjectMeta(foo3, "foo3")
  1316  	foo4 := obj.DeepCopyObject()
  1317  	foo4Meta := t.getObjectMetaOrFail(foo4)
  1318  	foo4Meta.SetName("foo4")
  1319  	foo4Meta.SetNamespace(genericapirequest.NamespaceValue(ctx))
  1320  	foo4Meta.SetLabels(testLabels)
  1321  
  1322  	objs := ([]runtime.Object{foo3, foo4})
  1323  
  1324  	assignFn(objs)
  1325  	filtered := []runtime.Object{objs[1]}
  1326  
  1327  	selector := labels.SelectorFromSet(labels.Set(testLabels))
  1328  	options := &metainternalversion.ListOptions{LabelSelector: selector}
  1329  	listObj, err := t.storage.(rest.Lister).List(ctx, options)
  1330  	if err != nil {
  1331  		t.Errorf("unexpected error: %v", err)
  1332  	}
  1333  	items, err := listToItems(listObj)
  1334  	if err != nil {
  1335  		t.Errorf("unexpected error: %v", err)
  1336  	}
  1337  	if len(items) != len(filtered) {
  1338  		t.Errorf("unexpected number of items: %v", len(items))
  1339  	}
  1340  	if !apiequality.Semantic.DeepEqual(filtered, items) {
  1341  		t.Errorf("expected: %#v, got: %#v", filtered, items)
  1342  	}
  1343  }
  1344  
  1345  func (t *Tester) testListNotFound(assignFn AssignFunc) {
  1346  	ctx := t.TestContext()
  1347  	_ = assignFn([]runtime.Object{})
  1348  
  1349  	listObj, err := t.storage.(rest.Lister).List(ctx, nil)
  1350  	if err != nil {
  1351  		t.Errorf("unexpected error: %v", err)
  1352  	}
  1353  	items, err := listToItems(listObj)
  1354  	if err != nil {
  1355  		t.Errorf("unexpected error: %v", err)
  1356  	}
  1357  	if len(items) != 0 {
  1358  		t.Errorf("unexpected items: %#v", items)
  1359  	}
  1360  }
  1361  
  1362  // testListTableConversion verifies a set of known bounds and expected limitations for the values
  1363  // returned from a TableList. These conditions may be changed if necessary with adequate review.
  1364  func (t *Tester) testListTableConversion(obj runtime.Object, assignFn AssignFunc) {
  1365  	ctx := t.TestContext()
  1366  	testLabels := map[string]string{"key": "value"}
  1367  
  1368  	foo3 := obj.DeepCopyObject()
  1369  	t.setObjectMeta(foo3, "foo3")
  1370  	foo4 := obj.DeepCopyObject()
  1371  	foo4Meta := t.getObjectMetaOrFail(foo4)
  1372  	foo4Meta.SetName("foo4")
  1373  	foo4Meta.SetNamespace(genericapirequest.NamespaceValue(ctx))
  1374  	foo4Meta.SetLabels(testLabels)
  1375  
  1376  	objs := ([]runtime.Object{foo3, foo4})
  1377  
  1378  	assignFn(objs)
  1379  
  1380  	options := &metainternalversion.ListOptions{}
  1381  	listObj, err := t.storage.(rest.Lister).List(ctx, options)
  1382  	if err != nil {
  1383  		t.Errorf("unexpected error: %v", err)
  1384  	}
  1385  	items, err := listToItems(listObj)
  1386  	if err != nil {
  1387  		t.Errorf("unexpected error: %v", err)
  1388  	}
  1389  	if len(items) != len(objs) {
  1390  		t.Errorf("unexpected number of items: %v", len(items))
  1391  	}
  1392  	if !apiequality.Semantic.DeepEqual(objs, items) {
  1393  		t.Errorf("expected: %#v, got: %#v", objs, items)
  1394  	}
  1395  
  1396  	m, err := meta.ListAccessor(listObj)
  1397  	if err != nil {
  1398  		t.Fatalf("list should support ListMeta %T: %v", listObj, err)
  1399  	}
  1400  	m.SetContinue("continuetoken")
  1401  	m.SetResourceVersion("11")
  1402  
  1403  	table, err := t.storage.(rest.TableConvertor).ConvertToTable(ctx, listObj, nil)
  1404  	if err != nil {
  1405  		t.Errorf("unexpected error: %v", err)
  1406  	}
  1407  	if table.ResourceVersion != "11" || table.Continue != "continuetoken" {
  1408  		t.Errorf("printer lost list meta: %#v", table.ListMeta)
  1409  	}
  1410  	if len(table.Rows) != len(items) {
  1411  		t.Errorf("unexpected number of rows: %v", len(table.Rows))
  1412  	}
  1413  	columns := table.ColumnDefinitions
  1414  	if len(columns) == 0 {
  1415  		t.Fatalf("unexpected number of columns: %v\n%#v", len(columns), columns)
  1416  	}
  1417  	if !strings.EqualFold(columns[0].Name, "Name") || columns[0].Type != "string" || columns[0].Format != "name" {
  1418  		t.Errorf("expect column 0 to be the name column: %#v", columns[0])
  1419  	}
  1420  	for j, column := range columns {
  1421  		if len(column.Name) == 0 {
  1422  			t.Errorf("column %d has no name", j)
  1423  		}
  1424  		switch column.Type {
  1425  		case "string", "date", "integer", "number", "boolean":
  1426  		default:
  1427  			t.Errorf("column %d has unexpected type: %q", j, column.Type)
  1428  		}
  1429  		switch {
  1430  		case column.Format == "":
  1431  		case column.Format == "name" && column.Type == "string":
  1432  		default:
  1433  			t.Errorf("column %d has unexpected format: %q with type %q", j, column.Format, column.Type)
  1434  		}
  1435  		if column.Priority < 0 || column.Priority > 2 {
  1436  			t.Errorf("column %d has unexpected priority: %q", j, column.Priority)
  1437  		}
  1438  		if len(column.Description) == 0 {
  1439  			t.Errorf("column %d has no description", j)
  1440  		}
  1441  		if column.Name == "Created At" && column.Type != "date" && column.Format != "" {
  1442  			t.Errorf("column %d looks like a created at column, but has a different type and format: %#v", j, column)
  1443  		}
  1444  	}
  1445  	for i, row := range table.Rows {
  1446  		if len(row.Cells) != len(table.ColumnDefinitions) {
  1447  			t.Errorf("row %d did not have the correct number of cells: %d in %v, expected %d", i, len(row.Cells), row.Cells, len(table.ColumnDefinitions))
  1448  		}
  1449  		for j, cell := range row.Cells {
  1450  			// do not add to this test without discussion - may break clients
  1451  			switch cell.(type) {
  1452  			case float64, int64, int32, int, string, bool:
  1453  			case []interface{}:
  1454  			case nil:
  1455  			default:
  1456  				t.Errorf("row %d, cell %d has an unrecognized type, only JSON serialization safe types are allowed: %T ", i, j, cell)
  1457  			}
  1458  		}
  1459  		if len(row.Cells) != len(table.ColumnDefinitions) {
  1460  			t.Fatalf("unmatched row length on row %d: %#v", i, row.Cells)
  1461  		}
  1462  	}
  1463  	data, _ := json.MarshalIndent(table, "", "  ")
  1464  	t.Logf("%s", string(data))
  1465  }
  1466  
  1467  // =============================================================================
  1468  // Watching tests.
  1469  
  1470  func (t *Tester) testWatchFields(obj runtime.Object, emitFn EmitFunc, fieldsPass, fieldsFail []fields.Set, actions []string) {
  1471  	ctx := t.TestContext()
  1472  
  1473  	for _, field := range fieldsPass {
  1474  		for _, action := range actions {
  1475  			options := &metainternalversion.ListOptions{FieldSelector: field.AsSelector(), ResourceVersion: "1"}
  1476  			watcher, err := t.storage.(rest.Watcher).Watch(ctx, options)
  1477  			if err != nil {
  1478  				t.Errorf("unexpected error: %v, %v", err, action)
  1479  			}
  1480  
  1481  			if err := emitFn(obj, action); err != nil {
  1482  				t.Errorf("unexpected error: %v", err)
  1483  			}
  1484  
  1485  			select {
  1486  			case _, ok := <-watcher.ResultChan():
  1487  				if !ok {
  1488  					t.Errorf("watch channel should be open")
  1489  				}
  1490  			case <-time.After(wait.ForeverTestTimeout):
  1491  				t.Errorf("unexpected timeout from result channel")
  1492  			}
  1493  			watcher.Stop()
  1494  		}
  1495  	}
  1496  
  1497  	for _, field := range fieldsFail {
  1498  		for _, action := range actions {
  1499  			options := &metainternalversion.ListOptions{FieldSelector: field.AsSelector(), ResourceVersion: "1"}
  1500  			watcher, err := t.storage.(rest.Watcher).Watch(ctx, options)
  1501  			if err != nil {
  1502  				t.Errorf("unexpected error: %v", err)
  1503  			}
  1504  			if err := emitFn(obj, action); err != nil {
  1505  				t.Errorf("unexpected error: %v", err)
  1506  			}
  1507  
  1508  			select {
  1509  			case <-watcher.ResultChan():
  1510  				t.Errorf("unexpected result from result channel")
  1511  			case <-time.After(time.Millisecond * 500):
  1512  				// expected case
  1513  			}
  1514  			watcher.Stop()
  1515  		}
  1516  	}
  1517  }
  1518  
  1519  func (t *Tester) testWatchLabels(obj runtime.Object, emitFn EmitFunc, labelsPass, labelsFail []labels.Set, actions []string) {
  1520  	ctx := t.TestContext()
  1521  
  1522  	for _, label := range labelsPass {
  1523  		for _, action := range actions {
  1524  			options := &metainternalversion.ListOptions{LabelSelector: label.AsSelector(), ResourceVersion: "1"}
  1525  			watcher, err := t.storage.(rest.Watcher).Watch(ctx, options)
  1526  			if err != nil {
  1527  				t.Errorf("unexpected error: %v", err)
  1528  			}
  1529  			if err := emitFn(obj, action); err != nil {
  1530  				t.Errorf("unexpected error: %v", err)
  1531  			}
  1532  
  1533  			select {
  1534  			case _, ok := <-watcher.ResultChan():
  1535  				if !ok {
  1536  					t.Errorf("watch channel should be open")
  1537  				}
  1538  			case <-time.After(wait.ForeverTestTimeout):
  1539  				t.Errorf("unexpected timeout from result channel")
  1540  			}
  1541  			watcher.Stop()
  1542  		}
  1543  	}
  1544  
  1545  	for _, label := range labelsFail {
  1546  		for _, action := range actions {
  1547  			options := &metainternalversion.ListOptions{LabelSelector: label.AsSelector(), ResourceVersion: "1"}
  1548  			watcher, err := t.storage.(rest.Watcher).Watch(ctx, options)
  1549  			if err != nil {
  1550  				t.Errorf("unexpected error: %v", err)
  1551  			}
  1552  			if err := emitFn(obj, action); err != nil {
  1553  				t.Errorf("unexpected error: %v", err)
  1554  			}
  1555  
  1556  			select {
  1557  			case <-watcher.ResultChan():
  1558  				t.Errorf("unexpected result from result channel")
  1559  			case <-time.After(time.Millisecond * 500):
  1560  				// expected case
  1561  			}
  1562  			watcher.Stop()
  1563  		}
  1564  	}
  1565  }