1
2
3
4
5
6
7
8
9
10 package mgocompat
11
12 import (
13 "encoding/binary"
14 "encoding/json"
15 "errors"
16 "net/url"
17 "reflect"
18 "strconv"
19 "strings"
20 "testing"
21 "time"
22
23 "go.mongodb.org/mongo-driver/bson"
24 "go.mongodb.org/mongo-driver/bson/bsoncodec"
25 "go.mongodb.org/mongo-driver/bson/bsonrw"
26 "go.mongodb.org/mongo-driver/bson/bsontype"
27 "go.mongodb.org/mongo-driver/bson/primitive"
28 "go.mongodb.org/mongo-driver/internal/assert"
29 )
30
31
32
33 func wrapInDoc(data string) string {
34 result := make([]byte, len(data)+5)
35 binary.LittleEndian.PutUint32(result, uint32(len(result)))
36 copy(result[4:], []byte(data))
37 return string(result)
38 }
39
40 func makeZeroDoc(value interface{}) (zero interface{}) {
41 v := reflect.ValueOf(value)
42 t := v.Type()
43 switch t.Kind() {
44 case reflect.Map:
45 mv := reflect.MakeMap(t)
46 zero = mv.Interface()
47 case reflect.Ptr:
48 pv := reflect.New(v.Type().Elem())
49 zero = pv.Interface()
50 case reflect.Slice, reflect.Int, reflect.Int64, reflect.Struct:
51 zero = reflect.New(t).Interface()
52 default:
53 panic("unsupported doc type: " + t.Name())
54 }
55 return zero
56 }
57
58 func testUnmarshal(t *testing.T, data string, obj interface{}) {
59 zero := makeZeroDoc(obj)
60 err := bson.UnmarshalWithRegistry(Registry, []byte(data), zero)
61 assert.Nil(t, err, "expected nil error, got: %v", err)
62 assert.True(t, reflect.DeepEqual(zero, obj), "expected: %v, got: %v", obj, zero)
63 }
64
65 type testItemType struct {
66 obj interface{}
67 data string
68 }
69
70
71
72
73 var sampleItems = []testItemType{
74 {bson.M{"hello": "world"},
75 "\x16\x00\x00\x00\x02hello\x00\x06\x00\x00\x00world\x00\x00"},
76 {bson.M{"BSON": []interface{}{"awesome", float64(5.05), 1986}},
77 "1\x00\x00\x00\x04BSON\x00&\x00\x00\x00\x020\x00\x08\x00\x00\x00" +
78 "awesome\x00\x011\x00333333\x14@\x102\x00\xc2\x07\x00\x00\x00\x00"},
79 {bson.M{"slice": []uint8{1, 2}},
80 "\x13\x00\x00\x00\x05slice\x00\x02\x00\x00\x00\x00\x01\x02\x00"},
81 {bson.M{"slice": []byte{1, 2}},
82 "\x13\x00\x00\x00\x05slice\x00\x02\x00\x00\x00\x00\x01\x02\x00"},
83 }
84
85 func TestMarshalSampleItems(t *testing.T) {
86 for i, item := range sampleItems {
87 t.Run(strconv.Itoa(i), func(t *testing.T) {
88 data, err := bson.MarshalWithRegistry(Registry, item.obj)
89 assert.Nil(t, err, "expected nil error, got: %v", err)
90 assert.Equal(t, string(data), item.data, "expected: %v, got: %v", item.data, string(data))
91 })
92 }
93 }
94
95 func TestUnmarshalSampleItems(t *testing.T) {
96 for i, item := range sampleItems {
97 t.Run(strconv.Itoa(i), func(t *testing.T) {
98 value := bson.M{}
99 err := bson.UnmarshalWithRegistry(Registry, []byte(item.data), &value)
100 assert.Nil(t, err, "expected nil error, got: %v", err)
101 assert.True(t, reflect.DeepEqual(value, item.obj), "expected: %v, got: %v", item.obj, value)
102 })
103 }
104 }
105
106
107
108
109
110
111 var allItems = []testItemType{
112 {bson.M{},
113 ""},
114 {bson.M{"_": float64(5.05)},
115 "\x01_\x00333333\x14@"},
116 {bson.M{"_": "yo"},
117 "\x02_\x00\x03\x00\x00\x00yo\x00"},
118 {bson.M{"_": bson.M{"a": true}},
119 "\x03_\x00\x09\x00\x00\x00\x08a\x00\x01\x00"},
120 {bson.M{"_": []interface{}{true, false}},
121 "\x04_\x00\r\x00\x00\x00\x080\x00\x01\x081\x00\x00\x00"},
122 {bson.M{"_": []byte("yo")},
123 "\x05_\x00\x02\x00\x00\x00\x00yo"},
124 {bson.M{"_": primitive.Binary{Subtype: 0x80, Data: []byte("udef")}},
125 "\x05_\x00\x04\x00\x00\x00\x80udef"},
126 {bson.M{"_": primitive.Undefined{}},
127 "\x06_\x00"},
128 {bson.M{"_": primitive.ObjectID{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B}},
129 "\x07_\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B"},
130 {bson.M{"_": primitive.DBPointer{DB: "testnamespace", Pointer: primitive.ObjectID{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B}}},
131 "\x0C_\x00\x0e\x00\x00\x00testnamespace\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B"},
132 {bson.M{"_": false},
133 "\x08_\x00\x00"},
134 {bson.M{"_": true},
135 "\x08_\x00\x01"},
136 {bson.M{"_": time.Unix(0, 258e6).UTC()},
137 "\x09_\x00\x02\x01\x00\x00\x00\x00\x00\x00"},
138 {bson.M{"_": nil},
139 "\x0A_\x00"},
140 {bson.M{"_": primitive.Regex{Pattern: "ab", Options: "cd"}},
141 "\x0B_\x00ab\x00cd\x00"},
142 {bson.M{"_": primitive.JavaScript("code")},
143 "\x0D_\x00\x05\x00\x00\x00code\x00"},
144 {bson.M{"_": primitive.Symbol("sym")},
145 "\x0E_\x00\x04\x00\x00\x00sym\x00"},
146 {bson.M{"_": primitive.CodeWithScope{Code: "code", Scope: primitive.D{{"", nil}}}},
147 "\x0F_\x00\x14\x00\x00\x00\x05\x00\x00\x00code\x00" +
148 "\x07\x00\x00\x00\x0A\x00\x00"},
149 {bson.M{"_": 258},
150 "\x10_\x00\x02\x01\x00\x00"},
151 {bson.M{"_": primitive.Timestamp{0, 258}},
152 "\x11_\x00\x02\x01\x00\x00\x00\x00\x00\x00"},
153 {bson.M{"_": int64(258)},
154 "\x12_\x00\x02\x01\x00\x00\x00\x00\x00\x00"},
155 {bson.M{"_": int64(258 << 32)},
156 "\x12_\x00\x00\x00\x00\x00\x02\x01\x00\x00"},
157 {bson.M{"_": primitive.MaxKey{}},
158 "\x7F_\x00"},
159 {bson.M{"_": primitive.MinKey{}},
160 "\xFF_\x00"},
161 }
162
163 func TestMarshalAllItems(t *testing.T) {
164 for i, item := range allItems {
165 t.Run(strconv.Itoa(i), func(t *testing.T) {
166 data, err := bson.MarshalWithRegistry(Registry, item.obj)
167 assert.Nil(t, err, "expected nil error, got: %v", err)
168 assert.Equal(t, string(data), wrapInDoc(item.data), "expected: %v, got: %v", wrapInDoc(item.data), string(data))
169 })
170 }
171 }
172
173 func TestUnmarshalAllItems(t *testing.T) {
174 for i, item := range allItems {
175 t.Run(strconv.Itoa(i), func(t *testing.T) {
176 value := bson.M{}
177 err := bson.UnmarshalWithRegistry(Registry, []byte(wrapInDoc(item.data)), &value)
178 assert.Nil(t, err, "expected nil error, got: %v", err)
179 assert.True(t, reflect.DeepEqual(value, item.obj), "expected: %v, got: %v", item.obj, value)
180 })
181 }
182 }
183
184 func TestUnmarshalRawAllItems(t *testing.T) {
185 for i, item := range allItems {
186 if len(item.data) == 0 {
187 continue
188 }
189 value := item.obj.(bson.M)["_"]
190 if value == nil {
191 continue
192 }
193 t.Run(strconv.Itoa(i), func(t *testing.T) {
194 pv := reflect.New(reflect.ValueOf(value).Type())
195 raw := bson.RawValue{Type: bsontype.Type(item.data[0]), Value: []byte(item.data[3:])}
196 err := raw.UnmarshalWithRegistry(Registry, pv.Interface())
197 assert.Nil(t, err, "expected nil error, got: %v", err)
198 assert.True(t, reflect.DeepEqual(value, pv.Elem().Interface()), "expected: %v, got: %v", value, pv.Elem().Interface())
199 })
200 }
201 }
202
203 func TestUnmarshalRawIncompatible(t *testing.T) {
204 raw := bson.RawValue{Type: 0x08, Value: []byte{0x01}}
205 err := raw.UnmarshalWithRegistry(Registry, &struct{}{})
206 assert.NotNil(t, err, "expected an error")
207 }
208
209 func TestUnmarshalZeroesStruct(t *testing.T) {
210 data, err := bson.MarshalWithRegistry(Registry, bson.M{"b": 2})
211 assert.Nil(t, err, "expected nil error, got: %v", err)
212 type T struct{ A, B int }
213 v := T{A: 1}
214 err = bson.UnmarshalWithRegistry(Registry, data, &v)
215 assert.Nil(t, err, "expected nil error, got: %v", err)
216 assert.Equal(t, 0, v.A, "expected: 0, got: %v", v.A)
217 assert.Equal(t, 2, v.B, "expected: 2, got: %v", v.B)
218 }
219
220 func TestUnmarshalZeroesMap(t *testing.T) {
221 data, err := bson.MarshalWithRegistry(Registry, bson.M{"b": 2})
222 assert.Nil(t, err, "expected nil error, got: %v", err)
223 m := bson.M{"a": 1}
224 err = bson.UnmarshalWithRegistry(Registry, data, &m)
225 assert.Nil(t, err, "expected nil error, got: %v", err)
226
227 want := bson.M{"b": 2}
228 assert.True(t, reflect.DeepEqual(want, m), "expected: %v, got: %v", want, m)
229 }
230
231 func TestUnmarshalNonNilInterface(t *testing.T) {
232 data, err := bson.MarshalWithRegistry(Registry, bson.M{"b": 2})
233 assert.Nil(t, err, "expected nil error, got: %v", err)
234 m := bson.M{"a": 1}
235 var i interface{} = m
236 err = bson.UnmarshalWithRegistry(Registry, data, &i)
237 assert.Nil(t, err, "expected nil error, got: %v", err)
238 assert.True(t, reflect.DeepEqual(bson.M{"b": 2}, i), "expected: %v, got: %v", bson.M{"b": 2}, i)
239 assert.True(t, reflect.DeepEqual(bson.M{"a": 1}, m), "expected: %v, got: %v", bson.M{"a": 1}, m)
240 }
241
242 func TestPtrInline(t *testing.T) {
243 cases := []struct {
244 In interface{}
245 Out bson.M
246 }{
247 {
248 In: InlinePtrStruct{A: 1, MStruct: &MStruct{M: 3}},
249 Out: bson.M{"a": 1, "m": 3},
250 },
251 {
252 In: inlinePtrPtrStruct{B: 10, InlinePtrStruct: &InlinePtrStruct{A: 20, MStruct: &MStruct{M: 30}}},
253 Out: bson.M{"b": 10, "a": 20, "m": 30},
254 },
255 {
256
257 In: &InlinePtrStruct{A: 3},
258 Out: bson.M{"a": 3},
259 },
260 {
261
262 In: &inlinePtrPtrStruct{B: 5},
263 Out: bson.M{"b": 5},
264 },
265 }
266
267 for i, cs := range cases {
268 t.Run(strconv.Itoa(i), func(t *testing.T) {
269 data, err := bson.MarshalWithRegistry(Registry, cs.In)
270 assert.Nil(t, err, "expected nil error, got: %v", err)
271 var dataBSON bson.M
272 err = bson.UnmarshalWithRegistry(Registry, data, &dataBSON)
273 assert.Nil(t, err, "expected nil error, got: %v", err)
274
275 assert.True(t, reflect.DeepEqual(cs.Out, dataBSON), "expected: %v, got: %v", cs.Out, dataBSON)
276 })
277 }
278 }
279
280
281
282
283 var js = primitive.JavaScript("code")
284
285 var oneWayMarshalItems = []testItemType{
286
287 {bson.M{"": &primitive.Binary{Subtype: 0x02, Data: []byte("old")}},
288 "\x05\x00\x07\x00\x00\x00\x02\x03\x00\x00\x00old"},
289 {bson.M{"": &primitive.Binary{Subtype: 0x80, Data: []byte("udef")}},
290 "\x05\x00\x04\x00\x00\x00\x80udef"},
291 {bson.M{"": &primitive.Regex{Pattern: "ab", Options: "cd"}},
292 "\x0B\x00ab\x00cd\x00"},
293 {bson.M{"": &js},
294 "\x0D\x00\x05\x00\x00\x00code\x00"},
295 {bson.M{"": &primitive.CodeWithScope{Code: "code", Scope: bson.M{"": nil}}},
296 "\x0F\x00\x14\x00\x00\x00\x05\x00\x00\x00code\x00" +
297 "\x07\x00\x00\x00\x0A\x00\x00"},
298
299
300 {bson.M{"": float32(5.05)},
301 "\x01\x00\x00\x00\x00@33\x14@"},
302
303
304 {bson.M{"": [2]bool{true, false}},
305 "\x04\x00\r\x00\x00\x00\x080\x00\x01\x081\x00\x00\x00"},
306
307
308 {bson.M{"": []bool{true, false}},
309 "\x04\x00\r\x00\x00\x00\x080\x00\x01\x081\x00\x00\x00"},
310
311
312 {bson.M{"": primitive.Binary{Subtype: 0x00, Data: []byte("yo")}},
313 "\x05\x00\x02\x00\x00\x00\x00yo"},
314 {bson.M{"": primitive.Binary{Subtype: 0x02, Data: []byte("old")}},
315 "\x05\x00\x07\x00\x00\x00\x02\x03\x00\x00\x00old"},
316
317
318
319
320 {bson.M{"": (*byte)(nil)},
321 "\x0A\x00"},
322
323
324
325
326 {bson.M{"": byte(8)},
327 "\x10\x00\x08\x00\x00\x00"},
328
329
330 {bson.M{"": uint32(258)},
331 "\x10\x00\x02\x01\x00\x00"},
332 {bson.M{"": uint64(258)},
333 "\x12\x00\x02\x01\x00\x00\x00\x00\x00\x00"},
334 {bson.M{"": uint64(258 << 32)},
335 "\x12\x00\x00\x00\x00\x00\x02\x01\x00\x00"},
336
337
338 {bson.M{"": int32(258)},
339 "\x10\x00\x02\x01\x00\x00"},
340
341
342
343 {bson.M{"": uint32(1<<32 - 1)},
344 "\x12\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00"},
345 {bson.M{"": uint(1<<32 - 1)},
346 "\x12\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00"},
347 }
348
349 func TestOneWayMarshalItems(t *testing.T) {
350 for i, item := range oneWayMarshalItems {
351 t.Run(strconv.Itoa(i), func(t *testing.T) {
352 data, err := bson.MarshalWithRegistry(Registry, item.obj)
353 assert.Nil(t, err, "expected nil error, got: %v", err)
354
355 assert.Equal(t, wrapInDoc(item.data), string(data), "expected: %v, got: %v", bson.Raw(wrapInDoc(item.data)), bson.Raw(data))
356 })
357 }
358 }
359
360
361
362
363
364 type specSample1 struct {
365 Hello string
366 }
367
368 type specSample2 struct {
369 BSON []interface{} `bson:"BSON"`
370 }
371
372 var structSampleItems = []testItemType{
373 {&specSample1{"world"},
374 "\x16\x00\x00\x00\x02hello\x00\x06\x00\x00\x00world\x00\x00"},
375 {&specSample2{[]interface{}{"awesome", float64(5.05), 1986}},
376 "1\x00\x00\x00\x04BSON\x00&\x00\x00\x00\x020\x00\x08\x00\x00\x00" +
377 "awesome\x00\x011\x00333333\x14@\x102\x00\xc2\x07\x00\x00\x00\x00"},
378 }
379
380 func TestMarshalStructSampleItems(t *testing.T) {
381 for i, item := range structSampleItems {
382 t.Run(strconv.Itoa(i), func(t *testing.T) {
383 data, err := bson.MarshalWithRegistry(Registry, item.obj)
384 assert.Nil(t, err, "expected nil error, got: %v", err)
385 assert.Equal(t, item.data, string(data), "expected: %v, got: %v", item.data, string(data))
386 })
387 }
388 }
389
390 func TestUnmarshalStructSampleItems(t *testing.T) {
391 for i, item := range structSampleItems {
392 t.Run(strconv.Itoa(i), func(t *testing.T) {
393 testUnmarshal(t, item.data, item.obj)
394 })
395 }
396 }
397
398 func Test64bitInt(t *testing.T) {
399 var i int64 = (1 << 31)
400 if int(i) > 0 {
401 data, err := bson.MarshalWithRegistry(Registry, bson.M{"i": int(i)})
402 assert.Nil(t, err, "expected nil error, got: %v", err)
403 want := wrapInDoc("\x12i\x00\x00\x00\x00\x80\x00\x00\x00\x00")
404 assert.Equal(t, want, string(data), "expected: %v, got: %v", want, string(data))
405
406 var result struct{ I int }
407 err = bson.UnmarshalWithRegistry(Registry, data, &result)
408 assert.Nil(t, err, "expected nil error, got: %v", err)
409 assert.Equal(t, i, int64(result.I), "expected: %v, got: %v", i, int64(result.I))
410 }
411 }
412
413
414
415
416 type prefixPtr string
417 type prefixVal string
418
419 func (t *prefixPtr) GetBSON() (interface{}, error) {
420 if t == nil {
421 return nil, nil
422 }
423 return "foo-" + string(*t), nil
424 }
425
426 func (t *prefixPtr) SetBSON(raw bson.RawValue) error {
427 var s string
428 if raw.Type == 0x0A {
429 return ErrSetZero
430 }
431 rval := reflect.ValueOf(&s).Elem()
432 decoder, err := Registry.LookupDecoder(rval.Type())
433 if err != nil {
434 return err
435 }
436 vr := bsonrw.NewBSONValueReader(raw.Type, raw.Value)
437 err = decoder.DecodeValue(bsoncodec.DecodeContext{Registry: Registry}, vr, rval)
438 if err != nil {
439 return err
440 }
441
442 if !strings.HasPrefix(s, "foo-") {
443 return errors.New("Prefix not found: " + s)
444 }
445 *t = prefixPtr(s[4:])
446 return nil
447 }
448
449 func (t prefixVal) GetBSON() (interface{}, error) {
450 return "foo-" + string(t), nil
451 }
452
453 func (t *prefixVal) SetBSON(raw bson.RawValue) error {
454 var s string
455 if raw.Type == 0x0A {
456 return ErrSetZero
457 }
458 rval := reflect.ValueOf(&s).Elem()
459 decoder, err := Registry.LookupDecoder(rval.Type())
460 if err != nil {
461 return err
462 }
463 vr := bsonrw.NewBSONValueReader(raw.Type, raw.Value)
464 err = decoder.DecodeValue(bsoncodec.DecodeContext{Registry: Registry}, vr, rval)
465 if err != nil {
466 return err
467 }
468
469 if !strings.HasPrefix(s, "foo-") {
470 return errors.New("Prefix not found: " + s)
471 }
472 *t = prefixVal(s[4:])
473 return nil
474 }
475
476 var bytevar = byte(8)
477 var byteptr = &bytevar
478 var prefixptr = prefixPtr("bar")
479 var prefixval = prefixVal("bar")
480
481 var structItems = []testItemType{
482 {&struct{ Ptr *byte }{nil},
483 "\x0Aptr\x00"},
484 {&struct{ Ptr *byte }{&bytevar},
485 "\x10ptr\x00\x08\x00\x00\x00"},
486 {&struct{ Ptr **byte }{&byteptr},
487 "\x10ptr\x00\x08\x00\x00\x00"},
488 {&struct{ Byte byte }{8},
489 "\x10byte\x00\x08\x00\x00\x00"},
490 {&struct{ Byte byte }{0},
491 "\x10byte\x00\x00\x00\x00\x00"},
492 {&struct {
493 V byte `bson:"Tag"`
494 }{8},
495 "\x10Tag\x00\x08\x00\x00\x00"},
496 {&struct {
497 V *struct {
498 Byte byte
499 }
500 }{&struct{ Byte byte }{8}},
501 "\x03v\x00" + "\x0f\x00\x00\x00\x10byte\x00\b\x00\x00\x00\x00"},
502 {&struct{ priv byte }{}, ""},
503
504
505 {&struct{ A, C, B, D, F, E *byte }{},
506 "\x0Aa\x00\x0Ac\x00\x0Ab\x00\x0Ad\x00\x0Af\x00\x0Ae\x00"},
507
508 {&struct{ V bson.RawValue }{bson.RawValue{Type: 0x03, Value: []byte("\x0f\x00\x00\x00\x10byte\x00\b\x00\x00\x00\x00")}},
509 "\x03v\x00" + "\x0f\x00\x00\x00\x10byte\x00\b\x00\x00\x00\x00"},
510 {&struct{ V bson.RawValue }{bson.RawValue{Type: 0x10, Value: []byte("\x00\x00\x00\x00")}},
511 "\x10v\x00" + "\x00\x00\x00\x00"},
512
513
514 {&struct{ V [2]byte }{[2]byte{'y', 'o'}},
515 "\x05v\x00\x02\x00\x00\x00\x00yo"},
516
517 {&struct{ V prefixPtr }{prefixPtr("buzz")},
518 "\x02v\x00\x09\x00\x00\x00foo-buzz\x00"},
519
520 {&struct{ V *prefixPtr }{&prefixptr},
521 "\x02v\x00\x08\x00\x00\x00foo-bar\x00"},
522
523 {&struct{ V *prefixPtr }{nil},
524 "\x0Av\x00"},
525
526 {&struct{ V prefixVal }{prefixVal("buzz")},
527 "\x02v\x00\x09\x00\x00\x00foo-buzz\x00"},
528
529 {&struct{ V *prefixVal }{&prefixval},
530 "\x02v\x00\x08\x00\x00\x00foo-bar\x00"},
531
532 {&struct{ V *prefixVal }{nil},
533 "\x0Av\x00"},
534 }
535
536 func TestMarshalStructItems(t *testing.T) {
537 for i, item := range structItems {
538 t.Run(strconv.Itoa(i), func(t *testing.T) {
539 data, err := bson.MarshalWithRegistry(Registry, item.obj)
540 assert.Nil(t, err, "expected nil error, got: %v", err)
541 assert.Equal(t, wrapInDoc(item.data), string(data), "expected: %v, got: %v", wrapInDoc(item.data), string(data))
542 })
543 }
544 }
545
546 func TestUnmarshalStructItems(t *testing.T) {
547 for i, item := range structItems {
548 t.Run(strconv.Itoa(i), func(t *testing.T) {
549 testUnmarshal(t, wrapInDoc(item.data), item.obj)
550 })
551 }
552 }
553
554 func TestUnmarshalRawStructItems(t *testing.T) {
555 for i, item := range structItems {
556 t.Run(strconv.Itoa(i), func(t *testing.T) {
557 raw := bson.Raw(wrapInDoc(item.data))
558 zero := makeZeroDoc(item.obj)
559 err := bson.UnmarshalWithRegistry(Registry, raw, zero)
560 assert.Nil(t, err, "expected nil error, got: %v", err)
561 assert.True(t, reflect.DeepEqual(item.obj, zero), "expected: %v, got: %v", item.obj, zero)
562 })
563 }
564 }
565
566
567
568
569
570
571
572
573
574
575
576
577 type dOnIface struct {
578 D interface{}
579 }
580
581 type ignoreField struct {
582 Before string
583 Ignore string `bson:"-"`
584 After string
585 }
586
587 var marshalItems = []testItemType{
588
589 {bson.D{{"a", nil}, {"c", nil}, {"b", nil}, {"d", nil}, {"f", nil}, {"e", true}},
590 "\x0Aa\x00\x0Ac\x00\x0Ab\x00\x0Ad\x00\x0Af\x00\x08e\x00\x01"},
591 {MyD{{"a", nil}, {"c", nil}, {"b", nil}, {"d", nil}, {"f", nil}, {"e", true}},
592 "\x0Aa\x00\x0Ac\x00\x0Ab\x00\x0Ad\x00\x0Af\x00\x08e\x00\x01"},
593 {&dOnIface{bson.D{{"a", nil}, {"c", nil}, {"b", nil}, {"d", true}}},
594 "\x03d\x00" + wrapInDoc("\x0Aa\x00\x0Ac\x00\x0Ab\x00\x08d\x00\x01")},
595
596 {&ignoreField{"before", "ignore", "after"},
597 "\x02before\x00\a\x00\x00\x00before\x00\x02after\x00\x06\x00\x00\x00after\x00"},
598
599
600
601
602
603
604 }
605
606 func TestMarshalOneWayItems(t *testing.T) {
607 for i, item := range marshalItems {
608 t.Run(strconv.Itoa(i), func(t *testing.T) {
609 data, err := bson.MarshalWithRegistry(Registry, item.obj)
610 assert.Nil(t, err, "expected nil error, got: %v", err)
611 assert.Equal(t, wrapInDoc(item.data), string(data), "expected: %v, got: %v", wrapInDoc(item.data), string(data))
612 })
613 }
614 }
615
616
617
618
619 type intAlias int
620
621 var unmarshalItems = []testItemType{
622
623 {&struct{ priv byte }{},
624 "\x10priv\x00\x08\x00\x00\x00"},
625
626
627 {&struct{ Byte byte }{9},
628 "\x10boot\x00\x08\x00\x00\x00" + "\x10byte\x00\x09\x00\x00\x00"},
629
630
631 {&ignoreField{"before", "", "after"},
632 "\x02before\x00\a\x00\x00\x00before\x00" +
633 "\x02-\x00\a\x00\x00\x00ignore\x00" +
634 "\x02after\x00\x06\x00\x00\x00after\x00"},
635
636
637 {&struct{ bson.D }{bson.D{{"a", nil}, {"c", nil}, {"b", nil}, {"d", true}}},
638 "\x03d\x00" + wrapInDoc("\x0Aa\x00\x0Ac\x00\x0Ab\x00\x08d\x00\x01")},
639
640
641
642
643
644
645 {bson.M{"_": []byte("old")},
646 "\x05_\x00\x07\x00\x00\x00\x02\x03\x00\x00\x00old"},
647
648
649 {bson.M{"_": []byte("old")},
650 "\x05_\x00\x03\x00\x00\x00\x02old"},
651
652
653 {map[int]string{10: "s"},
654 "\x0210\x00\x02\x00\x00\x00s\x00"},
655
656
657 {map[intAlias]string{10: "s"},
658 "\x0210\x00\x02\x00\x00\x00s\x00"},
659 }
660
661 func TestUnmarshalOneWayItems(t *testing.T) {
662 for i, item := range unmarshalItems {
663 t.Run(strconv.Itoa(i), func(t *testing.T) {
664 testUnmarshal(t, wrapInDoc(item.data), item.obj)
665 })
666 }
667 }
668
669 func TestUnmarshalNilInStruct(t *testing.T) {
670
671 b := byte(1)
672 v := &struct{ Ptr *byte }{&b}
673 err := bson.UnmarshalWithRegistry(Registry, []byte(wrapInDoc("\x0Aptr\x00")), v)
674 assert.Nil(t, err, "expected nil error, got: %v", err)
675
676 want := &struct{ Ptr *byte }{nil}
677 assert.Equal(t, *want, *v, "expected: %v, got: %v", *want, *v)
678 }
679
680
681
682
683 type structWithDupKeys struct {
684 Name byte
685 Other byte `bson:"name"`
686 }
687
688 var marshalErrorItems = []testItemType{
689 {bson.M{"": uint64(1 << 63)},
690 "BSON has no uint64 type, and value is too large to fit correctly in an int64"},
691 {int64(123),
692 "Can't marshal int64 as a BSON document"},
693 {bson.M{"": 1i},
694 "Can't marshal complex128 in a BSON document"},
695 {&structWithDupKeys{},
696 "Duplicated key 'name' in struct bson_test.structWithDupKeys"},
697 {bson.RawValue{Type: 0xA, Value: []byte{}},
698 "Attempted to marshal Raw kind 10 as a document"},
699 {bson.Raw{},
700 "Attempted to marshal empty Raw document"},
701 {bson.M{"w": bson.Raw{}},
702 "Attempted to marshal empty Raw document"},
703 {&inlineDupName{1, struct{ A, B int }{2, 3}},
704 "Duplicated key 'a' in struct bson_test.inlineDupName"},
705 {&inlineDupMap{},
706 "Multiple ,inline maps in struct bson_test.inlineDupMap"},
707 {&inlineBadKeyMap{},
708 "Option ,inline needs a map with string keys in struct bson_test.inlineBadKeyMap"},
709 {&inlineMap{A: 1, M: map[string]interface{}{"a": 1}},
710 `Can't have key "a" in inlined map; conflicts with struct field`},
711 }
712
713 func TestMarshalErrorItems(t *testing.T) {
714 for i, item := range marshalErrorItems {
715 t.Run(strconv.Itoa(i), func(t *testing.T) {
716 data, err := bson.MarshalWithRegistry(Registry, item.obj)
717
718 assert.NotNil(t, err, "expected error")
719 assert.Nil(t, data, " expected nil data, got: %v", data)
720 })
721 }
722 }
723
724
725
726
727 type unmarshalErrorType struct {
728 obj interface{}
729 data string
730 }
731
732 var unmarshalErrorItems = []unmarshalErrorType{
733
734 {
735 obj: &structWithDupKeys{},
736 data: "\x10name\x00\x08\x00\x00\x00",
737 },
738 {
739 obj: nil,
740 data: "\xEEname\x00",
741 },
742 {
743 obj: struct{ Name bool }{},
744 data: "\x10name\x00\x08\x00\x00\x00",
745 },
746 {
747 obj: 123,
748 data: "\x10name\x00\x08\x00\x00\x00",
749 },
750 {
751 obj: nil,
752 data: "\x08\x62\x00\x02",
753 },
754
755 {
756 obj: map[bool]interface{}{true: 1},
757 data: "\x10true\x00\x01\x00\x00\x00",
758 },
759 }
760
761 func TestUnmarshalErrorItems(t *testing.T) {
762 for i, item := range unmarshalErrorItems {
763 t.Run(strconv.Itoa(i), func(t *testing.T) {
764 data := []byte(wrapInDoc(item.data))
765 var value interface{}
766 switch reflect.ValueOf(item.obj).Kind() {
767 case reflect.Map, reflect.Ptr:
768 value = makeZeroDoc(item.obj)
769 case reflect.Invalid:
770 value = bson.M{}
771 default:
772 value = item.obj
773 }
774 err := bson.UnmarshalWithRegistry(Registry, data, value)
775 assert.NotNil(t, err, "expected error")
776 })
777 }
778 }
779
780 type unmarshalRawErrorType struct {
781 obj interface{}
782 raw bson.RawValue
783 }
784
785 var unmarshalRawErrorItems = []unmarshalRawErrorType{
786
787 {
788 obj: &structWithDupKeys{},
789 raw: bson.RawValue{Type: 0x03, Value: []byte("\x10byte\x00\x08\x00\x00\x00")},
790 },
791 {
792 obj: &struct{}{},
793 raw: bson.RawValue{Type: 0xEE, Value: []byte{}},
794 },
795 {
796 obj: struct{ Name bool }{},
797 raw: bson.RawValue{Type: 0x10, Value: []byte("\x08\x00\x00\x00")},
798 },
799 {
800 obj: 123,
801 raw: bson.RawValue{Type: 0x10, Value: []byte("\x08\x00\x00\x00")},
802 },
803 }
804
805 func TestUnmarshalRawErrorItems(t *testing.T) {
806 for i, item := range unmarshalRawErrorItems {
807 t.Run(strconv.Itoa(i), func(t *testing.T) {
808 err := item.raw.UnmarshalWithRegistry(Registry, item.obj)
809 assert.NotNil(t, err, "expected error")
810 })
811 }
812 }
813
814 var corruptedData = []string{
815 "\x04\x00\x00\x00\x00",
816 "\x06\x00\x00\x00\x00",
817 "\x05\x00\x00",
818 "\x05\x00\x00\x00\xff",
819 "\x0A\x00\x00\x00\x0Aooop\x00",
820
821
822 wrapInDoc("\x04\x00\x09\x00\x00\x00\x0A\x00\x00"),
823
824
825 wrapInDoc("\x04\x00\x08\x00\x00\x00\x0A\x00\x00"),
826
827
828 wrapInDoc("\x03\x00\x08\x00\x00\x00\x0A\x00\x00"),
829
830
831
832
833
834 "\x0c\x00\x00\x00\x02x\x00\xff\xff\xff\xff\x00",
835
836
837
838
839
840 "\r\x00\x00\x00\x05x\x00\xff\xff\xff\xff\x00\x00",
841 }
842
843 func TestUnmarshalMapDocumentTooShort(t *testing.T) {
844 for i, data := range corruptedData {
845 t.Run(strconv.Itoa(i), func(t *testing.T) {
846 err := bson.UnmarshalWithRegistry(Registry, []byte(data), bson.M{})
847 assert.NotNil(t, err, "expected error, got nil")
848
849 err = bson.UnmarshalWithRegistry(Registry, []byte(data), &struct{}{})
850 assert.NotNil(t, err, "expected error, got nil")
851 })
852 }
853 }
854
855
856
857
858 var setterResult = map[string]error{}
859
860 type setterType struct {
861 Received interface{}
862 }
863
864 func (o *setterType) SetBSON(raw bson.RawValue) error {
865 rval := reflect.ValueOf(o).Elem().Field(0)
866 decoder, err := Registry.LookupDecoder(rval.Type())
867 if err != nil {
868 return err
869 }
870 if raw.Type == 0x00 {
871 raw.Type = bsontype.EmbeddedDocument
872 }
873 vr := bsonrw.NewBSONValueReader(raw.Type, raw.Value)
874 err = decoder.DecodeValue(bsoncodec.DecodeContext{Registry: Registry}, vr, rval)
875 if err != nil {
876 return err
877 }
878
879 if s, ok := o.Received.(string); ok {
880 if result, ok := setterResult[s]; ok {
881 return result
882 }
883 }
884 return nil
885 }
886
887 type ptrSetterDoc struct {
888 Field *setterType `bson:"_"`
889 }
890
891 type valSetterDoc struct {
892 Field setterType `bson:"_"`
893 }
894
895 func TestUnmarshalAllItemsWithPtrSetter(t *testing.T) {
896 for ind, item := range allItems {
897 if ind == 3 {
898 continue
899 }
900 t.Run(strconv.Itoa(ind), func(t *testing.T) {
901 for i := 0; i != 2; i++ {
902 var field *setterType
903 if i == 0 {
904 obj := &ptrSetterDoc{}
905 err := bson.UnmarshalWithRegistry(Registry, []byte(wrapInDoc(item.data)), obj)
906 assert.Nil(t, err, "expected nil error, got: %v", err)
907 field = obj.Field
908 } else {
909 obj := &valSetterDoc{}
910 err := bson.UnmarshalWithRegistry(Registry, []byte(wrapInDoc(item.data)), obj)
911 assert.Nil(t, err, "expected nil error, got: %v", err)
912 field = &obj.Field
913 }
914 if item.data == "" {
915
916 if i == 0 {
917 assert.Nil(t, field, "expected field to be nil, got: %v", field)
918 } else {
919 assert.Nil(t, field.Received, "expected field.received to be nil, got: %v", field.Received)
920 }
921 } else {
922 expected := item.obj.(bson.M)["_"]
923 assert.NotNil(t, field, "Pointer not initialized (%#v)", expected)
924
925 assert.True(t, reflect.DeepEqual(expected, field.Received), "expected field.received to be: %v, got: %v", expected, field.Received)
926 }
927 }
928 })
929 }
930 }
931
932 func TestUnmarshalWholeDocumentWithSetter(t *testing.T) {
933 obj := &setterType{}
934 err := bson.UnmarshalWithRegistry(Registry, []byte(sampleItems[0].data), obj)
935 assert.Nil(t, err, "expected nil error, got: %v", err)
936 assert.True(t, reflect.DeepEqual(bson.M{"hello": "world"}, obj.Received), "expected obj.received to be: %v, got: %v", bson.M{"hello": "world"}, obj.Received)
937 }
938
939 func TestUnmarshalSetterErrors(t *testing.T) {
940 boom := errors.New("BOOM")
941 setterResult["2"] = boom
942 defer delete(setterResult, "2")
943
944 m := map[string]*setterType{}
945 data := wrapInDoc("\x02abc\x00\x02\x00\x00\x001\x00" +
946 "\x02def\x00\x02\x00\x00\x002\x00" +
947 "\x02ghi\x00\x02\x00\x00\x003\x00")
948 err := bson.UnmarshalWithRegistry(Registry, []byte(data), m)
949 assert.NotNil(t, err, "expected UnmarshalWithRegistry error %v, got nil", boom)
950
951
952
953 expectedErr := errors.New("error decoding key def: BOOM")
954 assert.Equal(t, expectedErr.Error(), err.Error(), "expected UnmarshalWithRegistry error %v, got %v", expectedErr, err)
955
956 assert.NotNil(t, m["abc"], "expected value not to be nil")
957 assert.Nil(t, m["def"], "expected value to be nil, got: %v", m["def"])
958 assert.Nil(t, m["ghi"], "expected value to be nil, got: %v", m["ghi"])
959
960 assert.Equal(t, "1", m["abc"].Received, "expected m[\"abc\"].Received to be: %v, got: %v", "1", m["abc"].Received)
961 }
962
963 func TestDMap(t *testing.T) {
964 d := bson.D{{"a", 1}, {"b", 2}}
965 want := bson.M{"a": 1, "b": 2}
966 assert.True(t, reflect.DeepEqual(want, d.Map()), "expected: %v, got: %v", want, d.Map())
967 }
968
969 func TestUnmarshalSetterErrSetZero(t *testing.T) {
970 setterResult["foo"] = ErrSetZero
971 defer delete(setterResult, "field")
972
973 data, err := bson.MarshalWithRegistry(Registry, bson.M{"field": "foo"})
974 assert.Nil(t, err, "expected nil error, got: %v", err)
975
976 m := map[string]*setterType{}
977 err = bson.UnmarshalWithRegistry(Registry, data, m)
978 assert.Nil(t, err, "expected nil error, got: %v", err)
979
980 value, ok := m["field"]
981 assert.True(t, reflect.DeepEqual(true, ok), "expected ok to be: %v, got: %v", true, ok)
982 assert.Nil(t, value, "expected nil value, got: %v", value)
983 }
984
985
986
987
988 type typeWithGetter struct {
989 result interface{}
990 err error
991 }
992
993 func (t *typeWithGetter) GetBSON() (interface{}, error) {
994 if t == nil {
995 return "<value is nil>", nil
996 }
997 return t.result, t.err
998 }
999
1000 type docWithGetterField struct {
1001 Field *typeWithGetter `bson:"_"`
1002 }
1003
1004 func TestMarshalAllItemsWithGetter(t *testing.T) {
1005 for i, item := range allItems {
1006 if item.data == "" {
1007 continue
1008 }
1009 t.Run(strconv.Itoa(i), func(t *testing.T) {
1010 obj := &docWithGetterField{}
1011 obj.Field = &typeWithGetter{result: item.obj.(bson.M)["_"]}
1012 data, err := bson.MarshalWithRegistry(Registry, obj)
1013 assert.Nil(t, err, "expected nil error, got: %v", err)
1014 assert.Equal(t, wrapInDoc(item.data), string(data),
1015 "expected value at %v to be: %v, got: %v", i, wrapInDoc(item.data), string(data))
1016 })
1017 }
1018 }
1019
1020 func TestMarshalWholeDocumentWithGetter(t *testing.T) {
1021 obj := &typeWithGetter{result: sampleItems[0].obj}
1022 data, err := bson.MarshalWithRegistry(Registry, obj)
1023 assert.Nil(t, err, "expected nil error, got: %v", err)
1024 assert.Equal(t, sampleItems[0].data, string(data),
1025 "expected: %v, got: %v", sampleItems[0].data, string(data))
1026 }
1027
1028 func TestGetterErrors(t *testing.T) {
1029 e := errors.New("oops")
1030
1031 obj1 := &docWithGetterField{}
1032 obj1.Field = &typeWithGetter{sampleItems[0].obj, e}
1033 data, err := bson.MarshalWithRegistry(Registry, obj1)
1034 assert.Equal(t, e, err, "expected error: %v, got: %v", e, err)
1035 assert.Nil(t, data, "expected nil data, got: %v", data)
1036
1037 obj2 := &typeWithGetter{sampleItems[0].obj, e}
1038 data, err = bson.MarshalWithRegistry(Registry, obj2)
1039 assert.Equal(t, e, err, "expected error: %v, got: %v", e, err)
1040 assert.Nil(t, data, "expected nil data, got: %v", data)
1041 }
1042
1043 type intGetter int64
1044
1045 func (t intGetter) GetBSON() (interface{}, error) {
1046 return int64(t), nil
1047 }
1048
1049 type typeWithIntGetter struct {
1050 V intGetter `bson:",minsize"`
1051 }
1052
1053 func TestMarshalShortWithGetter(t *testing.T) {
1054 obj := typeWithIntGetter{42}
1055 data, err := bson.MarshalWithRegistry(Registry, obj)
1056 assert.Nil(t, err, "expected nil error, got: %v", err)
1057 m := bson.M{}
1058 err = bson.UnmarshalWithRegistry(Registry, data, &m)
1059 assert.Nil(t, err, "expected nil error, got: %v", err)
1060 assert.Equal(t, 42, m["v"], "expected m[\"v\"] to be: %v, got: %v", 42, m["v"])
1061 }
1062
1063 func TestMarshalWithGetterNil(t *testing.T) {
1064 obj := docWithGetterField{}
1065 data, err := bson.MarshalWithRegistry(Registry, obj)
1066 assert.Nil(t, err, "expected nil error, got: %v", err)
1067 m := bson.M{}
1068 err = bson.UnmarshalWithRegistry(Registry, data, &m)
1069 assert.Nil(t, err, "expected nil error, got: %v", err)
1070 want := bson.M{"_": "<value is nil>"}
1071 assert.Equal(t, want, m, "expected m[\"v\"] to be: %v, got: %v", want, m)
1072 }
1073
1074
1075
1076
1077 type crossTypeItem struct {
1078 obj1 interface{}
1079 obj2 interface{}
1080 }
1081
1082 type condStr struct {
1083 V string `bson:",omitempty"`
1084 }
1085 type condStrNS struct {
1086 V string `a:"A" bson:",omitempty" b:"B"`
1087 }
1088 type condBool struct {
1089 V bool `bson:",omitempty"`
1090 }
1091 type condInt struct {
1092 V int `bson:",omitempty"`
1093 }
1094 type condUInt struct {
1095 V uint `bson:",omitempty"`
1096 }
1097 type condFloat struct {
1098 V float64 `bson:",omitempty"`
1099 }
1100 type condIface struct {
1101 V interface{} `bson:",omitempty"`
1102 }
1103 type condPtr struct {
1104 V *bool `bson:",omitempty"`
1105 }
1106 type condSlice struct {
1107 V []string `bson:",omitempty"`
1108 }
1109 type condMap struct {
1110 V map[string]int `bson:",omitempty"`
1111 }
1112 type namedCondStr struct {
1113 V string `bson:"myv,omitempty"`
1114 }
1115 type condTime struct {
1116 V time.Time `bson:",omitempty"`
1117 }
1118 type condStruct struct {
1119 V struct{ A []int } `bson:",omitempty"`
1120 }
1121
1122 type shortInt struct {
1123 V int64 `bson:",minsize"`
1124 }
1125 type shortUint struct {
1126 V uint64 `bson:",minsize"`
1127 }
1128 type shortIface struct {
1129 V interface{} `bson:",minsize"`
1130 }
1131 type shortPtr struct {
1132 V *int64 `bson:",minsize"`
1133 }
1134 type shortNonEmptyInt struct {
1135 V int64 `bson:",minsize,omitempty"`
1136 }
1137
1138 type inlineInt struct {
1139 V struct{ A, B int } `bson:",inline"`
1140 }
1141 type inlineDupName struct {
1142 A int
1143 V struct{ A, B int } `bson:",inline"`
1144 }
1145 type inlineMap struct {
1146 A int
1147 M map[string]interface{} `bson:",inline"`
1148 }
1149 type inlineMapInt struct {
1150 A int
1151 M map[string]int `bson:",inline"`
1152 }
1153 type inlineMapMyM struct {
1154 A int
1155 M MyM `bson:",inline"`
1156 }
1157 type inlineDupMap struct {
1158 M1 map[string]interface{} `bson:",inline"`
1159 M2 map[string]interface{} `bson:",inline"`
1160 }
1161 type inlineBadKeyMap struct {
1162 M map[int]int `bson:",inline"`
1163 }
1164 type inlineUnexported struct {
1165 M map[string]interface{} `bson:",inline"`
1166 unexported `bson:",inline"`
1167 }
1168 type MStruct struct {
1169 M int `bson:"m,omitempty"`
1170 }
1171 type InlinePtrStruct struct {
1172 A int
1173 *MStruct `bson:",inline"`
1174 }
1175 type inlinePtrPtrStruct struct {
1176 B int
1177 *InlinePtrStruct `bson:",inline"`
1178 }
1179 type unexported struct {
1180 A int
1181 }
1182
1183 type getterSetterD bson.D
1184
1185 func (s getterSetterD) GetBSON() (interface{}, error) {
1186 if len(s) == 0 {
1187 return bson.D{}, nil
1188 }
1189 return bson.D(s[:len(s)-1]), nil
1190 }
1191
1192 func (s *getterSetterD) SetBSON(raw bson.RawValue) error {
1193 var doc bson.D
1194 rval := reflect.ValueOf(&doc).Elem()
1195 decoder, err := Registry.LookupDecoder(rval.Type())
1196 if err != nil {
1197 return err
1198 }
1199 if raw.Type == 0x00 {
1200 raw.Type = bsontype.EmbeddedDocument
1201 }
1202 vr := bsonrw.NewBSONValueReader(raw.Type, raw.Value)
1203 err = decoder.DecodeValue(bsoncodec.DecodeContext{Registry: Registry}, vr, rval)
1204 if err != nil {
1205 return err
1206 }
1207 doc = append(doc, bson.E{"suffix", true})
1208 *s = getterSetterD(doc)
1209 return err
1210 }
1211
1212 type getterSetterInt int
1213
1214 func (i getterSetterInt) GetBSON() (interface{}, error) {
1215 return bson.D{{"a", int(i)}}, nil
1216 }
1217
1218 func (i *getterSetterInt) SetBSON(raw bson.RawValue) error {
1219 var doc struct{ A int }
1220 rval := reflect.ValueOf(&doc).Elem()
1221 decoder, err := Registry.LookupDecoder(rval.Type())
1222 if err != nil {
1223 return err
1224 }
1225 if raw.Type == 0x00 {
1226 raw.Type = bsontype.EmbeddedDocument
1227 }
1228 vr := bsonrw.NewBSONValueReader(raw.Type, raw.Value)
1229 err = decoder.DecodeValue(bsoncodec.DecodeContext{Registry: Registry}, vr, rval)
1230 if err != nil {
1231 return err
1232 }
1233 *i = getterSetterInt(doc.A)
1234 return err
1235 }
1236
1237 type ifaceType interface {
1238 Hello()
1239 }
1240
1241 type ifaceSlice []ifaceType
1242
1243 func (s *ifaceSlice) SetBSON(raw bson.RawValue) error {
1244 var ns []int
1245 rval := reflect.ValueOf(&ns).Elem()
1246 decoder, err := Registry.LookupDecoder(rval.Type())
1247 if err != nil {
1248 return err
1249 }
1250 vr := bsonrw.NewBSONValueReader(raw.Type, raw.Value)
1251 err = decoder.DecodeValue(bsoncodec.DecodeContext{Registry: Registry}, vr, rval)
1252 if err != nil {
1253 return err
1254 }
1255 *s = make(ifaceSlice, ns[0])
1256 return nil
1257 }
1258
1259 func (s ifaceSlice) GetBSON() (interface{}, error) {
1260 return []int{len(s)}, nil
1261 }
1262
1263 type (
1264 MyString string
1265 MyBytes []byte
1266 MyBool bool
1267 MyD bson.D
1268 MyRawD bson.Raw
1269 MyM map[string]interface{}
1270 )
1271
1272 var (
1273 truevar = true
1274 falsevar = false
1275
1276 int64var = int64(42)
1277 int64ptr = &int64var
1278 intvar = int(42)
1279
1280 gsintvar = getterSetterInt(42)
1281 )
1282
1283 func parseURL(s string) *url.URL {
1284 u, err := url.Parse(s)
1285 if err != nil {
1286 panic(err)
1287 }
1288 return u
1289 }
1290
1291
1292
1293
1294
1295 var twoWayCrossItems = []crossTypeItem{
1296
1297 {&struct{ I int }{42}, &struct{ I int8 }{42}},
1298 {&struct{ I int }{42}, &struct{ I int32 }{42}},
1299 {&struct{ I int }{42}, &struct{ I int64 }{42}},
1300 {&struct{ I int8 }{42}, &struct{ I int32 }{42}},
1301 {&struct{ I int8 }{42}, &struct{ I int64 }{42}},
1302 {&struct{ I int32 }{42}, &struct{ I int64 }{42}},
1303
1304
1305 {&struct{ I uint }{42}, &struct{ I uint8 }{42}},
1306 {&struct{ I uint }{42}, &struct{ I uint32 }{42}},
1307 {&struct{ I uint }{42}, &struct{ I uint64 }{42}},
1308 {&struct{ I uint8 }{42}, &struct{ I uint32 }{42}},
1309 {&struct{ I uint8 }{42}, &struct{ I uint64 }{42}},
1310 {&struct{ I uint32 }{42}, &struct{ I uint64 }{42}},
1311
1312
1313 {&struct{ I float32 }{42}, &struct{ I float64 }{42}},
1314
1315
1316 {&struct{ I uint }{42}, &struct{ I int }{42}},
1317 {&struct{ I uint }{42}, &struct{ I int8 }{42}},
1318 {&struct{ I uint }{42}, &struct{ I int32 }{42}},
1319 {&struct{ I uint }{42}, &struct{ I int64 }{42}},
1320 {&struct{ I uint8 }{42}, &struct{ I int }{42}},
1321 {&struct{ I uint8 }{42}, &struct{ I int8 }{42}},
1322 {&struct{ I uint8 }{42}, &struct{ I int32 }{42}},
1323 {&struct{ I uint8 }{42}, &struct{ I int64 }{42}},
1324 {&struct{ I uint32 }{42}, &struct{ I int }{42}},
1325 {&struct{ I uint32 }{42}, &struct{ I int8 }{42}},
1326 {&struct{ I uint32 }{42}, &struct{ I int32 }{42}},
1327 {&struct{ I uint32 }{42}, &struct{ I int64 }{42}},
1328 {&struct{ I uint64 }{42}, &struct{ I int }{42}},
1329 {&struct{ I uint64 }{42}, &struct{ I int8 }{42}},
1330 {&struct{ I uint64 }{42}, &struct{ I int32 }{42}},
1331 {&struct{ I uint64 }{42}, &struct{ I int64 }{42}},
1332
1333
1334 {&struct{ I int }{42}, &struct{ I float64 }{42}},
1335
1336
1337 {&struct{ I int }{1}, &struct{ I bool }{true}},
1338 {&struct{ I int }{0}, &struct{ I bool }{false}},
1339
1340
1341 {&struct{ I uint }{42}, &struct{ I float64 }{42}},
1342
1343
1344 {&struct{ I uint }{1}, &struct{ I bool }{true}},
1345 {&struct{ I uint }{0}, &struct{ I bool }{false}},
1346
1347
1348 {&struct{ I float64 }{1}, &struct{ I bool }{true}},
1349 {&struct{ I float64 }{0}, &struct{ I bool }{false}},
1350
1351
1352 {&struct{ S []byte }{[]byte("abc")}, &struct{ S string }{"abc"}},
1353 {&struct{ S []byte }{[]byte("def")}, &struct{ S primitive.Symbol }{"def"}},
1354 {&struct{ S string }{"ghi"}, &struct{ S primitive.Symbol }{"ghi"}},
1355
1356 {&struct{ S string }{"0123456789ab"},
1357 &struct{ S primitive.ObjectID }{primitive.ObjectID{0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62}}},
1358
1359
1360 {&struct {
1361 A struct {
1362 B, C int
1363 }
1364 }{struct{ B, C int }{1, 2}},
1365 map[string]map[string]int{"a": {"b": 1, "c": 2}}},
1366
1367 {&struct{ A primitive.Symbol }{"abc"}, map[string]string{"a": "abc"}},
1368 {&struct{ A primitive.Symbol }{"abc"}, map[string][]byte{"a": []byte("abc")}},
1369 {&struct{ A []byte }{[]byte("abc")}, map[string]string{"a": "abc"}},
1370 {&struct{ A uint }{42}, map[string]int{"a": 42}},
1371 {&struct{ A uint }{42}, map[string]float64{"a": 42}},
1372 {&struct{ A uint }{1}, map[string]bool{"a": true}},
1373 {&struct{ A int }{42}, map[string]uint{"a": 42}},
1374 {&struct{ A int }{42}, map[string]float64{"a": 42}},
1375 {&struct{ A int }{1}, map[string]bool{"a": true}},
1376 {&struct{ A float64 }{42}, map[string]float32{"a": 42}},
1377 {&struct{ A float64 }{42}, map[string]int{"a": 42}},
1378 {&struct{ A float64 }{42}, map[string]uint{"a": 42}},
1379 {&struct{ A float64 }{1}, map[string]bool{"a": true}},
1380 {&struct{ A bool }{true}, map[string]int{"a": 1}},
1381 {&struct{ A bool }{true}, map[string]uint{"a": 1}},
1382 {&struct{ A bool }{true}, map[string]float64{"a": 1}},
1383 {&struct{ A **byte }{&byteptr}, map[string]byte{"a": 8}},
1384
1385
1386 {&struct{ URL *url.URL }{parseURL("h://e.c/p")}, map[string]string{"url": "h://e.c/p"}},
1387 {&struct{ URL url.URL }{*parseURL("h://e.c/p")}, map[string]string{"url": "h://e.c/p"}},
1388
1389
1390 {&struct{ S []int }{[]int{1, 2, 3}}, map[string][]int{"s": {1, 2, 3}}},
1391 {&struct{ S *[]int }{&[]int{1, 2, 3}}, map[string][]int{"s": {1, 2, 3}}},
1392
1393
1394 {&condBool{true}, map[string]bool{"v": true}},
1395 {&condBool{}, map[string]bool{}},
1396 {&condInt{1}, map[string]int{"v": 1}},
1397 {&condInt{}, map[string]int{}},
1398 {&condUInt{1}, map[string]uint{"v": 1}},
1399 {&condUInt{}, map[string]uint{}},
1400 {&condFloat{}, map[string]int{}},
1401 {&condStr{"yo"}, map[string]string{"v": "yo"}},
1402 {&condStr{}, map[string]string{}},
1403 {&condStrNS{"yo"}, map[string]string{"v": "yo"}},
1404 {&condStrNS{}, map[string]string{}},
1405 {&condSlice{[]string{"yo"}}, map[string][]string{"v": {"yo"}}},
1406 {&condSlice{}, map[string][]string{}},
1407 {&condMap{map[string]int{"k": 1}}, bson.M{"v": bson.M{"k": 1}}},
1408 {&condMap{}, map[string][]string{}},
1409 {&condIface{"yo"}, map[string]string{"v": "yo"}},
1410 {&condIface{""}, map[string]string{"v": ""}},
1411 {&condIface{}, map[string]string{}},
1412 {&condPtr{&truevar}, map[string]bool{"v": true}},
1413 {&condPtr{&falsevar}, map[string]bool{"v": false}},
1414 {&condPtr{}, map[string]string{}},
1415
1416 {&condTime{time.Unix(123456789, 123e6).UTC()}, map[string]time.Time{"v": time.Unix(123456789, 123e6).UTC()}},
1417 {&condTime{}, map[string]string{}},
1418
1419 {&condStruct{struct{ A []int }{[]int{1}}}, bson.M{"v": bson.M{"a": []interface{}{1}}}},
1420 {&condStruct{struct{ A []int }{}}, bson.M{}},
1421
1422
1423
1424
1425 {&namedCondStr{"yo"}, map[string]string{"myv": "yo"}},
1426 {&namedCondStr{}, map[string]string{}},
1427
1428 {&shortInt{1}, map[string]interface{}{"v": 1}},
1429 {&shortInt{1 << 30}, map[string]interface{}{"v": 1 << 30}},
1430 {&shortInt{1 << 31}, map[string]interface{}{"v": int64(1 << 31)}},
1431 {&shortUint{1 << 30}, map[string]interface{}{"v": 1 << 30}},
1432 {&shortUint{1 << 31}, map[string]interface{}{"v": int64(1 << 31)}},
1433 {&shortIface{int64(1) << 31}, map[string]interface{}{"v": int64(1 << 31)}},
1434 {&shortPtr{int64ptr}, map[string]interface{}{"v": intvar}},
1435
1436 {&shortNonEmptyInt{1}, map[string]interface{}{"v": 1}},
1437 {&shortNonEmptyInt{1 << 31}, map[string]interface{}{"v": int64(1 << 31)}},
1438 {&shortNonEmptyInt{}, map[string]interface{}{}},
1439
1440 {&inlineInt{struct{ A, B int }{1, 2}}, map[string]interface{}{"a": 1, "b": 2}},
1441 {&inlineMap{A: 1, M: map[string]interface{}{"b": 2}}, map[string]interface{}{"a": 1, "b": 2}},
1442 {&inlineMap{A: 1, M: nil}, map[string]interface{}{"a": 1}},
1443 {&inlineMapInt{A: 1, M: map[string]int{"b": 2}}, map[string]int{"a": 1, "b": 2}},
1444 {&inlineMapInt{A: 1, M: nil}, map[string]int{"a": 1}},
1445 {&inlineMapMyM{A: 1, M: MyM{"b": MyM{"c": 3}}}, map[string]interface{}{"a": 1, "b": map[string]interface{}{"c": 3}}},
1446 {&inlineUnexported{M: map[string]interface{}{"b": 1}, unexported: unexported{A: 2}}, map[string]interface{}{"b": 1, "a": 2}},
1447
1448
1449 {&struct{ B []byte }{[]byte("abc")}, map[string]primitive.Binary{"b": {Data: []byte("abc")}}},
1450
1451
1452 {&struct{ B MyBytes }{[]byte("abc")}, &map[string]string{"b": "abc"}},
1453 {&struct{ B MyBytes }{[]byte{}}, &map[string]string{"b": ""}},
1454
1455 {&struct{ B []byte }{[]byte("abc")}, &map[string]MyBytes{"b": []byte("abc")}},
1456
1457
1458 {&struct{ B MyBool }{true}, map[string]bool{"b": true}},
1459 {&struct{ B MyBool }{}, map[string]bool{"b": false}},
1460
1461 {&struct{ B bool }{}, map[string]MyBool{"b": false}},
1462
1463
1464 {&struct{ V [2]int }{[...]int{1, 2}}, map[string][2]int{"v": {1, 2}}},
1465 {&struct{ V [2]byte }{[...]byte{1, 2}}, map[string][2]byte{"v": {1, 2}}},
1466
1467
1468 {&struct{ V time.Time }{}, map[string]interface{}{"v": time.Time{}}},
1469
1470
1471 {&struct{ V time.Time }{time.Unix(-62135596799, 1e6).UTC()},
1472 map[string]interface{}{"v": time.Unix(-62135596799, 1e6).UTC()}},
1473
1474
1475 {&bson.D{{"a", bson.D{{"b", 1}, {"c", 2}}}}, &bson.D{{"a", bson.D{{"b", 1}, {"c", 2}}}}},
1476 {&bson.D{{"a", bson.D{{"b", 1}, {"c", 2}}}}, &MyD{{"a", MyD{{"b", 1}, {"c", 2}}}}},
1477 {&struct{ V MyD }{MyD{{"a", 1}}}, &bson.D{{"v", bson.D{{"a", 1}}}}},
1478
1479
1480 {&bson.M{"a": bson.M{"b": 1, "c": 2}}, MyM{"a": MyM{"b": 1, "c": 2}}},
1481 {&bson.M{"a": bson.M{"b": 1, "c": 2}}, map[string]interface{}{"a": map[string]interface{}{"b": 1, "c": 2}}},
1482
1483
1484 {&bson.M{"a": bson.M{"b": 1, "c": 2}}, map[MyString]interface{}{"a": map[MyString]interface{}{"b": 1, "c": 2}}},
1485
1486
1487 {&struct{ N json.Number }{"5"}, map[string]interface{}{"n": int64(5)}},
1488 {&struct{ N json.Number }{"5.05"}, map[string]interface{}{"n": 5.05}},
1489 {&struct{ N json.Number }{"9223372036854776000"}, map[string]interface{}{"n": float64(1 << 63)}},
1490
1491
1492 {&bson.D{{"a", 1}}, &getterSetterD{{"a", 1}, {"suffix", true}}},
1493 {&bson.D{{"a", 42}}, &gsintvar},
1494
1495
1496 {&struct{ V ifaceSlice }{ifaceSlice{nil, nil, nil}}, bson.M{"v": []interface{}{3}}},
1497 }
1498
1499
1500 var oneWayCrossItems = []crossTypeItem{
1501
1502 {&shortIface{int64(1) << 30}, map[string]interface{}{"v": 1 << 30}},
1503
1504
1505 {&struct {
1506 V struct{ v time.Time } `bson:",omitempty"`
1507 }{}, map[string]interface{}{}},
1508 }
1509
1510 func testCrossPair(t *testing.T, dump interface{}, load interface{}) {
1511 zero := makeZeroDoc(load)
1512 data, err := bson.MarshalWithRegistry(Registry, dump)
1513 assert.Nil(t, err, "expected nil error, got: %v", err)
1514 err = bson.UnmarshalWithRegistry(Registry, data, zero)
1515 assert.Nil(t, err, "expected nil error, got: %v", err)
1516
1517 assert.True(t, reflect.DeepEqual(load, zero), "expected: %v, got: %v", load, zero)
1518 }
1519
1520 func TestTwoWayCrossPairs(t *testing.T) {
1521 for i, item := range twoWayCrossItems {
1522 t.Run(strconv.Itoa(i), func(t *testing.T) {
1523 testCrossPair(t, item.obj1, item.obj2)
1524 testCrossPair(t, item.obj2, item.obj1)
1525 })
1526 }
1527 }
1528
1529 func TestOneWayCrossPairs(t *testing.T) {
1530 for i, item := range oneWayCrossItems {
1531 t.Run(strconv.Itoa(i), func(t *testing.T) {
1532 testCrossPair(t, item.obj1, item.obj2)
1533 })
1534 }
1535 }
1536
1537
1538
1539
1540 type jsonType struct {
1541 ID primitive.ObjectID
1542 }
1543
1544 func objectIDHex(s string) primitive.ObjectID {
1545 oid, _ := primitive.ObjectIDFromHex(s)
1546 return oid
1547 }
1548
1549 var jsonIDTests = []struct {
1550 value jsonType
1551 json string
1552 marshal bool
1553 unmarshal bool
1554 error string
1555 }{{
1556 value: jsonType{ID: objectIDHex("4d88e15b60f486e428412dc9")},
1557 json: `{"ID":"4d88e15b60f486e428412dc9"}`,
1558 marshal: true,
1559 unmarshal: true,
1560 }, {
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571 json: `{"Id":"4d88e15b60f486e428412dc9A"}`,
1572 error: `invalid ObjectId in JSON: "4d88e15b60f486e428412dc9A"`,
1573 marshal: false,
1574 unmarshal: true,
1575 }, {
1576 json: `{"Id":"4d88e15b60f486e428412dcZ"}`,
1577 error: `invalid ObjectId in JSON: "4d88e15b60f486e428412dcZ" .*`,
1578 marshal: false,
1579 unmarshal: true,
1580 }}
1581
1582 func TestObjectIdJSONMarshaling(t *testing.T) {
1583 for i, test := range jsonIDTests {
1584 t.Run(strconv.Itoa(i), func(t *testing.T) {
1585 if test.marshal {
1586 data, err := json.Marshal(&test.value)
1587 if test.error == "" {
1588 assert.Nil(t, err, "expected nil error, got: %v", err)
1589 assert.Equal(t, test.json, string(data), "expected: %v, got: %v", test.json, string(data))
1590 } else {
1591 assert.NotNil(t, err, "expected a marshal error")
1592 }
1593 }
1594
1595 if test.unmarshal {
1596 var value jsonType
1597 err := json.Unmarshal([]byte(test.json), &value)
1598 if test.error == "" {
1599 assert.Nil(t, err, "expected nil error, got: %v", err)
1600 assert.True(t, reflect.DeepEqual(test.value, value), "expected: %v, got: %v", test.value, value)
1601 } else {
1602 assert.NotNil(t, err, "expected a unmarshal error")
1603 }
1604 }
1605 })
1606 }
1607 }
1608
1609 func TestMarshalNotRespectNil(t *testing.T) {
1610 type T struct {
1611 Slice []int
1612 BSlice []byte
1613 Map map[string]interface{}
1614 }
1615
1616 testStruct1 := T{}
1617
1618 assert.Nil(t, testStruct1.Slice, "expected nil slice, got: %v", testStruct1.Slice)
1619 assert.Nil(t, testStruct1.BSlice, "expected nil byte slice, got: %v", testStruct1.BSlice)
1620 assert.Nil(t, testStruct1.Map, "expected nil map, got: %v", testStruct1.Map)
1621
1622 b, _ := bson.MarshalWithRegistry(Registry, testStruct1)
1623
1624 testStruct2 := T{}
1625
1626 _ = bson.UnmarshalWithRegistry(Registry, b, &testStruct2)
1627
1628 assert.NotNil(t, testStruct2.Slice, "expected non-nil slice")
1629 assert.NotNil(t, testStruct2.BSlice, "expected non-nil byte slice")
1630 assert.NotNil(t, testStruct2.Map, "expected non-nil map")
1631 }
1632
1633 func TestMarshalRespectNil(t *testing.T) {
1634 type T struct {
1635 Slice []int
1636 SlicePtr *[]int
1637 Ptr *int
1638 Map map[string]interface{}
1639 MapPtr *map[string]interface{}
1640 }
1641
1642 testStruct1 := T{}
1643
1644 assert.Nil(t, testStruct1.Slice, "expected nil slice, got: %v", testStruct1.Slice)
1645 assert.Nil(t, testStruct1.SlicePtr, "expected nil slice ptr, got: %v", testStruct1.SlicePtr)
1646 assert.Nil(t, testStruct1.Map, "expected nil map, got: %v", testStruct1.Map)
1647 assert.Nil(t, testStruct1.MapPtr, "expected nil map ptr, got: %v", testStruct1.MapPtr)
1648 assert.Nil(t, testStruct1.Ptr, "expected nil ptr, got: %v", testStruct1.Ptr)
1649
1650 b, _ := bson.MarshalWithRegistry(RegistryRespectNilValues, testStruct1)
1651
1652 testStruct2 := T{}
1653
1654 _ = bson.UnmarshalWithRegistry(RegistryRespectNilValues, b, &testStruct2)
1655
1656 assert.Nil(t, testStruct2.Slice, "expected nil slice, got: %v", testStruct2.Slice)
1657 assert.Nil(t, testStruct2.SlicePtr, "expected nil slice ptr, got: %v", testStruct2.SlicePtr)
1658 assert.Nil(t, testStruct2.Map, "expected nil map, got: %v", testStruct2.Map)
1659 assert.Nil(t, testStruct2.MapPtr, "expected nil map ptr, got: %v", testStruct2.MapPtr)
1660 assert.Nil(t, testStruct2.Ptr, "expected nil ptr, got: %v", testStruct2.Ptr)
1661
1662 testStruct1 = T{
1663 Slice: []int{},
1664 SlicePtr: &[]int{},
1665 Map: map[string]interface{}{},
1666 MapPtr: &map[string]interface{}{},
1667 }
1668
1669 assert.NotNil(t, testStruct1.Slice, "expected non-nil slice")
1670 assert.NotNil(t, testStruct1.SlicePtr, "expected non-nil slice ptr")
1671 assert.NotNil(t, testStruct1.Map, "expected non-nil map")
1672 assert.NotNil(t, testStruct1.MapPtr, "expected non-nil map ptr")
1673
1674 b, _ = bson.MarshalWithRegistry(RegistryRespectNilValues, testStruct1)
1675
1676 testStruct2 = T{}
1677
1678 _ = bson.UnmarshalWithRegistry(RegistryRespectNilValues, b, &testStruct2)
1679
1680 assert.NotNil(t, testStruct2.Slice, "expected non-nil slice")
1681 assert.NotNil(t, testStruct2.SlicePtr, "expected non-nil slice ptr")
1682 assert.NotNil(t, testStruct2.Map, "expected non-nil map")
1683 assert.NotNil(t, testStruct2.MapPtr, "expected non-nil map ptr")
1684 }
1685
1686
1687 type Inner struct {
1688 ID string
1689 }
1690
1691 type InlineLoop struct {
1692 Inner `bson:",inline"`
1693 Value string
1694 Draft *InlineLoop `bson:",omitempty"`
1695 }
1696
1697 func TestInlineWithPointerToSelf(t *testing.T) {
1698 x1 := InlineLoop{
1699 Inner: Inner{
1700 ID: "1",
1701 },
1702 Value: "",
1703 }
1704
1705 bytes, err := bson.MarshalWithRegistry(Registry, x1)
1706 assert.Nil(t, err, "expected nil error, got: %v", err)
1707
1708 var x2 InlineLoop
1709 err = bson.UnmarshalWithRegistry(Registry, bytes, &x2)
1710 assert.Nil(t, err, "expected nil error, got: %v", err)
1711 assert.Equal(t, x1, x2, "Expected %v, got %v", x1, x2)
1712 }
1713
View as plain text