1
16
17 package runtime_test
18
19 import (
20 "encoding/json"
21 "reflect"
22 "testing"
23
24 "k8s.io/apimachinery/pkg/api/meta"
25 "k8s.io/apimachinery/pkg/runtime"
26 "k8s.io/apimachinery/pkg/runtime/schema"
27 "k8s.io/apimachinery/pkg/runtime/serializer"
28 runtimetesting "k8s.io/apimachinery/pkg/runtime/testing"
29 "k8s.io/apimachinery/pkg/util/diff"
30 utilruntime "k8s.io/apimachinery/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
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
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
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
195
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
209
210
211
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
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 }
262
View as plain text