github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/pkg/runtime/embedded_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 runtime_test 18 19 import ( 20 "encoding/json" 21 "reflect" 22 "testing" 23 24 "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/api/meta" 25 "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/runtime" 26 "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/runtime/schema" 27 "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/runtime/serializer" 28 runtimetesting "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/runtime/testing" 29 "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/util/diff" 30 utilruntime "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/util/runtime" 31 ) 32 33 func TestDecodeEmptyRawExtensionAsObject(t *testing.T) { 34 internalGV := schema.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} 35 externalGV := schema.GroupVersion{Group: "test.group", Version: "v1test"} 36 externalGVK := externalGV.WithKind("ObjectTest") 37 38 s := runtime.NewScheme() 39 s.AddKnownTypes(internalGV, &runtimetesting.ObjectTest{}) 40 s.AddKnownTypeWithName(externalGVK, &runtimetesting.ObjectTestExternal{}) 41 utilruntime.Must(runtimetesting.RegisterConversions(s)) 42 43 codec := serializer.NewCodecFactory(s).LegacyCodec(externalGV) 44 45 obj, gvk, err := codec.Decode([]byte(`{"kind":"`+externalGVK.Kind+`","apiVersion":"`+externalGV.String()+`","items":[{}]}`), nil, nil) 46 if err != nil { 47 t.Fatalf("unexpected error: %v", err) 48 } 49 test := obj.(*runtimetesting.ObjectTest) 50 if unk, ok := test.Items[0].(*runtime.Unknown); !ok || unk.Kind != "" || unk.APIVersion != "" || string(unk.Raw) != "{}" || unk.ContentType != runtime.ContentTypeJSON { 51 t.Fatalf("unexpected object: %#v", test.Items[0]) 52 } 53 if *gvk != externalGVK { 54 t.Fatalf("unexpected kind: %#v", gvk) 55 } 56 57 obj, gvk, err = codec.Decode([]byte(`{"kind":"`+externalGVK.Kind+`","apiVersion":"`+externalGV.String()+`","items":[{"kind":"Other","apiVersion":"v1"}]}`), nil, nil) 58 if err != nil { 59 t.Fatalf("unexpected error: %v", err) 60 } 61 test = obj.(*runtimetesting.ObjectTest) 62 if unk, ok := test.Items[0].(*runtime.Unknown); !ok || unk.Kind != "" || unk.APIVersion != "" || string(unk.Raw) != `{"kind":"Other","apiVersion":"v1"}` || unk.ContentType != runtime.ContentTypeJSON { 63 t.Fatalf("unexpected object: %#v", test.Items[0]) 64 } 65 if *gvk != externalGVK { 66 t.Fatalf("unexpected kind: %#v", gvk) 67 } 68 } 69 70 func TestArrayOfRuntimeObject(t *testing.T) { 71 internalGV := schema.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} 72 externalGV := schema.GroupVersion{Group: "test.group", Version: "v1test"} 73 74 s := runtime.NewScheme() 75 s.AddKnownTypes(internalGV, &runtimetesting.EmbeddedTest{}) 76 s.AddKnownTypeWithName(externalGV.WithKind("EmbeddedTest"), &runtimetesting.EmbeddedTestExternal{}) 77 s.AddKnownTypes(internalGV, &runtimetesting.ObjectTest{}) 78 s.AddKnownTypeWithName(externalGV.WithKind("ObjectTest"), &runtimetesting.ObjectTestExternal{}) 79 utilruntime.Must(runtimetesting.RegisterConversions(s)) 80 81 codec := serializer.NewCodecFactory(s).LegacyCodec(externalGV) 82 83 innerItems := []runtime.Object{ 84 &runtimetesting.EmbeddedTest{ID: "baz"}, 85 } 86 items := []runtime.Object{ 87 &runtimetesting.EmbeddedTest{ID: "foo"}, 88 &runtimetesting.EmbeddedTest{ID: "bar"}, 89 // TODO: until YAML is removed, this JSON must be in ascending key order to ensure consistent roundtrip serialization 90 &runtime.Unknown{ 91 Raw: []byte(`{"apiVersion":"unknown.group/unknown","foo":"bar","kind":"OtherTest"}`), 92 ContentType: runtime.ContentTypeJSON, 93 }, 94 &runtimetesting.ObjectTest{ 95 Items: runtime.NewEncodableList(codec, innerItems), 96 }, 97 } 98 internal := &runtimetesting.ObjectTest{ 99 Items: runtime.NewEncodableList(codec, items), 100 } 101 wire, err := runtime.Encode(codec, internal) 102 if err != nil { 103 t.Fatalf("unexpected error: %v", err) 104 } 105 t.Logf("Wire format is:\n%s\n", string(wire)) 106 107 obj := &runtimetesting.ObjectTestExternal{} 108 if err := json.Unmarshal(wire, obj); err != nil { 109 t.Fatalf("unexpected error: %v", err) 110 } 111 t.Logf("exact wire is: %s", string(obj.Items[0].Raw)) 112 113 items[3] = &runtimetesting.ObjectTest{Items: innerItems} 114 internal.Items = items 115 116 decoded, err := runtime.Decode(codec, wire) 117 if err != nil { 118 t.Fatalf("unexpected error: %v", err) 119 } 120 list, err := meta.ExtractList(decoded) 121 if err != nil { 122 t.Fatalf("unexpected error: %v", err) 123 } 124 if errs := runtime.DecodeList(list, codec); len(errs) > 0 { 125 t.Fatalf("unexpected error: %v", errs) 126 } 127 128 list2, err := meta.ExtractList(list[3]) 129 if err != nil { 130 t.Fatalf("unexpected error: %v", err) 131 } 132 if errs := runtime.DecodeList(list2, codec); len(errs) > 0 { 133 t.Fatalf("unexpected error: %v", errs) 134 } 135 if err := meta.SetList(list[3], list2); err != nil { 136 t.Fatalf("unexpected error: %v", err) 137 } 138 139 // we want DecodeList to set type meta if possible, even on runtime.Unknown objects 140 internal.Items[2].(*runtime.Unknown).TypeMeta = runtime.TypeMeta{Kind: "OtherTest", APIVersion: "unknown.group/unknown"} 141 if e, a := internal.Items, list; !reflect.DeepEqual(e, a) { 142 t.Errorf("mismatched decoded: %s", diff.ObjectGoPrintSideBySide(e, a)) 143 } 144 } 145 146 func TestNestedObject(t *testing.T) { 147 internalGV := schema.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} 148 externalGV := schema.GroupVersion{Group: "test.group", Version: "v1test"} 149 embeddedTestExternalGVK := externalGV.WithKind("EmbeddedTest") 150 151 s := runtime.NewScheme() 152 s.AddKnownTypes(internalGV, &runtimetesting.EmbeddedTest{}) 153 s.AddKnownTypeWithName(embeddedTestExternalGVK, &runtimetesting.EmbeddedTestExternal{}) 154 utilruntime.Must(runtimetesting.RegisterConversions(s)) 155 156 codec := serializer.NewCodecFactory(s).LegacyCodec(externalGV) 157 158 inner := &runtimetesting.EmbeddedTest{ 159 ID: "inner", 160 } 161 outer := &runtimetesting.EmbeddedTest{ 162 ID: "outer", 163 Object: runtime.NewEncodable(codec, inner), 164 } 165 166 wire, err := runtime.Encode(codec, outer) 167 if err != nil { 168 t.Fatalf("Unexpected encode error '%v'", err) 169 } 170 171 t.Logf("Wire format is:\n%v\n", string(wire)) 172 173 decoded, err := runtime.Decode(codec, wire) 174 if err != nil { 175 t.Fatalf("Unexpected decode error %v", err) 176 } 177 178 // for later tests 179 outer.Object = inner 180 181 if e, a := outer, decoded; reflect.DeepEqual(e, a) { 182 t.Errorf("Expected unequal %#v %#v", e, a) 183 } 184 185 obj, err := runtime.Decode(codec, decoded.(*runtimetesting.EmbeddedTest).Object.(*runtime.Unknown).Raw) 186 if err != nil { 187 t.Fatal(err) 188 } 189 decoded.(*runtimetesting.EmbeddedTest).Object = obj 190 if e, a := outer, decoded; !reflect.DeepEqual(e, a) { 191 t.Errorf("Expected equal %#v %#v", e, a) 192 } 193 194 // test JSON decoding of the external object, which should preserve 195 // raw bytes 196 var externalViaJSON runtimetesting.EmbeddedTestExternal 197 err = json.Unmarshal(wire, &externalViaJSON) 198 if err != nil { 199 t.Fatalf("Unexpected decode error %v", err) 200 } 201 if externalViaJSON.Kind == "" || externalViaJSON.APIVersion == "" || externalViaJSON.ID != "outer" { 202 t.Errorf("Expected objects to have type info set, got %#v", externalViaJSON) 203 } 204 if len(externalViaJSON.EmptyObject.Raw) > 0 { 205 t.Errorf("Expected deserialization of empty nested objects into empty bytes, got %#v", externalViaJSON) 206 } 207 208 // test JSON decoding, too, since Decode uses yaml unmarshalling. 209 // Generic Unmarshalling of JSON cannot load the nested objects because there is 210 // no default schema set. Consumers wishing to get direct JSON decoding must use 211 // the external representation 212 var decodedViaJSON runtimetesting.EmbeddedTest 213 err = json.Unmarshal(wire, &decodedViaJSON) 214 if err == nil { 215 t.Fatal("Expeceted decode error") 216 } 217 if _, ok := err.(*json.UnmarshalTypeError); !ok { 218 t.Fatalf("Unexpected decode error: %v", err) 219 } 220 if a := decodedViaJSON; a.Object != nil || a.EmptyObject != nil { 221 t.Errorf("Expected embedded objects to be nil: %#v", a) 222 } 223 } 224 225 // TestDeepCopyOfRuntimeObject checks to make sure that runtime.Objects's can be passed through DeepCopy with fidelity 226 func TestDeepCopyOfRuntimeObject(t *testing.T) { 227 internalGV := schema.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} 228 externalGV := schema.GroupVersion{Group: "test.group", Version: "v1test"} 229 embeddedTestExternalGVK := externalGV.WithKind("EmbeddedTest") 230 231 s := runtime.NewScheme() 232 s.AddKnownTypes(internalGV, &runtimetesting.EmbeddedTest{}) 233 s.AddKnownTypeWithName(embeddedTestExternalGVK, &runtimetesting.EmbeddedTestExternal{}) 234 utilruntime.Must(runtimetesting.RegisterConversions(s)) 235 236 original := &runtimetesting.EmbeddedTest{ 237 ID: "outer", 238 Object: &runtimetesting.EmbeddedTest{ 239 ID: "inner", 240 }, 241 } 242 243 codec := serializer.NewCodecFactory(s).LegacyCodec(externalGV) 244 245 originalData, err := runtime.Encode(codec, original) 246 if err != nil { 247 t.Errorf("unexpected error: %v", err) 248 } 249 t.Logf("originalRole = %v\n", string(originalData)) 250 251 copyOfOriginal := original.DeepCopy() 252 copiedData, err := runtime.Encode(codec, copyOfOriginal) 253 if err != nil { 254 t.Errorf("unexpected error: %v", err) 255 } 256 t.Logf("copyOfRole = %v\n", string(copiedData)) 257 258 if !reflect.DeepEqual(original, copyOfOriginal) { 259 t.Errorf("expected \n%v\n, got \n%v", string(originalData), string(copiedData)) 260 } 261 }