...

Source file src/go.mongodb.org/mongo-driver/bson/mgocompat/bson_test.go

Documentation: go.mongodb.org/mongo-driver/bson/mgocompat

     1  // Copyright (C) MongoDB, Inc. 2017-present.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"); you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
     6  //
     7  // Based on gopkg.in/mgo.v2/bson by Gustavo Niemeyer
     8  // See THIRD-PARTY-NOTICES for original license terms.
     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  // Wrap up the document elements contained in data, prepending the int32
    32  // length of the data, and appending the '\x00' value closing the document.
    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  // Samples from bsonspec.org:
    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  // Every type, ordered by the type flag. These are not wrapped with the
   108  // length and last \x00 from the document. wrapInDoc() computes them.
   109  // Note that all of them should be supported as two-way conversions.
   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{}}, // Obsolete, but still seen in the wild.
   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"}, //technically this is not the same as the original mgo test
   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()}, // Note the NS <=> MS conversion.
   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}} // true
   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  		{ // go deeper
   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  			// nil embed struct
   257  			In:  &InlinePtrStruct{A: 3},
   258  			Out: bson.M{"a": 3},
   259  		},
   260  		{
   261  			// nil embed struct
   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  // Some one way marshaling operations which would unmarshal differently.
   282  
   283  var js = primitive.JavaScript("code")
   284  
   285  var oneWayMarshalItems = []testItemType{
   286  	// These are being passed as pointers, and will unmarshal as values.
   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  	// There's no float32 type in BSON.  Will encode as a float64.
   300  	{bson.M{"": float32(5.05)},
   301  		"\x01\x00\x00\x00\x00@33\x14@"},
   302  
   303  	// The array will be unmarshaled as a slice instead.
   304  	{bson.M{"": [2]bool{true, false}},
   305  		"\x04\x00\r\x00\x00\x00\x080\x00\x01\x081\x00\x00\x00"},
   306  
   307  	// The typed slice will be unmarshaled as []interface{}.
   308  	{bson.M{"": []bool{true, false}},
   309  		"\x04\x00\r\x00\x00\x00\x080\x00\x01\x081\x00\x00\x00"},
   310  
   311  	// Will unmarshal as a []byte.
   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  	// No way to preserve the type information here. We might encode as a zero
   318  	// value, but this would mean that pointer values in structs wouldn't be
   319  	// able to correctly distinguish between unset and set to the zero value.
   320  	{bson.M{"": (*byte)(nil)},
   321  		"\x0A\x00"},
   322  
   323  	// No int types smaller than int32 in BSON. Could encode this as a char,
   324  	// but it would still be ambiguous, take more, and be awkward in Go when
   325  	// loaded without typing information.
   326  	{bson.M{"": byte(8)},
   327  		"\x10\x00\x08\x00\x00\x00"},
   328  
   329  	// There are no unsigned types in BSON.  Will unmarshal as int32 or int64.
   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  	// This will unmarshal as int.
   338  	{bson.M{"": int32(258)},
   339  		"\x10\x00\x02\x01\x00\x00"},
   340  
   341  	// That's a special case. The unsigned value is too large for an int32,
   342  	// so an int64 is used instead.
   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  // Two-way tests for user-defined structures using the samples
   362  // from bsonspec.org.
   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  // Generic two-way struct marshaling tests.
   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  	// The order of the dumped fields should be the same in the struct.
   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  	// Byte arrays.
   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  // func TestUnmarshalRawNil(t *testing.T) {
   567  // 	// Regression test: shouldn't try to nil out the pointer itself,
   568  // 	// as it's not settable.
   569  // 	raw := bson.RawValue{Type: 0x0A, Value: []byte{}}
   570  // 	err := raw.UnmarshalWithRegistry(Registry, &struct{}{})
   571  // 	assert.Nil(t, err, "expected nil error, got: %v", err)
   572  // }
   573  
   574  // --------------------------------------------------------------------------
   575  // One-way marshaling tests.
   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  	// Ordered document dump.  Will unmarshal as a dictionary by default.
   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  	// Marshalling a Raw document does nothing.
   600  	// {bson.RawValue{Type: 0x03, Value: []byte(wrapInDoc("anything"))},
   601  	// 	"anything"},
   602  	// {bson.RawValue{Value: []byte(wrapInDoc("anything"))},
   603  	// 	"anything"},
   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  // One-way unmarshaling tests.
   618  
   619  type intAlias int
   620  
   621  var unmarshalItems = []testItemType{
   622  	// Field is private.  Should not attempt to unmarshal it.
   623  	{&struct{ priv byte }{},
   624  		"\x10priv\x00\x08\x00\x00\x00"},
   625  
   626  	// Ignore non-existing field.
   627  	{&struct{ Byte byte }{9},
   628  		"\x10boot\x00\x08\x00\x00\x00" + "\x10byte\x00\x09\x00\x00\x00"},
   629  
   630  	// Do not unmarshal on ignored field.
   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  	// Ordered document.
   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  	// Raw document.
   641  	// {&bson.RawValue{Type: 0x03, Value: []byte(wrapInDoc("\x10byte\x00\x08\x00\x00\x00"))},
   642  	// 	"\x10byte\x00\x08\x00\x00\x00"},
   643  
   644  	// Decode old binary.
   645  	{bson.M{"_": []byte("old")},
   646  		"\x05_\x00\x07\x00\x00\x00\x02\x03\x00\x00\x00old"},
   647  
   648  	// Decode old binary without length. According to the spec, this shouldn't happen.
   649  	{bson.M{"_": []byte("old")},
   650  		"\x05_\x00\x03\x00\x00\x00\x02old"},
   651  
   652  	// int key maps
   653  	{map[int]string{10: "s"},
   654  		"\x0210\x00\x02\x00\x00\x00s\x00"},
   655  
   656  	//// event if type is alias to int
   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  	// Nil is the default value, so we need to ensure it's indeed being set.
   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  // Marshalling error cases.
   682  
   683  type structWithDupKeys struct {
   684  	Name  byte
   685  	Other byte `bson:"name"` // Tag should precede.
   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  // Unmarshalling error cases.
   726  
   727  type unmarshalErrorType struct {
   728  	obj  interface{}
   729  	data string
   730  }
   731  
   732  var unmarshalErrorItems = []unmarshalErrorType{
   733  	// Tag name conflicts with existing parameter.
   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  	// Non-string and not numeric map key.
   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  	// Tag name conflicts with existing parameter.
   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",         // Document shorter than minimum
   816  	"\x06\x00\x00\x00\x00",         // Not enough data
   817  	"\x05\x00\x00",                 // Broken length
   818  	"\x05\x00\x00\x00\xff",         // Corrupted termination
   819  	"\x0A\x00\x00\x00\x0Aooop\x00", // Unfinished C string
   820  
   821  	// Array end past end of string (s[2]=0x07 is correct)
   822  	wrapInDoc("\x04\x00\x09\x00\x00\x00\x0A\x00\x00"),
   823  
   824  	// Array end within string, but past acceptable.
   825  	wrapInDoc("\x04\x00\x08\x00\x00\x00\x0A\x00\x00"),
   826  
   827  	// Document end within string, but past acceptable.
   828  	wrapInDoc("\x03\x00\x08\x00\x00\x00\x0A\x00\x00"),
   829  
   830  	// // String with corrupted end.
   831  	// wrapInDoc("\x02\x00\x03\x00\x00\x00yo\xFF"),
   832  
   833  	// String with negative length (issue #116).
   834  	"\x0c\x00\x00\x00\x02x\x00\xff\xff\xff\xff\x00",
   835  
   836  	// // String with zero length (must include trailing '\x00')
   837  	// "\x0c\x00\x00\x00\x02x\x00\x00\x00\x00\x00\x00",
   838  
   839  	// Binary with negative length.
   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  // Setter test cases.
   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  					// Nothing to unmarshal. Should be untouched.
   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  	// It's not possible to generate the actual expected error here because it's an *UnmarshalError, which is defined
   952  	// in bsoncodec and only contains unexported fields.
   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  // Getter test cases.
   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  // Cross-type conversion tests.
  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  // That's a pretty fun test.  It will dump the first item, generate a zero
  1292  // value equivalent to the second one, load the dumped data onto it, and then
  1293  // verify that the resulting value is deep-equal to the untouched second value.
  1294  // Then, it will do the same in the *opposite* direction!
  1295  var twoWayCrossItems = []crossTypeItem{
  1296  	// int<=>int
  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  	// uint<=>uint
  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  	// float32<=>float64
  1313  	{&struct{ I float32 }{42}, &struct{ I float64 }{42}},
  1314  
  1315  	// int<=>uint
  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  	// int <=> float
  1334  	{&struct{ I int }{42}, &struct{ I float64 }{42}},
  1335  
  1336  	// int <=> bool
  1337  	{&struct{ I int }{1}, &struct{ I bool }{true}},
  1338  	{&struct{ I int }{0}, &struct{ I bool }{false}},
  1339  
  1340  	// uint <=> float64
  1341  	{&struct{ I uint }{42}, &struct{ I float64 }{42}},
  1342  
  1343  	// uint <=> bool
  1344  	{&struct{ I uint }{1}, &struct{ I bool }{true}},
  1345  	{&struct{ I uint }{0}, &struct{ I bool }{false}},
  1346  
  1347  	// float64 <=> bool
  1348  	{&struct{ I float64 }{1}, &struct{ I bool }{true}},
  1349  	{&struct{ I float64 }{0}, &struct{ I bool }{false}},
  1350  
  1351  	// string <=> string and string <=> []byte
  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  	// map <=> struct
  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  	// url.URL <=> string
  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  	// Slices
  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  	// Conditionals
  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  	// {&condRaw{bson.RawValue{Type: 0x0A, Value: []byte{}}},bson.M{"v": nil}},
  1423  	// {&condRaw{bson.RawValue{Type: 0x00}}, bson.M{}},
  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  	// []byte <=> Binary
  1449  	{&struct{ B []byte }{[]byte("abc")}, map[string]primitive.Binary{"b": {Data: []byte("abc")}}},
  1450  
  1451  	// []byte <=> MyBytes
  1452  	{&struct{ B MyBytes }{[]byte("abc")}, &map[string]string{"b": "abc"}},
  1453  	{&struct{ B MyBytes }{[]byte{}}, &map[string]string{"b": ""}},
  1454  	// {&struct{ B MyBytes }{}, &map[string]bool{}},
  1455  	{&struct{ B []byte }{[]byte("abc")}, &map[string]MyBytes{"b": []byte("abc")}},
  1456  
  1457  	// bool <=> MyBool
  1458  	{&struct{ B MyBool }{true}, map[string]bool{"b": true}},
  1459  	{&struct{ B MyBool }{}, map[string]bool{"b": false}},
  1460  	// {&struct{ B MyBool }{}, map[string]string{}},
  1461  	{&struct{ B bool }{}, map[string]MyBool{"b": false}},
  1462  
  1463  	// arrays
  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  	// zero time
  1468  	{&struct{ V time.Time }{}, map[string]interface{}{"v": time.Time{}}},
  1469  
  1470  	// zero time + 1 second + 1 millisecond; overflows int64 as nanoseconds
  1471  	{&struct{ V time.Time }{time.Unix(-62135596799, 1e6).UTC()},
  1472  		map[string]interface{}{"v": time.Unix(-62135596799, 1e6).UTC()}},
  1473  
  1474  	// bson.D <=> []DocElem
  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  	// bson.M <=> map
  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  	// bson.M <=> map[MyString]
  1484  	{&bson.M{"a": bson.M{"b": 1, "c": 2}}, map[MyString]interface{}{"a": map[MyString]interface{}{"b": 1, "c": 2}}},
  1485  
  1486  	// json.Number <=> int64, float64
  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  	// bson.D <=> non-struct getter/setter
  1492  	{&bson.D{{"a", 1}}, &getterSetterD{{"a", 1}, {"suffix", true}}},
  1493  	{&bson.D{{"a", 42}}, &gsintvar},
  1494  
  1495  	// Interface slice setter.
  1496  	{&struct{ V ifaceSlice }{ifaceSlice{nil, nil, nil}}, bson.M{"v": []interface{}{3}}},
  1497  }
  1498  
  1499  // Same thing, but only one way (obj1 => obj2).
  1500  var oneWayCrossItems = []crossTypeItem{
  1501  	// Would get decoded into a int32 too in the opposite direction.
  1502  	{&shortIface{int64(1) << 30}, map[string]interface{}{"v": 1 << 30}},
  1503  
  1504  	// Ensure omitempty on struct with private fields works properly.
  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  // ObjectId JSON marshalling.
  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  	// 	value:     jsonType{},
  1562  	// 	json:      `{"Id":""}`,
  1563  	// 	marshal:   true,
  1564  	// 	unmarshal: true,
  1565  	// }, {
  1566  	// 	value:     jsonType{},
  1567  	// 	json:      `{"Id":null}`,
  1568  	// 	marshal:   false,
  1569  	// 	unmarshal: true,
  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  // Our mgocompat.Registry tests
  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