github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/pkg/test/api_meta_meta_test.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 test
    18  
    19  import (
    20  	"reflect"
    21  	"testing"
    22  
    23  	fuzz "github.com/google/gofuzz"
    24  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/api/meta"
    25  	metafuzzer "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/apis/meta/fuzzer"
    26  	metav1 "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/apis/meta/v1"
    27  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/apis/testapigroup"
    28  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/runtime"
    29  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/runtime/schema"
    30  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/runtime/serializer"
    31  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/types"
    32  )
    33  
    34  func TestAPIObjectMeta(t *testing.T) {
    35  	j := &testapigroup.Carp{
    36  		TypeMeta: metav1.TypeMeta{APIVersion: "/a", Kind: "b"},
    37  		ObjectMeta: metav1.ObjectMeta{
    38  			Namespace:       "bar",
    39  			Name:            "foo",
    40  			GenerateName:    "prefix",
    41  			UID:             "uid",
    42  			ResourceVersion: "1",
    43  			SelfLink:        "some/place/only/we/know",
    44  			Labels:          map[string]string{"foo": "bar"},
    45  			Annotations:     map[string]string{"x": "y"},
    46  			Finalizers: []string{
    47  				"finalizer.1",
    48  				"finalizer.2",
    49  			},
    50  		},
    51  	}
    52  	var _ metav1.Object = &j.ObjectMeta
    53  	var _ metav1.ObjectMetaAccessor = j
    54  	accessor, err := meta.Accessor(j)
    55  	if err != nil {
    56  		t.Fatalf("unexpected error: %v", err)
    57  	}
    58  	if accessor != metav1.Object(j) {
    59  		t.Fatalf("should have returned the same pointer: %#v\n\n%#v", accessor, j)
    60  	}
    61  	if e, a := "bar", accessor.GetNamespace(); e != a {
    62  		t.Errorf("expected %v, got %v", e, a)
    63  	}
    64  	if e, a := "foo", accessor.GetName(); e != a {
    65  		t.Errorf("expected %v, got %v", e, a)
    66  	}
    67  	if e, a := "prefix", accessor.GetGenerateName(); e != a {
    68  		t.Errorf("expected %v, got %v", e, a)
    69  	}
    70  	if e, a := "uid", string(accessor.GetUID()); e != a {
    71  		t.Errorf("expected %v, got %v", e, a)
    72  	}
    73  	if e, a := "1", accessor.GetResourceVersion(); e != a {
    74  		t.Errorf("expected %v, got %v", e, a)
    75  	}
    76  	if e, a := "some/place/only/we/know", accessor.GetSelfLink(); e != a {
    77  		t.Errorf("expected %v, got %v", e, a)
    78  	}
    79  	if e, a := []string{"finalizer.1", "finalizer.2"}, accessor.GetFinalizers(); !reflect.DeepEqual(e, a) {
    80  		t.Errorf("expected %v, got %v", e, a)
    81  	}
    82  
    83  	typeAccessor, err := meta.TypeAccessor(j)
    84  	if err != nil {
    85  		t.Fatalf("unexpected error: %v", err)
    86  	}
    87  	if e, a := "a", typeAccessor.GetAPIVersion(); e != a {
    88  		t.Errorf("expected %v, got %v", e, a)
    89  	}
    90  	if e, a := "b", typeAccessor.GetKind(); e != a {
    91  		t.Errorf("expected %v, got %v", e, a)
    92  	}
    93  
    94  	accessor.SetNamespace("baz")
    95  	accessor.SetName("bar")
    96  	accessor.SetGenerateName("generate")
    97  	accessor.SetUID("other")
    98  	typeAccessor.SetAPIVersion("c")
    99  	typeAccessor.SetKind("d")
   100  	accessor.SetResourceVersion("2")
   101  	accessor.SetSelfLink("google.com")
   102  	accessor.SetFinalizers([]string{"finalizer.3"})
   103  
   104  	// Prove that accessor changes the original object.
   105  	if e, a := "baz", j.Namespace; e != a {
   106  		t.Errorf("expected %v, got %v", e, a)
   107  	}
   108  	if e, a := "bar", j.Name; e != a {
   109  		t.Errorf("expected %v, got %v", e, a)
   110  	}
   111  	if e, a := "generate", j.GenerateName; e != a {
   112  		t.Errorf("expected %v, got %v", e, a)
   113  	}
   114  	if e, a := types.UID("other"), j.UID; e != a {
   115  		t.Errorf("expected %v, got %v", e, a)
   116  	}
   117  	if e, a := "c", j.APIVersion; e != a {
   118  		t.Errorf("expected %v, got %v", e, a)
   119  	}
   120  	if e, a := "d", j.Kind; e != a {
   121  		t.Errorf("expected %v, got %v", e, a)
   122  	}
   123  	if e, a := "2", j.ResourceVersion; e != a {
   124  		t.Errorf("expected %v, got %v", e, a)
   125  	}
   126  	if e, a := "google.com", j.SelfLink; e != a {
   127  		t.Errorf("expected %v, got %v", e, a)
   128  	}
   129  	if e, a := []string{"finalizer.3"}, j.Finalizers; !reflect.DeepEqual(e, a) {
   130  		t.Errorf("expected %v, got %v", e, a)
   131  	}
   132  
   133  	typeAccessor.SetAPIVersion("d")
   134  	typeAccessor.SetKind("e")
   135  	if e, a := "d", j.APIVersion; e != a {
   136  		t.Errorf("expected %v, got %v", e, a)
   137  	}
   138  	if e, a := "e", j.Kind; e != a {
   139  		t.Errorf("expected %v, got %v", e, a)
   140  	}
   141  }
   142  
   143  func TestGenericTypeMeta(t *testing.T) {
   144  	type TypeMeta struct {
   145  		Kind              string                  `json:"kind,omitempty"`
   146  		Namespace         string                  `json:"namespace,omitempty"`
   147  		Name              string                  `json:"name,omitempty"`
   148  		GenerateName      string                  `json:"generateName,omitempty"`
   149  		UID               string                  `json:"uid,omitempty"`
   150  		CreationTimestamp metav1.Time             `json:"creationTimestamp,omitempty"`
   151  		SelfLink          string                  `json:"selfLink,omitempty"`
   152  		ResourceVersion   string                  `json:"resourceVersion,omitempty"`
   153  		APIVersion        string                  `json:"apiVersion,omitempty"`
   154  		Labels            map[string]string       `json:"labels,omitempty"`
   155  		Annotations       map[string]string       `json:"annotations,omitempty"`
   156  		OwnerReferences   []metav1.OwnerReference `json:"ownerReferences,omitempty"`
   157  		Finalizers        []string                `json:"finalizers,omitempty"`
   158  	}
   159  
   160  	j := struct{ TypeMeta }{TypeMeta{APIVersion: "a", Kind: "b"}}
   161  
   162  	typeAccessor, err := meta.TypeAccessor(&j)
   163  	if err != nil {
   164  		t.Fatalf("unexpected error: %v", err)
   165  	}
   166  	if e, a := "a", typeAccessor.GetAPIVersion(); e != a {
   167  		t.Errorf("expected %v, got %v", e, a)
   168  	}
   169  	if e, a := "b", typeAccessor.GetKind(); e != a {
   170  		t.Errorf("expected %v, got %v", e, a)
   171  	}
   172  
   173  	typeAccessor.SetAPIVersion("c")
   174  	typeAccessor.SetKind("d")
   175  
   176  	if e, a := "c", j.APIVersion; e != a {
   177  		t.Errorf("expected %v, got %v", e, a)
   178  	}
   179  	if e, a := "d", j.Kind; e != a {
   180  		t.Errorf("expected %v, got %v", e, a)
   181  	}
   182  
   183  	typeAccessor.SetAPIVersion("d")
   184  	typeAccessor.SetKind("e")
   185  
   186  	if e, a := "d", j.APIVersion; e != a {
   187  		t.Errorf("expected %v, got %v", e, a)
   188  	}
   189  	if e, a := "e", j.Kind; e != a {
   190  		t.Errorf("expected %v, got %v", e, a)
   191  	}
   192  }
   193  
   194  type InternalTypeMeta struct {
   195  	Kind               string                  `json:"kind,omitempty"`
   196  	Namespace          string                  `json:"namespace,omitempty"`
   197  	Name               string                  `json:"name,omitempty"`
   198  	GenerateName       string                  `json:"generateName,omitempty"`
   199  	UID                string                  `json:"uid,omitempty"`
   200  	CreationTimestamp  metav1.Time             `json:"creationTimestamp,omitempty"`
   201  	SelfLink           string                  `json:"selfLink,omitempty"`
   202  	ResourceVersion    string                  `json:"resourceVersion,omitempty"`
   203  	Continue           string                  `json:"next,omitempty"`
   204  	RemainingItemCount *int64                  `json:"remainingItemCount,omitempty"`
   205  	APIVersion         string                  `json:"apiVersion,omitempty"`
   206  	Labels             map[string]string       `json:"labels,omitempty"`
   207  	Annotations        map[string]string       `json:"annotations,omitempty"`
   208  	Finalizers         []string                `json:"finalizers,omitempty"`
   209  	OwnerReferences    []metav1.OwnerReference `json:"ownerReferences,omitempty"`
   210  }
   211  
   212  func (m *InternalTypeMeta) GetResourceVersion() string     { return m.ResourceVersion }
   213  func (m *InternalTypeMeta) SetResourceVersion(rv string)   { m.ResourceVersion = rv }
   214  func (m *InternalTypeMeta) GetSelfLink() string            { return m.SelfLink }
   215  func (m *InternalTypeMeta) SetSelfLink(link string)        { m.SelfLink = link }
   216  func (m *InternalTypeMeta) GetContinue() string            { return m.Continue }
   217  func (m *InternalTypeMeta) SetContinue(c string)           { m.Continue = c }
   218  func (m *InternalTypeMeta) GetRemainingItemCount() *int64  { return m.RemainingItemCount }
   219  func (m *InternalTypeMeta) SetRemainingItemCount(c *int64) { m.RemainingItemCount = c }
   220  
   221  type MyAPIObject struct {
   222  	TypeMeta InternalTypeMeta `json:",inline"`
   223  }
   224  
   225  func (obj *MyAPIObject) GetListMeta() metav1.ListInterface { return &obj.TypeMeta }
   226  
   227  func (obj *MyAPIObject) GetObjectKind() schema.ObjectKind { return obj }
   228  func (obj *MyAPIObject) SetGroupVersionKind(gvk schema.GroupVersionKind) {
   229  	obj.TypeMeta.APIVersion, obj.TypeMeta.Kind = gvk.ToAPIVersionAndKind()
   230  }
   231  func (obj *MyAPIObject) GroupVersionKind() schema.GroupVersionKind {
   232  	return schema.FromAPIVersionAndKind(obj.TypeMeta.APIVersion, obj.TypeMeta.Kind)
   233  }
   234  func (obj *MyAPIObject) DeepCopyObject() runtime.Object {
   235  	panic("MyAPIObject does not support DeepCopy")
   236  }
   237  
   238  type MyIncorrectlyMarkedAsAPIObject struct{}
   239  
   240  func (obj *MyIncorrectlyMarkedAsAPIObject) GetObjectKind() schema.ObjectKind {
   241  	return schema.EmptyObjectKind
   242  }
   243  func (obj *MyIncorrectlyMarkedAsAPIObject) DeepCopyObject() runtime.Object {
   244  	panic("MyIncorrectlyMarkedAsAPIObject does not support DeepCopy")
   245  }
   246  
   247  func TestResourceVersionerOfAPI(t *testing.T) {
   248  	type T struct {
   249  		runtime.Object
   250  		Expected string
   251  	}
   252  	testCases := map[string]T{
   253  		"empty api object":                   {&MyAPIObject{}, ""},
   254  		"api object with version":            {&MyAPIObject{TypeMeta: InternalTypeMeta{ResourceVersion: "1"}}, "1"},
   255  		"pointer to api object with version": {&MyAPIObject{TypeMeta: InternalTypeMeta{ResourceVersion: "1"}}, "1"},
   256  	}
   257  	versioning := meta.NewAccessor()
   258  	for key, testCase := range testCases {
   259  		actual, err := versioning.ResourceVersion(testCase.Object)
   260  		if err != nil {
   261  			t.Errorf("%s: unexpected error %#v", key, err)
   262  		}
   263  		if actual != testCase.Expected {
   264  			t.Errorf("%s: expected %v, got %v", key, testCase.Expected, actual)
   265  		}
   266  	}
   267  
   268  	failingCases := map[string]struct {
   269  		runtime.Object
   270  		Expected string
   271  	}{
   272  		"not a valid object to try": {&MyIncorrectlyMarkedAsAPIObject{}, "1"},
   273  	}
   274  	for key, testCase := range failingCases {
   275  		_, err := versioning.ResourceVersion(testCase.Object)
   276  		if err == nil {
   277  			t.Errorf("%s: expected error, got nil", key)
   278  		}
   279  	}
   280  
   281  	setCases := map[string]struct {
   282  		runtime.Object
   283  		Expected string
   284  	}{
   285  		"pointer to api object with version": {&MyAPIObject{TypeMeta: InternalTypeMeta{ResourceVersion: "1"}}, "1"},
   286  	}
   287  	for key, testCase := range setCases {
   288  		if err := versioning.SetResourceVersion(testCase.Object, "5"); err != nil {
   289  			t.Errorf("%s: unexpected error %#v", key, err)
   290  		}
   291  		actual, err := versioning.ResourceVersion(testCase.Object)
   292  		if err != nil {
   293  			t.Errorf("%s: unexpected error %#v", key, err)
   294  		}
   295  		if actual != "5" {
   296  			t.Errorf("%s: expected %v, got %v", key, "5", actual)
   297  		}
   298  	}
   299  }
   300  
   301  type MyAPIObject2 struct {
   302  	metav1.TypeMeta
   303  	metav1.ObjectMeta
   304  }
   305  
   306  func getObjectMetaAndOwnerReferences() (myAPIObject2 MyAPIObject2, metaOwnerReferences []metav1.OwnerReference) {
   307  	scheme := runtime.NewScheme()
   308  	codecs := serializer.NewCodecFactory(scheme)
   309  	fuzz.New().NilChance(.5).NumElements(1, 5).Funcs(metafuzzer.Funcs(codecs)...).MaxDepth(10).Fuzz(&myAPIObject2)
   310  	references := myAPIObject2.ObjectMeta.OwnerReferences
   311  	// This is necessary for the test to pass because the getter will return a
   312  	// non-nil slice.
   313  	metaOwnerReferences = make([]metav1.OwnerReference, 0)
   314  	for i := 0; i < len(references); i++ {
   315  		metaOwnerReferences = append(metaOwnerReferences, metav1.OwnerReference{
   316  			Kind:               references[i].Kind,
   317  			Name:               references[i].Name,
   318  			UID:                references[i].UID,
   319  			APIVersion:         references[i].APIVersion,
   320  			Controller:         references[i].Controller,
   321  			BlockOwnerDeletion: references[i].BlockOwnerDeletion,
   322  		})
   323  	}
   324  	if len(references) == 0 {
   325  		// This is necessary for the test to pass because the setter will make a
   326  		// non-nil slice.
   327  		myAPIObject2.ObjectMeta.OwnerReferences = make([]metav1.OwnerReference, 0)
   328  	}
   329  	return myAPIObject2, metaOwnerReferences
   330  }
   331  
   332  func testGetOwnerReferences(t *testing.T) {
   333  	obj, expected := getObjectMetaAndOwnerReferences()
   334  	accessor, err := meta.Accessor(&obj)
   335  	if err != nil {
   336  		t.Error(err)
   337  	}
   338  	references := accessor.GetOwnerReferences()
   339  	if !reflect.DeepEqual(references, expected) {
   340  		t.Errorf("expect %#v\n got %#v", expected, references)
   341  	}
   342  }
   343  
   344  func testSetOwnerReferences(t *testing.T) {
   345  	expected, references := getObjectMetaAndOwnerReferences()
   346  	obj := MyAPIObject2{}
   347  	accessor, err := meta.Accessor(&obj)
   348  	if err != nil {
   349  		t.Error(err)
   350  	}
   351  	accessor.SetOwnerReferences(references)
   352  	if e, a := expected.ObjectMeta.OwnerReferences, obj.ObjectMeta.OwnerReferences; !reflect.DeepEqual(e, a) {
   353  		t.Errorf("expect %#v\n got %#v", e, a)
   354  	}
   355  }
   356  
   357  func TestAccessOwnerReferences(t *testing.T) {
   358  	fuzzIter := 5
   359  	for i := 0; i < fuzzIter; i++ {
   360  		testGetOwnerReferences(t)
   361  		testSetOwnerReferences(t)
   362  	}
   363  }
   364  
   365  // BenchmarkAccessorSetFastPath shows the interface fast path
   366  func BenchmarkAccessorSetFastPath(b *testing.B) {
   367  	obj := &testapigroup.Carp{
   368  		TypeMeta: metav1.TypeMeta{APIVersion: "/a", Kind: "b"},
   369  		ObjectMeta: metav1.ObjectMeta{
   370  			Namespace:       "bar",
   371  			Name:            "foo",
   372  			GenerateName:    "prefix",
   373  			UID:             "uid",
   374  			ResourceVersion: "1",
   375  			SelfLink:        "some/place/only/we/know",
   376  			Labels:          map[string]string{"foo": "bar"},
   377  			Annotations:     map[string]string{"x": "y"},
   378  		},
   379  	}
   380  
   381  	b.ResetTimer()
   382  	for i := 0; i < b.N; i++ {
   383  		acc, err := meta.Accessor(obj)
   384  		if err != nil {
   385  			b.Fatal(err)
   386  		}
   387  		acc.SetNamespace("something")
   388  	}
   389  	b.StopTimer()
   390  }