github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/pkg/apis/meta/v1/unstructured/unstructured_test.go (about) 1 /* 2 Copyright 2018 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 unstructured_test 18 19 import ( 20 "math/rand" 21 "reflect" 22 "testing" 23 24 "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/api/apitesting/fuzzer" 25 "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/api/equality" 26 metafuzzer "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/apis/meta/fuzzer" 27 metav1 "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/apis/meta/v1" 28 "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/apis/meta/v1/unstructured" 29 "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/runtime" 30 "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/runtime/serializer" 31 "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/util/diff" 32 "github.com/stretchr/testify/assert" 33 ) 34 35 func TestNilUnstructuredContent(t *testing.T) { 36 var u unstructured.Unstructured 37 uCopy := u.DeepCopy() 38 content := u.UnstructuredContent() 39 expContent := make(map[string]interface{}) 40 assert.EqualValues(t, expContent, content) 41 assert.Equal(t, uCopy, &u) 42 } 43 44 // TestUnstructuredMetadataRoundTrip checks that metadata accessors 45 // correctly set the metadata for unstructured objects. 46 // First, it fuzzes an empty ObjectMeta and sets this value as the metadata for an unstructured object. 47 // Next, it uses metadata accessor methods to set these fuzzed values to another unstructured object. 48 // Finally, it checks that both the unstructured objects are equal. 49 func TestUnstructuredMetadataRoundTrip(t *testing.T) { 50 scheme := runtime.NewScheme() 51 codecs := serializer.NewCodecFactory(scheme) 52 seed := rand.Int63() 53 fuzzer := fuzzer.FuzzerFor(metafuzzer.Funcs, rand.NewSource(seed), codecs) 54 55 N := 1000 56 for i := 0; i < N; i++ { 57 u := &unstructured.Unstructured{Object: map[string]interface{}{}} 58 uCopy := u.DeepCopy() 59 metadata := &metav1.ObjectMeta{} 60 fuzzer.Fuzz(metadata) 61 62 if err := setObjectMeta(u, metadata); err != nil { 63 t.Fatalf("unexpected error setting fuzzed ObjectMeta: %v", err) 64 } 65 setObjectMetaUsingAccessors(u, uCopy) 66 67 if !equality.Semantic.DeepEqual(u, uCopy) { 68 t.Errorf("diff: %v", diff.ObjectReflectDiff(u, uCopy)) 69 } 70 } 71 } 72 73 // TestUnstructuredMetadataOmitempty checks that ObjectMeta omitempty 74 // semantics are enforced for unstructured objects. 75 // The fuzzing test above should catch these cases but this is here just to be safe. 76 // Example: the metadata.clusterName field has the omitempty json tag 77 // so if it is set to it's zero value (""), it should be removed from the metadata map. 78 func TestUnstructuredMetadataOmitempty(t *testing.T) { 79 scheme := runtime.NewScheme() 80 codecs := serializer.NewCodecFactory(scheme) 81 seed := rand.Int63() 82 fuzzer := fuzzer.FuzzerFor(metafuzzer.Funcs, rand.NewSource(seed), codecs) 83 84 // fuzz to make sure we don't miss any function calls below 85 u := &unstructured.Unstructured{Object: map[string]interface{}{}} 86 metadata := &metav1.ObjectMeta{} 87 fuzzer.Fuzz(metadata) 88 if err := setObjectMeta(u, metadata); err != nil { 89 t.Fatalf("unexpected error setting fuzzed ObjectMeta: %v", err) 90 } 91 92 // set zero values for all fields in metadata explicitly 93 // to check that omitempty fields having zero values are never set 94 u.SetName("") 95 u.SetGenerateName("") 96 u.SetNamespace("") 97 u.SetSelfLink("") 98 u.SetUID("") 99 u.SetResourceVersion("") 100 u.SetGeneration(0) 101 u.SetCreationTimestamp(metav1.Time{}) 102 u.SetDeletionTimestamp(nil) 103 u.SetDeletionGracePeriodSeconds(nil) 104 u.SetLabels(nil) 105 u.SetAnnotations(nil) 106 u.SetOwnerReferences(nil) 107 u.SetFinalizers(nil) 108 u.SetManagedFields(nil) 109 110 gotMetadata, _, err := unstructured.NestedFieldNoCopy(u.UnstructuredContent(), "metadata") 111 if err != nil { 112 t.Error(err) 113 } 114 emptyMetadata := make(map[string]interface{}) 115 116 if !reflect.DeepEqual(gotMetadata, emptyMetadata) { 117 t.Errorf("expected %v, got %v", emptyMetadata, gotMetadata) 118 } 119 } 120 121 func setObjectMeta(u *unstructured.Unstructured, objectMeta *metav1.ObjectMeta) error { 122 if objectMeta == nil { 123 unstructured.RemoveNestedField(u.UnstructuredContent(), "metadata") 124 return nil 125 } 126 metadata, err := runtime.DefaultUnstructuredConverter.ToUnstructured(objectMeta) 127 if err != nil { 128 return err 129 } 130 u.UnstructuredContent()["metadata"] = metadata 131 return nil 132 } 133 134 func setObjectMetaUsingAccessors(u, uCopy *unstructured.Unstructured) { 135 uCopy.SetName(u.GetName()) 136 uCopy.SetGenerateName(u.GetGenerateName()) 137 uCopy.SetNamespace(u.GetNamespace()) 138 uCopy.SetSelfLink(u.GetSelfLink()) 139 uCopy.SetUID(u.GetUID()) 140 uCopy.SetResourceVersion(u.GetResourceVersion()) 141 uCopy.SetGeneration(u.GetGeneration()) 142 uCopy.SetCreationTimestamp(u.GetCreationTimestamp()) 143 uCopy.SetDeletionTimestamp(u.GetDeletionTimestamp()) 144 uCopy.SetDeletionGracePeriodSeconds(u.GetDeletionGracePeriodSeconds()) 145 uCopy.SetLabels(u.GetLabels()) 146 uCopy.SetAnnotations(u.GetAnnotations()) 147 uCopy.SetOwnerReferences(u.GetOwnerReferences()) 148 uCopy.SetFinalizers(u.GetFinalizers()) 149 uCopy.SetManagedFields(u.GetManagedFields()) 150 }