@@ -23,6 +23,9 @@ import (
23
23
"testing"
24
24
25
25
"k8s.io/apimachinery/pkg/runtime"
26
+ runtimetesting "k8s.io/apimachinery/pkg/runtime/testing"
27
+
28
+ "github.com/google/go-cmp/cmp"
26
29
)
27
30
28
31
func TestEmbeddedRawExtensionMarshal (t * testing.T ) {
@@ -111,3 +114,151 @@ func TestEmbeddedRawExtensionRoundTrip(t *testing.T) {
111
114
}
112
115
}
113
116
}
117
+
118
+ func TestRawExtensionMarshalUnstructured (t * testing.T ) {
119
+ for _ , tc := range []struct {
120
+ Name string
121
+ In runtime.RawExtension
122
+ WantCBOR []byte
123
+ ExpectedErrorCBOR string
124
+ WantJSON string
125
+ ExpectedErrorJSON string
126
+ }{
127
+ {
128
+ Name : "nil bytes and nil object" ,
129
+ In : runtime.RawExtension {},
130
+ WantCBOR : []byte {0xf6 },
131
+ WantJSON : "null" ,
132
+ },
133
+ {
134
+ Name : "nil bytes and non-nil object" ,
135
+ In : runtime.RawExtension {Object : & runtimetesting.ExternalSimple {TestString : "foo" }},
136
+ WantCBOR : []byte ("\xa1 \x4a testString\x43 foo" ),
137
+ WantJSON : `{"testString":"foo"}` ,
138
+ },
139
+ {
140
+ Name : "cbor bytes not enclosed in self-described tag" ,
141
+ In : runtime.RawExtension {Raw : []byte {0x43 , 'f' , 'o' , 'o' }}, // 'foo'
142
+ ExpectedErrorCBOR : "cannot convert RawExtension with unrecognized content type to unstructured" ,
143
+ ExpectedErrorJSON : "cannot convert RawExtension with unrecognized content type to unstructured" ,
144
+ },
145
+ {
146
+ Name : "cbor bytes enclosed in self-described tag" ,
147
+ In : runtime.RawExtension {Raw : []byte {0xd9 , 0xd9 , 0xf7 , 0x43 , 'f' , 'o' , 'o' }}, // 55799('foo')
148
+ WantCBOR : []byte {0xd9 , 0xd9 , 0xf7 , 0x43 , 'f' , 'o' , 'o' }, // 55799('foo')
149
+ WantJSON : `"foo"` ,
150
+ },
151
+ {
152
+ Name : "json bytes" ,
153
+ In : runtime.RawExtension {Raw : []byte (`"foo"` )},
154
+ WantCBOR : []byte {0x43 , 'f' , 'o' , 'o' },
155
+ WantJSON : `"foo"` ,
156
+ },
157
+ {
158
+ Name : "ambiguous bytes not enclosed in self-described cbor tag" ,
159
+ In : runtime.RawExtension {Raw : []byte {'0' }}, // CBOR -17 / JSON 0
160
+ WantCBOR : []byte {0x00 },
161
+ WantJSON : `0` ,
162
+ },
163
+ {
164
+ Name : "ambiguous bytes enclosed in self-described cbor tag" ,
165
+ In : runtime.RawExtension {Raw : []byte {0xd9 , 0xd9 , 0xf7 , '0' }}, // 55799(-17)
166
+ WantCBOR : []byte {0xd9 , 0xd9 , 0xf7 , '0' },
167
+ WantJSON : `-17` ,
168
+ },
169
+ {
170
+ Name : "unrecognized bytes" ,
171
+ In : runtime.RawExtension {Raw : []byte {0xff }},
172
+ ExpectedErrorCBOR : "cannot convert RawExtension with unrecognized content type to unstructured" ,
173
+ ExpectedErrorJSON : "cannot convert RawExtension with unrecognized content type to unstructured" ,
174
+ },
175
+ {
176
+ Name : "invalid cbor with self-described cbor prefix" ,
177
+ In : runtime.RawExtension {Raw : []byte {0xd9 , 0xd9 , 0xf7 , 0xff }},
178
+ WantCBOR : []byte {0xd9 , 0xd9 , 0xf7 , 0xff }, // verbatim
179
+ ExpectedErrorJSON : `failed to parse RawExtension bytes as CBOR: cbor: unexpected "break" code` ,
180
+ },
181
+ {
182
+ Name : "invalid json with json prefix" ,
183
+ In : runtime.RawExtension {Raw : []byte (`{{` )},
184
+ ExpectedErrorCBOR : `failed to parse RawExtension bytes as JSON: invalid character '{' looking for beginning of object key string` ,
185
+ WantJSON : `{{` , // verbatim
186
+ },
187
+ } {
188
+ t .Run (tc .Name , func (t * testing.T ) {
189
+ t .Run ("CBOR" , func (t * testing.T ) {
190
+ got , err := tc .In .MarshalCBOR ()
191
+ if err != nil {
192
+ if tc .ExpectedErrorCBOR == "" {
193
+ t .Fatalf ("unexpected error: %v" , err )
194
+ }
195
+ if msg := err .Error (); msg != tc .ExpectedErrorCBOR {
196
+ t .Fatalf ("expected error %q but got %q" , tc .ExpectedErrorCBOR , msg )
197
+ }
198
+ }
199
+
200
+ if diff := cmp .Diff (tc .WantCBOR , got ); diff != "" {
201
+ t .Errorf ("unexpected diff:\n %s" , diff )
202
+ }
203
+ })
204
+
205
+ t .Run ("JSON" , func (t * testing.T ) {
206
+ got , err := tc .In .MarshalJSON ()
207
+ if err != nil {
208
+ if tc .ExpectedErrorJSON == "" {
209
+ t .Fatalf ("unexpected error: %v" , err )
210
+ }
211
+ if msg := err .Error (); msg != tc .ExpectedErrorJSON {
212
+ t .Fatalf ("expected error %q but got %q" , tc .ExpectedErrorJSON , msg )
213
+ }
214
+ }
215
+
216
+ if diff := cmp .Diff (tc .WantJSON , string (got )); diff != "" {
217
+ t .Errorf ("unexpected diff:\n %s" , diff )
218
+ }
219
+ })
220
+ })
221
+ }
222
+ }
223
+
224
+ func TestRawExtensionUnmarshalCBOR (t * testing.T ) {
225
+ for _ , tc := range []struct {
226
+ Name string
227
+ In []byte
228
+ Want runtime.RawExtension
229
+ }{
230
+ {
231
+ // From json.Unmarshaler: By convention, to approximate the behavior of
232
+ // Unmarshal itself, Unmarshalers implement UnmarshalJSON([]byte("null")) as
233
+ // a no-op.
234
+ Name : "no-op on null" ,
235
+ In : []byte {0xf6 },
236
+ Want : runtime.RawExtension {},
237
+ },
238
+ {
239
+ Name : "input copied verbatim" ,
240
+ In : []byte {0xd9 , 0xd9 , 0xf7 , 0x5f , 0x41 , 'f' , 0x42 , 'o' , 'o' , 0xff }, // 55799(_ 'f' 'oo')
241
+ Want : runtime.RawExtension {
242
+ Raw : []byte {0xd9 , 0xd9 , 0xf7 , 0x5f , 0x41 , 'f' , 0x42 , 'o' , 'o' , 0xff }, // 55799(_ 'f' 'oo')
243
+ },
244
+ },
245
+ {
246
+ Name : "input enclosed in self-described tag if absent" ,
247
+ In : []byte {0x5f , 0x41 , 'f' , 0x42 , 'o' , 'o' , 0xff }, // (_ 'f' 'oo')
248
+ Want : runtime.RawExtension {
249
+ Raw : []byte {0xd9 , 0xd9 , 0xf7 , 0x5f , 0x41 , 'f' , 0x42 , 'o' , 'o' , 0xff }, // 55799(_ 'f' 'oo')
250
+ },
251
+ },
252
+ } {
253
+ t .Run (tc .Name , func (t * testing.T ) {
254
+ var got runtime.RawExtension
255
+ if err := got .UnmarshalCBOR (tc .In ); err != nil {
256
+ t .Fatalf ("unexpected error: %v" , err )
257
+ }
258
+
259
+ if diff := cmp .Diff (tc .Want , got ); diff != "" {
260
+ t .Errorf ("unexpected diff:\n %s" , diff )
261
+ }
262
+ })
263
+ }
264
+ }
0 commit comments