...

Source file src/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders_test.go

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

     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  package bsoncodec
     8  
     9  import (
    10  	"encoding/json"
    11  	"errors"
    12  	"fmt"
    13  	"math"
    14  	"net/url"
    15  	"reflect"
    16  	"strings"
    17  	"testing"
    18  	"time"
    19  
    20  	"github.com/google/go-cmp/cmp"
    21  	"go.mongodb.org/mongo-driver/bson/bsonrw"
    22  	"go.mongodb.org/mongo-driver/bson/bsonrw/bsonrwtest"
    23  	"go.mongodb.org/mongo-driver/bson/bsontype"
    24  	"go.mongodb.org/mongo-driver/bson/primitive"
    25  	"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
    26  )
    27  
    28  type myInterface interface {
    29  	Foo() int
    30  }
    31  
    32  type myStruct struct {
    33  	Val int
    34  }
    35  
    36  func (ms myStruct) Foo() int {
    37  	return ms.Val
    38  }
    39  
    40  func TestDefaultValueEncoders(t *testing.T) {
    41  	var dve DefaultValueEncoders
    42  	var wrong = func(string, string) string { return "wrong" }
    43  
    44  	type mybool bool
    45  	type myint8 int8
    46  	type myint16 int16
    47  	type myint32 int32
    48  	type myint64 int64
    49  	type myint int
    50  	type myuint8 uint8
    51  	type myuint16 uint16
    52  	type myuint32 uint32
    53  	type myuint64 uint64
    54  	type myuint uint
    55  	type myfloat32 float32
    56  	type myfloat64 float64
    57  
    58  	now := time.Now().Truncate(time.Millisecond)
    59  	pjsnum := new(json.Number)
    60  	*pjsnum = json.Number("3.14159")
    61  	d128 := primitive.NewDecimal128(12345, 67890)
    62  	var nilValueMarshaler *testValueMarshaler
    63  	var nilMarshaler *testMarshaler
    64  	var nilProxy *testProxy
    65  
    66  	vmStruct := struct{ V testValueMarshalPtr }{testValueMarshalPtr{t: bsontype.String, buf: []byte{0x04, 0x00, 0x00, 0x00, 'f', 'o', 'o', 0x00}}}
    67  	mStruct := struct{ V testMarshalPtr }{testMarshalPtr{buf: bsoncore.BuildDocument(nil, bsoncore.AppendDoubleElement(nil, "pi", 3.14159))}}
    68  	pStruct := struct{ V testProxyPtr }{testProxyPtr{ret: int64(1234567890)}}
    69  
    70  	type subtest struct {
    71  		name   string
    72  		val    interface{}
    73  		ectx   *EncodeContext
    74  		llvrw  *bsonrwtest.ValueReaderWriter
    75  		invoke bsonrwtest.Invoked
    76  		err    error
    77  	}
    78  
    79  	testCases := []struct {
    80  		name     string
    81  		ve       ValueEncoder
    82  		subtests []subtest
    83  	}{
    84  		{
    85  			"BooleanEncodeValue",
    86  			ValueEncoderFunc(dve.BooleanEncodeValue),
    87  			[]subtest{
    88  				{
    89  					"wrong type",
    90  					wrong,
    91  					nil,
    92  					nil,
    93  					bsonrwtest.Nothing,
    94  					ValueEncoderError{Name: "BooleanEncodeValue", Kinds: []reflect.Kind{reflect.Bool}, Received: reflect.ValueOf(wrong)},
    95  				},
    96  				{"fast path", bool(true), nil, nil, bsonrwtest.WriteBoolean, nil},
    97  				{"reflection path", mybool(true), nil, nil, bsonrwtest.WriteBoolean, nil},
    98  			},
    99  		},
   100  		{
   101  			"IntEncodeValue",
   102  			ValueEncoderFunc(dve.IntEncodeValue),
   103  			[]subtest{
   104  				{
   105  					"wrong type",
   106  					wrong,
   107  					nil,
   108  					nil,
   109  					bsonrwtest.Nothing,
   110  					ValueEncoderError{
   111  						Name:     "IntEncodeValue",
   112  						Kinds:    []reflect.Kind{reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int},
   113  						Received: reflect.ValueOf(wrong),
   114  					},
   115  				},
   116  				{"int8/fast path", int8(127), nil, nil, bsonrwtest.WriteInt32, nil},
   117  				{"int16/fast path", int16(32767), nil, nil, bsonrwtest.WriteInt32, nil},
   118  				{"int32/fast path", int32(2147483647), nil, nil, bsonrwtest.WriteInt32, nil},
   119  				{"int64/fast path", int64(1234567890987), nil, nil, bsonrwtest.WriteInt64, nil},
   120  				{"int64/fast path - minsize", int64(math.MaxInt32), &EncodeContext{MinSize: true}, nil, bsonrwtest.WriteInt32, nil},
   121  				{"int64/fast path - minsize too large", int64(math.MaxInt32 + 1), &EncodeContext{MinSize: true}, nil, bsonrwtest.WriteInt64, nil},
   122  				{"int64/fast path - minsize too small", int64(math.MinInt32 - 1), &EncodeContext{MinSize: true}, nil, bsonrwtest.WriteInt64, nil},
   123  				{"int/fast path - positive int32", int(math.MaxInt32 - 1), nil, nil, bsonrwtest.WriteInt32, nil},
   124  				{"int/fast path - negative int32", int(math.MinInt32 + 1), nil, nil, bsonrwtest.WriteInt32, nil},
   125  				{"int/fast path - MaxInt32", int(math.MaxInt32), nil, nil, bsonrwtest.WriteInt32, nil},
   126  				{"int/fast path - MinInt32", int(math.MinInt32), nil, nil, bsonrwtest.WriteInt32, nil},
   127  				{"int8/reflection path", myint8(127), nil, nil, bsonrwtest.WriteInt32, nil},
   128  				{"int16/reflection path", myint16(32767), nil, nil, bsonrwtest.WriteInt32, nil},
   129  				{"int32/reflection path", myint32(2147483647), nil, nil, bsonrwtest.WriteInt32, nil},
   130  				{"int64/reflection path", myint64(1234567890987), nil, nil, bsonrwtest.WriteInt64, nil},
   131  				{"int64/reflection path - minsize", myint64(math.MaxInt32), &EncodeContext{MinSize: true}, nil, bsonrwtest.WriteInt32, nil},
   132  				{"int64/reflection path - minsize too large", myint64(math.MaxInt32 + 1), &EncodeContext{MinSize: true}, nil, bsonrwtest.WriteInt64, nil},
   133  				{"int64/reflection path - minsize too small", myint64(math.MinInt32 - 1), &EncodeContext{MinSize: true}, nil, bsonrwtest.WriteInt64, nil},
   134  				{"int/reflection path - positive int32", myint(math.MaxInt32 - 1), nil, nil, bsonrwtest.WriteInt32, nil},
   135  				{"int/reflection path - negative int32", myint(math.MinInt32 + 1), nil, nil, bsonrwtest.WriteInt32, nil},
   136  				{"int/reflection path - MaxInt32", myint(math.MaxInt32), nil, nil, bsonrwtest.WriteInt32, nil},
   137  				{"int/reflection path - MinInt32", myint(math.MinInt32), nil, nil, bsonrwtest.WriteInt32, nil},
   138  			},
   139  		},
   140  		{
   141  			"UintEncodeValue",
   142  			defaultUIntCodec,
   143  			[]subtest{
   144  				{
   145  					"wrong type",
   146  					wrong,
   147  					nil,
   148  					nil,
   149  					bsonrwtest.Nothing,
   150  					ValueEncoderError{
   151  						Name:     "UintEncodeValue",
   152  						Kinds:    []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint},
   153  						Received: reflect.ValueOf(wrong),
   154  					},
   155  				},
   156  				{"uint8/fast path", uint8(127), nil, nil, bsonrwtest.WriteInt32, nil},
   157  				{"uint16/fast path", uint16(32767), nil, nil, bsonrwtest.WriteInt32, nil},
   158  				{"uint32/fast path", uint32(2147483647), nil, nil, bsonrwtest.WriteInt64, nil},
   159  				{"uint64/fast path", uint64(1234567890987), nil, nil, bsonrwtest.WriteInt64, nil},
   160  				{"uint/fast path", uint(1234567), nil, nil, bsonrwtest.WriteInt64, nil},
   161  				{"uint32/fast path - minsize", uint32(2147483647), &EncodeContext{MinSize: true}, nil, bsonrwtest.WriteInt32, nil},
   162  				{"uint64/fast path - minsize", uint64(2147483647), &EncodeContext{MinSize: true}, nil, bsonrwtest.WriteInt32, nil},
   163  				{"uint/fast path - minsize", uint(2147483647), &EncodeContext{MinSize: true}, nil, bsonrwtest.WriteInt32, nil},
   164  				{"uint32/fast path - minsize too large", uint32(2147483648), &EncodeContext{MinSize: true}, nil, bsonrwtest.WriteInt64, nil},
   165  				{"uint64/fast path - minsize too large", uint64(2147483648), &EncodeContext{MinSize: true}, nil, bsonrwtest.WriteInt64, nil},
   166  				{"uint/fast path - minsize too large", uint(2147483648), &EncodeContext{MinSize: true}, nil, bsonrwtest.WriteInt64, nil},
   167  				{"uint64/fast path - overflow", uint64(1 << 63), nil, nil, bsonrwtest.Nothing, fmt.Errorf("%d overflows int64", uint64(1<<63))},
   168  				{"uint8/reflection path", myuint8(127), nil, nil, bsonrwtest.WriteInt32, nil},
   169  				{"uint16/reflection path", myuint16(32767), nil, nil, bsonrwtest.WriteInt32, nil},
   170  				{"uint32/reflection path", myuint32(2147483647), nil, nil, bsonrwtest.WriteInt64, nil},
   171  				{"uint64/reflection path", myuint64(1234567890987), nil, nil, bsonrwtest.WriteInt64, nil},
   172  				{"uint32/reflection path - minsize", myuint32(2147483647), &EncodeContext{MinSize: true}, nil, bsonrwtest.WriteInt32, nil},
   173  				{"uint64/reflection path - minsize", myuint64(2147483647), &EncodeContext{MinSize: true}, nil, bsonrwtest.WriteInt32, nil},
   174  				{"uint/reflection path - minsize", myuint(2147483647), &EncodeContext{MinSize: true}, nil, bsonrwtest.WriteInt32, nil},
   175  				{"uint32/reflection path - minsize too large", myuint(1 << 31), &EncodeContext{MinSize: true}, nil, bsonrwtest.WriteInt64, nil},
   176  				{"uint64/reflection path - minsize too large", myuint64(1 << 31), &EncodeContext{MinSize: true}, nil, bsonrwtest.WriteInt64, nil},
   177  				{"uint/reflection path - minsize too large", myuint(2147483648), &EncodeContext{MinSize: true}, nil, bsonrwtest.WriteInt64, nil},
   178  				{"uint64/reflection path - overflow", myuint64(1 << 63), nil, nil, bsonrwtest.Nothing, fmt.Errorf("%d overflows int64", uint64(1<<63))},
   179  			},
   180  		},
   181  		{
   182  			"FloatEncodeValue",
   183  			ValueEncoderFunc(dve.FloatEncodeValue),
   184  			[]subtest{
   185  				{
   186  					"wrong type",
   187  					wrong,
   188  					nil,
   189  					nil,
   190  					bsonrwtest.Nothing,
   191  					ValueEncoderError{
   192  						Name:     "FloatEncodeValue",
   193  						Kinds:    []reflect.Kind{reflect.Float32, reflect.Float64},
   194  						Received: reflect.ValueOf(wrong),
   195  					},
   196  				},
   197  				{"float32/fast path", float32(3.14159), nil, nil, bsonrwtest.WriteDouble, nil},
   198  				{"float64/fast path", float64(3.14159), nil, nil, bsonrwtest.WriteDouble, nil},
   199  				{"float32/reflection path", myfloat32(3.14159), nil, nil, bsonrwtest.WriteDouble, nil},
   200  				{"float64/reflection path", myfloat64(3.14159), nil, nil, bsonrwtest.WriteDouble, nil},
   201  			},
   202  		},
   203  		{
   204  			"TimeEncodeValue",
   205  			defaultTimeCodec,
   206  			[]subtest{
   207  				{
   208  					"wrong type",
   209  					wrong,
   210  					nil,
   211  					nil,
   212  					bsonrwtest.Nothing,
   213  					ValueEncoderError{Name: "TimeEncodeValue", Types: []reflect.Type{tTime}, Received: reflect.ValueOf(wrong)},
   214  				},
   215  				{"time.Time", now, nil, nil, bsonrwtest.WriteDateTime, nil},
   216  			},
   217  		},
   218  		{
   219  			"MapEncodeValue",
   220  			defaultMapCodec,
   221  			[]subtest{
   222  				{
   223  					"wrong kind",
   224  					wrong,
   225  					nil,
   226  					nil,
   227  					bsonrwtest.Nothing,
   228  					ValueEncoderError{Name: "MapEncodeValue", Kinds: []reflect.Kind{reflect.Map}, Received: reflect.ValueOf(wrong)},
   229  				},
   230  				{
   231  					"WriteDocument Error",
   232  					map[string]interface{}{},
   233  					nil,
   234  					&bsonrwtest.ValueReaderWriter{Err: errors.New("wd error"), ErrAfter: bsonrwtest.WriteDocument},
   235  					bsonrwtest.WriteDocument,
   236  					errors.New("wd error"),
   237  				},
   238  				{
   239  					"Lookup Error",
   240  					map[string]int{"foo": 1},
   241  					&EncodeContext{Registry: NewRegistryBuilder().Build()},
   242  					&bsonrwtest.ValueReaderWriter{},
   243  					bsonrwtest.WriteDocument,
   244  					fmt.Errorf("no encoder found for int"),
   245  				},
   246  				{
   247  					"WriteDocumentElement Error",
   248  					map[string]interface{}{"foo": "bar"},
   249  					&EncodeContext{Registry: buildDefaultRegistry()},
   250  					&bsonrwtest.ValueReaderWriter{Err: errors.New("wde error"), ErrAfter: bsonrwtest.WriteDocumentElement},
   251  					bsonrwtest.WriteDocumentElement,
   252  					errors.New("wde error"),
   253  				},
   254  				{
   255  					"EncodeValue Error",
   256  					map[string]interface{}{"foo": "bar"},
   257  					&EncodeContext{Registry: buildDefaultRegistry()},
   258  					&bsonrwtest.ValueReaderWriter{Err: errors.New("ev error"), ErrAfter: bsonrwtest.WriteString},
   259  					bsonrwtest.WriteString,
   260  					errors.New("ev error"),
   261  				},
   262  				{
   263  					"empty map/success",
   264  					map[string]interface{}{},
   265  					&EncodeContext{Registry: NewRegistryBuilder().Build()},
   266  					&bsonrwtest.ValueReaderWriter{},
   267  					bsonrwtest.WriteDocumentEnd,
   268  					nil,
   269  				},
   270  				{
   271  					"with interface/success",
   272  					map[string]myInterface{"foo": myStruct{1}},
   273  					&EncodeContext{Registry: buildDefaultRegistry()},
   274  					nil,
   275  					bsonrwtest.WriteDocumentEnd,
   276  					nil,
   277  				},
   278  				{
   279  					"with interface/nil/success",
   280  					map[string]myInterface{"foo": nil},
   281  					&EncodeContext{Registry: buildDefaultRegistry()},
   282  					nil,
   283  					bsonrwtest.WriteDocumentEnd,
   284  					nil,
   285  				},
   286  				{
   287  					"non-string key success",
   288  					map[int]interface{}{
   289  						1: "foobar",
   290  					},
   291  					&EncodeContext{Registry: buildDefaultRegistry()},
   292  					&bsonrwtest.ValueReaderWriter{},
   293  					bsonrwtest.WriteDocumentEnd,
   294  					nil,
   295  				},
   296  			},
   297  		},
   298  		{
   299  			"ArrayEncodeValue",
   300  			ValueEncoderFunc(dve.ArrayEncodeValue),
   301  			[]subtest{
   302  				{
   303  					"wrong kind",
   304  					wrong,
   305  					nil,
   306  					nil,
   307  					bsonrwtest.Nothing,
   308  					ValueEncoderError{Name: "ArrayEncodeValue", Kinds: []reflect.Kind{reflect.Array}, Received: reflect.ValueOf(wrong)},
   309  				},
   310  				{
   311  					"WriteArray Error",
   312  					[1]string{},
   313  					nil,
   314  					&bsonrwtest.ValueReaderWriter{Err: errors.New("wa error"), ErrAfter: bsonrwtest.WriteArray},
   315  					bsonrwtest.WriteArray,
   316  					errors.New("wa error"),
   317  				},
   318  				{
   319  					"Lookup Error",
   320  					[1]int{1},
   321  					&EncodeContext{Registry: NewRegistryBuilder().Build()},
   322  					&bsonrwtest.ValueReaderWriter{},
   323  					bsonrwtest.WriteArray,
   324  					fmt.Errorf("no encoder found for int"),
   325  				},
   326  				{
   327  					"WriteArrayElement Error",
   328  					[1]string{"foo"},
   329  					&EncodeContext{Registry: buildDefaultRegistry()},
   330  					&bsonrwtest.ValueReaderWriter{Err: errors.New("wae error"), ErrAfter: bsonrwtest.WriteArrayElement},
   331  					bsonrwtest.WriteArrayElement,
   332  					errors.New("wae error"),
   333  				},
   334  				{
   335  					"EncodeValue Error",
   336  					[1]string{"foo"},
   337  					&EncodeContext{Registry: buildDefaultRegistry()},
   338  					&bsonrwtest.ValueReaderWriter{Err: errors.New("ev error"), ErrAfter: bsonrwtest.WriteString},
   339  					bsonrwtest.WriteString,
   340  					errors.New("ev error"),
   341  				},
   342  				{
   343  					"[1]primitive.E/success",
   344  					[1]primitive.E{{"hello", "world"}},
   345  					&EncodeContext{Registry: buildDefaultRegistry()},
   346  					nil,
   347  					bsonrwtest.WriteDocumentEnd,
   348  					nil,
   349  				},
   350  				{
   351  					"[1]primitive.E/success",
   352  					[1]primitive.E{{"hello", nil}},
   353  					&EncodeContext{Registry: buildDefaultRegistry()},
   354  					nil,
   355  					bsonrwtest.WriteDocumentEnd,
   356  					nil,
   357  				},
   358  				{
   359  					"[1]interface/success",
   360  					[1]myInterface{myStruct{1}},
   361  					&EncodeContext{Registry: buildDefaultRegistry()},
   362  					nil,
   363  					bsonrwtest.WriteArrayEnd,
   364  					nil,
   365  				},
   366  				{
   367  					"[1]interface/nil/success",
   368  					[1]myInterface{nil},
   369  					&EncodeContext{Registry: buildDefaultRegistry()},
   370  					nil,
   371  					bsonrwtest.WriteArrayEnd,
   372  					nil,
   373  				},
   374  			},
   375  		},
   376  		{
   377  			"SliceEncodeValue",
   378  			defaultSliceCodec,
   379  			[]subtest{
   380  				{
   381  					"wrong kind",
   382  					wrong,
   383  					nil,
   384  					nil,
   385  					bsonrwtest.Nothing,
   386  					ValueEncoderError{Name: "SliceEncodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: reflect.ValueOf(wrong)},
   387  				},
   388  				{
   389  					"WriteArray Error",
   390  					[]string{},
   391  					nil,
   392  					&bsonrwtest.ValueReaderWriter{Err: errors.New("wa error"), ErrAfter: bsonrwtest.WriteArray},
   393  					bsonrwtest.WriteArray,
   394  					errors.New("wa error"),
   395  				},
   396  				{
   397  					"Lookup Error",
   398  					[]int{1},
   399  					&EncodeContext{Registry: NewRegistryBuilder().Build()},
   400  					&bsonrwtest.ValueReaderWriter{},
   401  					bsonrwtest.WriteArray,
   402  					fmt.Errorf("no encoder found for int"),
   403  				},
   404  				{
   405  					"WriteArrayElement Error",
   406  					[]string{"foo"},
   407  					&EncodeContext{Registry: buildDefaultRegistry()},
   408  					&bsonrwtest.ValueReaderWriter{Err: errors.New("wae error"), ErrAfter: bsonrwtest.WriteArrayElement},
   409  					bsonrwtest.WriteArrayElement,
   410  					errors.New("wae error"),
   411  				},
   412  				{
   413  					"EncodeValue Error",
   414  					[]string{"foo"},
   415  					&EncodeContext{Registry: buildDefaultRegistry()},
   416  					&bsonrwtest.ValueReaderWriter{Err: errors.New("ev error"), ErrAfter: bsonrwtest.WriteString},
   417  					bsonrwtest.WriteString,
   418  					errors.New("ev error"),
   419  				},
   420  				{
   421  					"D/success",
   422  					primitive.D{{"hello", "world"}},
   423  					&EncodeContext{Registry: buildDefaultRegistry()},
   424  					nil,
   425  					bsonrwtest.WriteDocumentEnd,
   426  					nil,
   427  				},
   428  				{
   429  					"D/success",
   430  					primitive.D{{"hello", nil}},
   431  					&EncodeContext{Registry: buildDefaultRegistry()},
   432  					nil,
   433  					bsonrwtest.WriteDocumentEnd,
   434  					nil,
   435  				},
   436  				{
   437  					"empty slice/success",
   438  					[]interface{}{},
   439  					&EncodeContext{Registry: NewRegistryBuilder().Build()},
   440  					&bsonrwtest.ValueReaderWriter{},
   441  					bsonrwtest.WriteArrayEnd,
   442  					nil,
   443  				},
   444  				{
   445  					"interface/success",
   446  					[]myInterface{myStruct{1}},
   447  					&EncodeContext{Registry: buildDefaultRegistry()},
   448  					nil,
   449  					bsonrwtest.WriteArrayEnd,
   450  					nil,
   451  				},
   452  				{
   453  					"interface/success",
   454  					[]myInterface{nil},
   455  					&EncodeContext{Registry: buildDefaultRegistry()},
   456  					nil,
   457  					bsonrwtest.WriteArrayEnd,
   458  					nil,
   459  				},
   460  			},
   461  		},
   462  		{
   463  			"ObjectIDEncodeValue",
   464  			ValueEncoderFunc(dve.ObjectIDEncodeValue),
   465  			[]subtest{
   466  				{
   467  					"wrong type",
   468  					wrong,
   469  					nil,
   470  					nil,
   471  					bsonrwtest.Nothing,
   472  					ValueEncoderError{Name: "ObjectIDEncodeValue", Types: []reflect.Type{tOID}, Received: reflect.ValueOf(wrong)},
   473  				},
   474  				{
   475  					"primitive.ObjectID/success",
   476  					primitive.ObjectID{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C},
   477  					nil, nil, bsonrwtest.WriteObjectID, nil,
   478  				},
   479  			},
   480  		},
   481  		{
   482  			"Decimal128EncodeValue",
   483  			ValueEncoderFunc(dve.Decimal128EncodeValue),
   484  			[]subtest{
   485  				{
   486  					"wrong type",
   487  					wrong,
   488  					nil,
   489  					nil,
   490  					bsonrwtest.Nothing,
   491  					ValueEncoderError{Name: "Decimal128EncodeValue", Types: []reflect.Type{tDecimal}, Received: reflect.ValueOf(wrong)},
   492  				},
   493  				{"Decimal128/success", d128, nil, nil, bsonrwtest.WriteDecimal128, nil},
   494  			},
   495  		},
   496  		{
   497  			"JSONNumberEncodeValue",
   498  			ValueEncoderFunc(dve.JSONNumberEncodeValue),
   499  			[]subtest{
   500  				{
   501  					"wrong type",
   502  					wrong,
   503  					nil,
   504  					nil,
   505  					bsonrwtest.Nothing,
   506  					ValueEncoderError{Name: "JSONNumberEncodeValue", Types: []reflect.Type{tJSONNumber}, Received: reflect.ValueOf(wrong)},
   507  				},
   508  				{
   509  					"json.Number/invalid",
   510  					json.Number("hello world"),
   511  					nil, nil, bsonrwtest.Nothing, errors.New(`strconv.ParseFloat: parsing "hello world": invalid syntax`),
   512  				},
   513  				{
   514  					"json.Number/int64/success",
   515  					json.Number("1234567890"),
   516  					nil, nil, bsonrwtest.WriteInt64, nil,
   517  				},
   518  				{
   519  					"json.Number/float64/success",
   520  					json.Number("3.14159"),
   521  					nil, nil, bsonrwtest.WriteDouble, nil,
   522  				},
   523  			},
   524  		},
   525  		{
   526  			"URLEncodeValue",
   527  			ValueEncoderFunc(dve.URLEncodeValue),
   528  			[]subtest{
   529  				{
   530  					"wrong type",
   531  					wrong,
   532  					nil,
   533  					nil,
   534  					bsonrwtest.Nothing,
   535  					ValueEncoderError{Name: "URLEncodeValue", Types: []reflect.Type{tURL}, Received: reflect.ValueOf(wrong)},
   536  				},
   537  				{"url.URL", url.URL{Scheme: "http", Host: "example.com"}, nil, nil, bsonrwtest.WriteString, nil},
   538  			},
   539  		},
   540  		{
   541  			"ByteSliceEncodeValue",
   542  			defaultByteSliceCodec,
   543  			[]subtest{
   544  				{
   545  					"wrong type",
   546  					wrong,
   547  					nil,
   548  					nil,
   549  					bsonrwtest.Nothing,
   550  					ValueEncoderError{Name: "ByteSliceEncodeValue", Types: []reflect.Type{tByteSlice}, Received: reflect.ValueOf(wrong)},
   551  				},
   552  				{"[]byte", []byte{0x01, 0x02, 0x03}, nil, nil, bsonrwtest.WriteBinary, nil},
   553  				{"[]byte/nil", []byte(nil), nil, nil, bsonrwtest.WriteNull, nil},
   554  			},
   555  		},
   556  		{
   557  			"EmptyInterfaceEncodeValue",
   558  			defaultEmptyInterfaceCodec,
   559  			[]subtest{
   560  				{
   561  					"wrong type",
   562  					wrong,
   563  					nil,
   564  					nil,
   565  					bsonrwtest.Nothing,
   566  					ValueEncoderError{Name: "EmptyInterfaceEncodeValue", Types: []reflect.Type{tEmpty}, Received: reflect.ValueOf(wrong)},
   567  				},
   568  			},
   569  		},
   570  		{
   571  			"ValueMarshalerEncodeValue",
   572  			ValueEncoderFunc(dve.ValueMarshalerEncodeValue),
   573  			[]subtest{
   574  				{
   575  					"wrong type",
   576  					wrong,
   577  					nil,
   578  					nil,
   579  					bsonrwtest.Nothing,
   580  					ValueEncoderError{
   581  						Name:     "ValueMarshalerEncodeValue",
   582  						Types:    []reflect.Type{tValueMarshaler},
   583  						Received: reflect.ValueOf(wrong),
   584  					},
   585  				},
   586  				{
   587  					"MarshalBSONValue error",
   588  					testValueMarshaler{err: errors.New("mbsonv error")},
   589  					nil,
   590  					nil,
   591  					bsonrwtest.Nothing,
   592  					errors.New("mbsonv error"),
   593  				},
   594  				{
   595  					"Copy error",
   596  					testValueMarshaler{},
   597  					nil,
   598  					nil,
   599  					bsonrwtest.Nothing,
   600  					fmt.Errorf("Cannot copy unknown BSON type %s", bsontype.Type(0)),
   601  				},
   602  				{
   603  					"success struct implementation",
   604  					testValueMarshaler{t: bsontype.String, buf: []byte{0x04, 0x00, 0x00, 0x00, 'f', 'o', 'o', 0x00}},
   605  					nil,
   606  					nil,
   607  					bsonrwtest.WriteString,
   608  					nil,
   609  				},
   610  				{
   611  					"success ptr to struct implementation",
   612  					&testValueMarshaler{t: bsontype.String, buf: []byte{0x04, 0x00, 0x00, 0x00, 'f', 'o', 'o', 0x00}},
   613  					nil,
   614  					nil,
   615  					bsonrwtest.WriteString,
   616  					nil,
   617  				},
   618  				{
   619  					"success nil ptr to struct implementation",
   620  					nilValueMarshaler,
   621  					nil,
   622  					nil,
   623  					bsonrwtest.WriteNull,
   624  					nil,
   625  				},
   626  				{
   627  					"success ptr to ptr implementation",
   628  					&testValueMarshalPtr{t: bsontype.String, buf: []byte{0x04, 0x00, 0x00, 0x00, 'f', 'o', 'o', 0x00}},
   629  					nil,
   630  					nil,
   631  					bsonrwtest.WriteString,
   632  					nil,
   633  				},
   634  				{
   635  					"unaddressable ptr implementation",
   636  					testValueMarshalPtr{t: bsontype.String, buf: []byte{0x04, 0x00, 0x00, 0x00, 'f', 'o', 'o', 0x00}},
   637  					nil,
   638  					nil,
   639  					bsonrwtest.Nothing,
   640  					ValueEncoderError{
   641  						Name:     "ValueMarshalerEncodeValue",
   642  						Types:    []reflect.Type{tValueMarshaler},
   643  						Received: reflect.ValueOf(testValueMarshalPtr{}),
   644  					},
   645  				},
   646  			},
   647  		},
   648  		{
   649  			"MarshalerEncodeValue",
   650  			ValueEncoderFunc(dve.MarshalerEncodeValue),
   651  			[]subtest{
   652  				{
   653  					"wrong type",
   654  					wrong,
   655  					nil,
   656  					nil,
   657  					bsonrwtest.Nothing,
   658  					ValueEncoderError{Name: "MarshalerEncodeValue", Types: []reflect.Type{tMarshaler}, Received: reflect.ValueOf(wrong)},
   659  				},
   660  				{
   661  					"MarshalBSON error",
   662  					testMarshaler{err: errors.New("mbson error")},
   663  					nil,
   664  					nil,
   665  					bsonrwtest.Nothing,
   666  					errors.New("mbson error"),
   667  				},
   668  				{
   669  					"success struct implementation",
   670  					testMarshaler{buf: bsoncore.BuildDocument(nil, bsoncore.AppendDoubleElement(nil, "pi", 3.14159))},
   671  					nil,
   672  					nil,
   673  					bsonrwtest.WriteDocumentEnd,
   674  					nil,
   675  				},
   676  				{
   677  					"success ptr to struct implementation",
   678  					&testMarshaler{buf: bsoncore.BuildDocument(nil, bsoncore.AppendDoubleElement(nil, "pi", 3.14159))},
   679  					nil,
   680  					nil,
   681  					bsonrwtest.WriteDocumentEnd,
   682  					nil,
   683  				},
   684  				{
   685  					"success nil ptr to struct implementation",
   686  					nilMarshaler,
   687  					nil,
   688  					nil,
   689  					bsonrwtest.WriteNull,
   690  					nil,
   691  				},
   692  				{
   693  					"success ptr to ptr implementation",
   694  					&testMarshalPtr{buf: bsoncore.BuildDocument(nil, bsoncore.AppendDoubleElement(nil, "pi", 3.14159))},
   695  					nil,
   696  					nil,
   697  					bsonrwtest.WriteDocumentEnd,
   698  					nil,
   699  				},
   700  				{
   701  					"unaddressable ptr implementation",
   702  					testMarshalPtr{buf: bsoncore.BuildDocument(nil, bsoncore.AppendDoubleElement(nil, "pi", 3.14159))},
   703  					nil,
   704  					nil,
   705  					bsonrwtest.Nothing,
   706  					ValueEncoderError{Name: "MarshalerEncodeValue", Types: []reflect.Type{tMarshaler}, Received: reflect.ValueOf(testMarshalPtr{})},
   707  				},
   708  			},
   709  		},
   710  		{
   711  			"ProxyEncodeValue",
   712  			ValueEncoderFunc(dve.ProxyEncodeValue),
   713  			[]subtest{
   714  				{
   715  					"wrong type",
   716  					wrong,
   717  					nil,
   718  					nil,
   719  					bsonrwtest.Nothing,
   720  					ValueEncoderError{Name: "ProxyEncodeValue", Types: []reflect.Type{tProxy}, Received: reflect.ValueOf(wrong)},
   721  				},
   722  				{
   723  					"Proxy error",
   724  					testProxy{err: errors.New("proxy error")},
   725  					nil,
   726  					nil,
   727  					bsonrwtest.Nothing,
   728  					errors.New("proxy error"),
   729  				},
   730  				{
   731  					"Lookup error",
   732  					testProxy{ret: nil},
   733  					&EncodeContext{Registry: buildDefaultRegistry()},
   734  					nil,
   735  					bsonrwtest.Nothing,
   736  					ErrNoEncoder{Type: nil},
   737  				},
   738  				{
   739  					"success struct implementation",
   740  					testProxy{ret: int64(1234567890)},
   741  					&EncodeContext{Registry: buildDefaultRegistry()},
   742  					nil,
   743  					bsonrwtest.WriteInt64,
   744  					nil,
   745  				},
   746  				{
   747  					"success ptr to struct implementation",
   748  					&testProxy{ret: int64(1234567890)},
   749  					&EncodeContext{Registry: buildDefaultRegistry()},
   750  					nil,
   751  					bsonrwtest.WriteInt64,
   752  					nil,
   753  				},
   754  				{
   755  					"success nil ptr to struct implementation",
   756  					nilProxy,
   757  					nil,
   758  					nil,
   759  					bsonrwtest.WriteNull,
   760  					nil,
   761  				},
   762  				{
   763  					"success ptr to ptr implementation",
   764  					&testProxyPtr{ret: int64(1234567890)},
   765  					&EncodeContext{Registry: buildDefaultRegistry()},
   766  					nil,
   767  					bsonrwtest.WriteInt64,
   768  					nil,
   769  				},
   770  				{
   771  					"unaddressable ptr implementation",
   772  					testProxyPtr{ret: int64(1234567890)},
   773  					nil,
   774  					nil,
   775  					bsonrwtest.Nothing,
   776  					ValueEncoderError{Name: "ProxyEncodeValue", Types: []reflect.Type{tProxy}, Received: reflect.ValueOf(testProxyPtr{})},
   777  				},
   778  			},
   779  		},
   780  		{
   781  			"PointerCodec.EncodeValue",
   782  			NewPointerCodec(),
   783  			[]subtest{
   784  				{
   785  					"nil",
   786  					nil,
   787  					nil,
   788  					nil,
   789  					bsonrwtest.WriteNull,
   790  					nil,
   791  				},
   792  				{
   793  					"not pointer",
   794  					int32(123456),
   795  					nil,
   796  					nil,
   797  					bsonrwtest.Nothing,
   798  					ValueEncoderError{Name: "PointerCodec.EncodeValue", Kinds: []reflect.Kind{reflect.Ptr}, Received: reflect.ValueOf(int32(123456))},
   799  				},
   800  				{
   801  					"typed nil",
   802  					(*int32)(nil),
   803  					nil,
   804  					nil,
   805  					bsonrwtest.WriteNull,
   806  					nil,
   807  				},
   808  				{
   809  					"no encoder",
   810  					&wrong,
   811  					&EncodeContext{Registry: buildDefaultRegistry()},
   812  					nil,
   813  					bsonrwtest.Nothing,
   814  					ErrNoEncoder{Type: reflect.TypeOf(wrong)},
   815  				},
   816  			},
   817  		},
   818  		{
   819  			"pointer implementation addressable interface",
   820  			NewPointerCodec(),
   821  			[]subtest{
   822  				{
   823  					"ValueMarshaler",
   824  					&vmStruct,
   825  					&EncodeContext{Registry: buildDefaultRegistry()},
   826  					nil,
   827  					bsonrwtest.WriteDocumentEnd,
   828  					nil,
   829  				},
   830  				{
   831  					"Marshaler",
   832  					&mStruct,
   833  					&EncodeContext{Registry: buildDefaultRegistry()},
   834  					nil,
   835  					bsonrwtest.WriteDocumentEnd,
   836  					nil,
   837  				},
   838  				{
   839  					"Proxy",
   840  					&pStruct,
   841  					&EncodeContext{Registry: buildDefaultRegistry()},
   842  					nil,
   843  					bsonrwtest.WriteDocumentEnd,
   844  					nil,
   845  				},
   846  			},
   847  		},
   848  		{
   849  			"JavaScriptEncodeValue",
   850  			ValueEncoderFunc(dve.JavaScriptEncodeValue),
   851  			[]subtest{
   852  				{
   853  					"wrong type",
   854  					wrong,
   855  					nil,
   856  					nil,
   857  					bsonrwtest.Nothing,
   858  					ValueEncoderError{Name: "JavaScriptEncodeValue", Types: []reflect.Type{tJavaScript}, Received: reflect.ValueOf(wrong)},
   859  				},
   860  				{"JavaScript", primitive.JavaScript("foobar"), nil, nil, bsonrwtest.WriteJavascript, nil},
   861  			},
   862  		},
   863  		{
   864  			"SymbolEncodeValue",
   865  			ValueEncoderFunc(dve.SymbolEncodeValue),
   866  			[]subtest{
   867  				{
   868  					"wrong type",
   869  					wrong,
   870  					nil,
   871  					nil,
   872  					bsonrwtest.Nothing,
   873  					ValueEncoderError{Name: "SymbolEncodeValue", Types: []reflect.Type{tSymbol}, Received: reflect.ValueOf(wrong)},
   874  				},
   875  				{"Symbol", primitive.Symbol("foobar"), nil, nil, bsonrwtest.WriteSymbol, nil},
   876  			},
   877  		},
   878  		{
   879  			"BinaryEncodeValue",
   880  			ValueEncoderFunc(dve.BinaryEncodeValue),
   881  			[]subtest{
   882  				{
   883  					"wrong type",
   884  					wrong,
   885  					nil,
   886  					nil,
   887  					bsonrwtest.Nothing,
   888  					ValueEncoderError{Name: "BinaryEncodeValue", Types: []reflect.Type{tBinary}, Received: reflect.ValueOf(wrong)},
   889  				},
   890  				{"Binary/success", primitive.Binary{Data: []byte{0x01, 0x02}, Subtype: 0xFF}, nil, nil, bsonrwtest.WriteBinaryWithSubtype, nil},
   891  			},
   892  		},
   893  		{
   894  			"UndefinedEncodeValue",
   895  			ValueEncoderFunc(dve.UndefinedEncodeValue),
   896  			[]subtest{
   897  				{
   898  					"wrong type",
   899  					wrong,
   900  					nil,
   901  					nil,
   902  					bsonrwtest.Nothing,
   903  					ValueEncoderError{Name: "UndefinedEncodeValue", Types: []reflect.Type{tUndefined}, Received: reflect.ValueOf(wrong)},
   904  				},
   905  				{"Undefined/success", primitive.Undefined{}, nil, nil, bsonrwtest.WriteUndefined, nil},
   906  			},
   907  		},
   908  		{
   909  			"DateTimeEncodeValue",
   910  			ValueEncoderFunc(dve.DateTimeEncodeValue),
   911  			[]subtest{
   912  				{
   913  					"wrong type",
   914  					wrong,
   915  					nil,
   916  					nil,
   917  					bsonrwtest.Nothing,
   918  					ValueEncoderError{Name: "DateTimeEncodeValue", Types: []reflect.Type{tDateTime}, Received: reflect.ValueOf(wrong)},
   919  				},
   920  				{"DateTime/success", primitive.DateTime(1234567890), nil, nil, bsonrwtest.WriteDateTime, nil},
   921  			},
   922  		},
   923  		{
   924  			"NullEncodeValue",
   925  			ValueEncoderFunc(dve.NullEncodeValue),
   926  			[]subtest{
   927  				{
   928  					"wrong type",
   929  					wrong,
   930  					nil,
   931  					nil,
   932  					bsonrwtest.Nothing,
   933  					ValueEncoderError{Name: "NullEncodeValue", Types: []reflect.Type{tNull}, Received: reflect.ValueOf(wrong)},
   934  				},
   935  				{"Null/success", primitive.Null{}, nil, nil, bsonrwtest.WriteNull, nil},
   936  			},
   937  		},
   938  		{
   939  			"RegexEncodeValue",
   940  			ValueEncoderFunc(dve.RegexEncodeValue),
   941  			[]subtest{
   942  				{
   943  					"wrong type",
   944  					wrong,
   945  					nil,
   946  					nil,
   947  					bsonrwtest.Nothing,
   948  					ValueEncoderError{Name: "RegexEncodeValue", Types: []reflect.Type{tRegex}, Received: reflect.ValueOf(wrong)},
   949  				},
   950  				{"Regex/success", primitive.Regex{Pattern: "foo", Options: "bar"}, nil, nil, bsonrwtest.WriteRegex, nil},
   951  			},
   952  		},
   953  		{
   954  			"DBPointerEncodeValue",
   955  			ValueEncoderFunc(dve.DBPointerEncodeValue),
   956  			[]subtest{
   957  				{
   958  					"wrong type",
   959  					wrong,
   960  					nil,
   961  					nil,
   962  					bsonrwtest.Nothing,
   963  					ValueEncoderError{Name: "DBPointerEncodeValue", Types: []reflect.Type{tDBPointer}, Received: reflect.ValueOf(wrong)},
   964  				},
   965  				{
   966  					"DBPointer/success",
   967  					primitive.DBPointer{
   968  						DB:      "foobar",
   969  						Pointer: primitive.ObjectID{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C},
   970  					},
   971  					nil, nil, bsonrwtest.WriteDBPointer, nil,
   972  				},
   973  			},
   974  		},
   975  		{
   976  			"TimestampEncodeValue",
   977  			ValueEncoderFunc(dve.TimestampEncodeValue),
   978  			[]subtest{
   979  				{
   980  					"wrong type",
   981  					wrong,
   982  					nil,
   983  					nil,
   984  					bsonrwtest.Nothing,
   985  					ValueEncoderError{Name: "TimestampEncodeValue", Types: []reflect.Type{tTimestamp}, Received: reflect.ValueOf(wrong)},
   986  				},
   987  				{"Timestamp/success", primitive.Timestamp{T: 12345, I: 67890}, nil, nil, bsonrwtest.WriteTimestamp, nil},
   988  			},
   989  		},
   990  		{
   991  			"MinKeyEncodeValue",
   992  			ValueEncoderFunc(dve.MinKeyEncodeValue),
   993  			[]subtest{
   994  				{
   995  					"wrong type",
   996  					wrong,
   997  					nil,
   998  					nil,
   999  					bsonrwtest.Nothing,
  1000  					ValueEncoderError{Name: "MinKeyEncodeValue", Types: []reflect.Type{tMinKey}, Received: reflect.ValueOf(wrong)},
  1001  				},
  1002  				{"MinKey/success", primitive.MinKey{}, nil, nil, bsonrwtest.WriteMinKey, nil},
  1003  			},
  1004  		},
  1005  		{
  1006  			"MaxKeyEncodeValue",
  1007  			ValueEncoderFunc(dve.MaxKeyEncodeValue),
  1008  			[]subtest{
  1009  				{
  1010  					"wrong type",
  1011  					wrong,
  1012  					nil,
  1013  					nil,
  1014  					bsonrwtest.Nothing,
  1015  					ValueEncoderError{Name: "MaxKeyEncodeValue", Types: []reflect.Type{tMaxKey}, Received: reflect.ValueOf(wrong)},
  1016  				},
  1017  				{"MaxKey/success", primitive.MaxKey{}, nil, nil, bsonrwtest.WriteMaxKey, nil},
  1018  			},
  1019  		},
  1020  		{
  1021  			"CoreDocumentEncodeValue",
  1022  			ValueEncoderFunc(dve.CoreDocumentEncodeValue),
  1023  			[]subtest{
  1024  				{
  1025  					"wrong type",
  1026  					wrong,
  1027  					nil,
  1028  					nil,
  1029  					bsonrwtest.Nothing,
  1030  					ValueEncoderError{
  1031  						Name:     "CoreDocumentEncodeValue",
  1032  						Types:    []reflect.Type{tCoreDocument},
  1033  						Received: reflect.ValueOf(wrong),
  1034  					},
  1035  				},
  1036  				{
  1037  					"WriteDocument Error",
  1038  					bsoncore.Document{},
  1039  					nil,
  1040  					&bsonrwtest.ValueReaderWriter{Err: errors.New("wd error"), ErrAfter: bsonrwtest.WriteDocument},
  1041  					bsonrwtest.WriteDocument,
  1042  					errors.New("wd error"),
  1043  				},
  1044  				{
  1045  					"bsoncore.Document.Elements Error",
  1046  					bsoncore.Document{0xFF, 0x00, 0x00, 0x00, 0x00},
  1047  					nil,
  1048  					&bsonrwtest.ValueReaderWriter{},
  1049  					bsonrwtest.WriteDocument,
  1050  					errors.New("length read exceeds number of bytes available. length=5 bytes=255"),
  1051  				},
  1052  				{
  1053  					"WriteDocumentElement Error",
  1054  					bsoncore.Document(buildDocument(bsoncore.AppendNullElement(nil, "foo"))),
  1055  					nil,
  1056  					&bsonrwtest.ValueReaderWriter{Err: errors.New("wde error"), ErrAfter: bsonrwtest.WriteDocumentElement},
  1057  					bsonrwtest.WriteDocumentElement,
  1058  					errors.New("wde error"),
  1059  				},
  1060  				{
  1061  					"encodeValue error",
  1062  					bsoncore.Document(buildDocument(bsoncore.AppendNullElement(nil, "foo"))),
  1063  					nil,
  1064  					&bsonrwtest.ValueReaderWriter{Err: errors.New("ev error"), ErrAfter: bsonrwtest.WriteNull},
  1065  					bsonrwtest.WriteNull,
  1066  					errors.New("ev error"),
  1067  				},
  1068  				{
  1069  					"iterator error",
  1070  					bsoncore.Document{0x0C, 0x00, 0x00, 0x00, 0x01, 'f', 'o', 'o', 0x00, 0x01, 0x02, 0x03},
  1071  					nil,
  1072  					&bsonrwtest.ValueReaderWriter{},
  1073  					bsonrwtest.WriteDocumentElement,
  1074  					errors.New("not enough bytes available to read type. bytes=3 type=double"),
  1075  				},
  1076  			},
  1077  		},
  1078  		{
  1079  			"StructEncodeValue",
  1080  			defaultTestStructCodec,
  1081  			[]subtest{
  1082  				{
  1083  					"interface value",
  1084  					struct{ Foo myInterface }{Foo: myStruct{1}},
  1085  					&EncodeContext{Registry: buildDefaultRegistry()},
  1086  					nil,
  1087  					bsonrwtest.WriteDocumentEnd,
  1088  					nil,
  1089  				},
  1090  				{
  1091  					"nil interface value",
  1092  					struct{ Foo myInterface }{Foo: nil},
  1093  					&EncodeContext{Registry: buildDefaultRegistry()},
  1094  					nil,
  1095  					bsonrwtest.WriteDocumentEnd,
  1096  					nil,
  1097  				},
  1098  			},
  1099  		},
  1100  		{
  1101  			"CodeWithScopeEncodeValue",
  1102  			ValueEncoderFunc(dve.CodeWithScopeEncodeValue),
  1103  			[]subtest{
  1104  				{
  1105  					"wrong type",
  1106  					wrong,
  1107  					nil,
  1108  					nil,
  1109  					bsonrwtest.Nothing,
  1110  					ValueEncoderError{
  1111  						Name:     "CodeWithScopeEncodeValue",
  1112  						Types:    []reflect.Type{tCodeWithScope},
  1113  						Received: reflect.ValueOf(wrong),
  1114  					},
  1115  				},
  1116  				{
  1117  					"WriteCodeWithScope error",
  1118  					primitive.CodeWithScope{},
  1119  					nil,
  1120  					&bsonrwtest.ValueReaderWriter{Err: errors.New("wcws error"), ErrAfter: bsonrwtest.WriteCodeWithScope},
  1121  					bsonrwtest.WriteCodeWithScope,
  1122  					errors.New("wcws error"),
  1123  				},
  1124  				{
  1125  					"CodeWithScope/success",
  1126  					primitive.CodeWithScope{
  1127  						Code:  "var hello = 'world';",
  1128  						Scope: primitive.D{},
  1129  					},
  1130  					&EncodeContext{Registry: buildDefaultRegistry()},
  1131  					nil, bsonrwtest.WriteDocumentEnd, nil,
  1132  				},
  1133  			},
  1134  		},
  1135  		{
  1136  			"CoreArrayEncodeValue",
  1137  			defaultArrayCodec,
  1138  			[]subtest{
  1139  				{
  1140  					"wrong type",
  1141  					wrong,
  1142  					nil,
  1143  					nil,
  1144  					bsonrwtest.Nothing,
  1145  					ValueEncoderError{
  1146  						Name:     "CoreArrayEncodeValue",
  1147  						Types:    []reflect.Type{tCoreArray},
  1148  						Received: reflect.ValueOf(wrong),
  1149  					},
  1150  				},
  1151  
  1152  				{
  1153  					"WriteArray Error",
  1154  					bsoncore.Array{},
  1155  					nil,
  1156  					&bsonrwtest.ValueReaderWriter{Err: errors.New("wa error"), ErrAfter: bsonrwtest.WriteArray},
  1157  					bsonrwtest.WriteArray,
  1158  					errors.New("wa error"),
  1159  				},
  1160  				{
  1161  					"WriteArrayElement Error",
  1162  					bsoncore.Array(buildDocumentArray(func(doc []byte) []byte {
  1163  						return bsoncore.AppendNullElement(nil, "foo")
  1164  					})),
  1165  					nil,
  1166  					&bsonrwtest.ValueReaderWriter{Err: errors.New("wae error"), ErrAfter: bsonrwtest.WriteArrayElement},
  1167  					bsonrwtest.WriteArrayElement,
  1168  					errors.New("wae error"),
  1169  				},
  1170  				{
  1171  					"encodeValue error",
  1172  					bsoncore.Array(buildDocumentArray(func(doc []byte) []byte {
  1173  						return bsoncore.AppendNullElement(nil, "foo")
  1174  					})),
  1175  					nil,
  1176  					&bsonrwtest.ValueReaderWriter{Err: errors.New("ev error"), ErrAfter: bsonrwtest.WriteNull},
  1177  					bsonrwtest.WriteNull,
  1178  					errors.New("ev error"),
  1179  				},
  1180  			},
  1181  		},
  1182  	}
  1183  
  1184  	for _, tc := range testCases {
  1185  		t.Run(tc.name, func(t *testing.T) {
  1186  			for _, subtest := range tc.subtests {
  1187  				t.Run(subtest.name, func(t *testing.T) {
  1188  					var ec EncodeContext
  1189  					if subtest.ectx != nil {
  1190  						ec = *subtest.ectx
  1191  					}
  1192  					llvrw := new(bsonrwtest.ValueReaderWriter)
  1193  					if subtest.llvrw != nil {
  1194  						llvrw = subtest.llvrw
  1195  					}
  1196  					llvrw.T = t
  1197  					err := tc.ve.EncodeValue(ec, llvrw, reflect.ValueOf(subtest.val))
  1198  					if !compareErrors(err, subtest.err) {
  1199  						t.Errorf("Errors do not match. got %v; want %v", err, subtest.err)
  1200  					}
  1201  					invoked := llvrw.Invoked
  1202  					if !cmp.Equal(invoked, subtest.invoke) {
  1203  						t.Errorf("Incorrect method invoked. got %v; want %v", invoked, subtest.invoke)
  1204  					}
  1205  				})
  1206  			}
  1207  		})
  1208  	}
  1209  
  1210  	t.Run("success path", func(t *testing.T) {
  1211  		oid := primitive.NewObjectID()
  1212  		oids := []primitive.ObjectID{primitive.NewObjectID(), primitive.NewObjectID(), primitive.NewObjectID()}
  1213  		var str = new(string)
  1214  		*str = "bar"
  1215  		now := time.Now().Truncate(time.Millisecond)
  1216  		murl, err := url.Parse("https://mongodb.com/random-url?hello=world")
  1217  		if err != nil {
  1218  			t.Errorf("Error parsing URL: %v", err)
  1219  			t.FailNow()
  1220  		}
  1221  		decimal128, err := primitive.ParseDecimal128("1.5e10")
  1222  		if err != nil {
  1223  			t.Errorf("Error parsing decimal128: %v", err)
  1224  			t.FailNow()
  1225  		}
  1226  
  1227  		testCases := []struct {
  1228  			name  string
  1229  			value interface{}
  1230  			b     []byte
  1231  			err   error
  1232  		}{
  1233  			{
  1234  				"map[string]int",
  1235  				map[string]int32{"foo": 1},
  1236  				[]byte{
  1237  					0x0E, 0x00, 0x00, 0x00,
  1238  					0x10, 'f', 'o', 'o', 0x00,
  1239  					0x01, 0x00, 0x00, 0x00,
  1240  					0x00,
  1241  				},
  1242  				nil,
  1243  			},
  1244  			{
  1245  				"map[string]primitive.ObjectID",
  1246  				map[string]primitive.ObjectID{"foo": oid},
  1247  				buildDocument(bsoncore.AppendObjectIDElement(nil, "foo", oid)),
  1248  				nil,
  1249  			},
  1250  			{
  1251  				"map[string][]int32",
  1252  				map[string][]int32{"Z": {1, 2, 3}},
  1253  				buildDocumentArray(func(doc []byte) []byte {
  1254  					doc = bsoncore.AppendInt32Element(doc, "0", 1)
  1255  					doc = bsoncore.AppendInt32Element(doc, "1", 2)
  1256  					return bsoncore.AppendInt32Element(doc, "2", 3)
  1257  				}),
  1258  				nil,
  1259  			},
  1260  			{
  1261  				"map[string][]primitive.ObjectID",
  1262  				map[string][]primitive.ObjectID{"Z": oids},
  1263  				buildDocumentArray(func(doc []byte) []byte {
  1264  					doc = bsoncore.AppendObjectIDElement(doc, "0", oids[0])
  1265  					doc = bsoncore.AppendObjectIDElement(doc, "1", oids[1])
  1266  					return bsoncore.AppendObjectIDElement(doc, "2", oids[2])
  1267  				}),
  1268  				nil,
  1269  			},
  1270  			{
  1271  				"map[string][]json.Number(int64)",
  1272  				map[string][]json.Number{"Z": {json.Number("5"), json.Number("10")}},
  1273  				buildDocumentArray(func(doc []byte) []byte {
  1274  					doc = bsoncore.AppendInt64Element(doc, "0", 5)
  1275  					return bsoncore.AppendInt64Element(doc, "1", 10)
  1276  				}),
  1277  				nil,
  1278  			},
  1279  			{
  1280  				"map[string][]json.Number(float64)",
  1281  				map[string][]json.Number{"Z": {json.Number("5"), json.Number("10.1")}},
  1282  				buildDocumentArray(func(doc []byte) []byte {
  1283  					doc = bsoncore.AppendInt64Element(doc, "0", 5)
  1284  					return bsoncore.AppendDoubleElement(doc, "1", 10.1)
  1285  				}),
  1286  				nil,
  1287  			},
  1288  			{
  1289  				"map[string][]*url.URL",
  1290  				map[string][]*url.URL{"Z": {murl}},
  1291  				buildDocumentArray(func(doc []byte) []byte {
  1292  					return bsoncore.AppendStringElement(doc, "0", murl.String())
  1293  				}),
  1294  				nil,
  1295  			},
  1296  			{
  1297  				"map[string][]primitive.Decimal128",
  1298  				map[string][]primitive.Decimal128{"Z": {decimal128}},
  1299  				buildDocumentArray(func(doc []byte) []byte {
  1300  					return bsoncore.AppendDecimal128Element(doc, "0", decimal128)
  1301  				}),
  1302  				nil,
  1303  			},
  1304  			{
  1305  				"-",
  1306  				struct {
  1307  					A string `bson:"-"`
  1308  				}{
  1309  					A: "",
  1310  				},
  1311  				[]byte{0x05, 0x00, 0x00, 0x00, 0x00},
  1312  				nil,
  1313  			},
  1314  			{
  1315  				"omitempty",
  1316  				struct {
  1317  					A string `bson:",omitempty"`
  1318  				}{
  1319  					A: "",
  1320  				},
  1321  				[]byte{0x05, 0x00, 0x00, 0x00, 0x00},
  1322  				nil,
  1323  			},
  1324  			{
  1325  				"omitempty, empty time",
  1326  				struct {
  1327  					A time.Time `bson:",omitempty"`
  1328  				}{
  1329  					A: time.Time{},
  1330  				},
  1331  				[]byte{0x05, 0x00, 0x00, 0x00, 0x00},
  1332  				nil,
  1333  			},
  1334  			{
  1335  				"no private fields",
  1336  				noPrivateFields{a: "should be empty"},
  1337  				[]byte{0x05, 0x00, 0x00, 0x00, 0x00},
  1338  				nil,
  1339  			},
  1340  			{
  1341  				"minsize",
  1342  				struct {
  1343  					A int64 `bson:",minsize"`
  1344  				}{
  1345  					A: 12345,
  1346  				},
  1347  				buildDocument(bsoncore.AppendInt32Element(nil, "a", 12345)),
  1348  				nil,
  1349  			},
  1350  			{
  1351  				"inline",
  1352  				struct {
  1353  					Foo struct {
  1354  						A int64 `bson:",minsize"`
  1355  					} `bson:",inline"`
  1356  				}{
  1357  					Foo: struct {
  1358  						A int64 `bson:",minsize"`
  1359  					}{
  1360  						A: 12345,
  1361  					},
  1362  				},
  1363  				buildDocument(bsoncore.AppendInt32Element(nil, "a", 12345)),
  1364  				nil,
  1365  			},
  1366  			{
  1367  				"inline struct pointer",
  1368  				struct {
  1369  					Foo *struct {
  1370  						A int64 `bson:",minsize"`
  1371  					} `bson:",inline"`
  1372  					Bar *struct {
  1373  						B int64
  1374  					} `bson:",inline"`
  1375  				}{
  1376  					Foo: &struct {
  1377  						A int64 `bson:",minsize"`
  1378  					}{
  1379  						A: 12345,
  1380  					},
  1381  					Bar: nil,
  1382  				},
  1383  				buildDocument(bsoncore.AppendInt32Element(nil, "a", 12345)),
  1384  				nil,
  1385  			},
  1386  			{
  1387  				"nested inline struct pointer",
  1388  				struct {
  1389  					Foo *struct {
  1390  						Bar *struct {
  1391  							A int64 `bson:",minsize"`
  1392  						} `bson:",inline"`
  1393  					} `bson:",inline"`
  1394  				}{
  1395  					Foo: &struct {
  1396  						Bar *struct {
  1397  							A int64 `bson:",minsize"`
  1398  						} `bson:",inline"`
  1399  					}{
  1400  						Bar: &struct {
  1401  							A int64 `bson:",minsize"`
  1402  						}{
  1403  							A: 12345,
  1404  						},
  1405  					},
  1406  				},
  1407  				buildDocument(bsoncore.AppendInt32Element(nil, "a", 12345)),
  1408  				nil,
  1409  			},
  1410  			{
  1411  				"inline nil struct pointer",
  1412  				struct {
  1413  					Foo *struct {
  1414  						A int64 `bson:",minsize"`
  1415  					} `bson:",inline"`
  1416  				}{
  1417  					Foo: nil,
  1418  				},
  1419  				buildDocument([]byte{}),
  1420  				nil,
  1421  			},
  1422  			{
  1423  				"inline overwrite",
  1424  				struct {
  1425  					Foo struct {
  1426  						A int32
  1427  						B string
  1428  					} `bson:",inline"`
  1429  					A int64
  1430  				}{
  1431  					Foo: struct {
  1432  						A int32
  1433  						B string
  1434  					}{
  1435  						A: 0,
  1436  						B: "foo",
  1437  					},
  1438  					A: 54321,
  1439  				},
  1440  				buildDocument(func(doc []byte) []byte {
  1441  					doc = bsoncore.AppendStringElement(doc, "b", "foo")
  1442  					doc = bsoncore.AppendInt64Element(doc, "a", 54321)
  1443  					return doc
  1444  				}(nil)),
  1445  				nil,
  1446  			},
  1447  			{
  1448  				"inline overwrite respects ordering",
  1449  				struct {
  1450  					A   int64
  1451  					Foo struct {
  1452  						A int32
  1453  						B string
  1454  					} `bson:",inline"`
  1455  				}{
  1456  					A: 54321,
  1457  					Foo: struct {
  1458  						A int32
  1459  						B string
  1460  					}{
  1461  						A: 0,
  1462  						B: "foo",
  1463  					},
  1464  				},
  1465  				buildDocument(func(doc []byte) []byte {
  1466  					doc = bsoncore.AppendInt64Element(doc, "a", 54321)
  1467  					doc = bsoncore.AppendStringElement(doc, "b", "foo")
  1468  					return doc
  1469  				}(nil)),
  1470  				nil,
  1471  			},
  1472  			{
  1473  				"inline overwrite with nested structs",
  1474  				struct {
  1475  					Foo struct {
  1476  						A int32
  1477  					} `bson:",inline"`
  1478  					Bar struct {
  1479  						A int32
  1480  					} `bson:",inline"`
  1481  					A int64
  1482  				}{
  1483  					Foo: struct {
  1484  						A int32
  1485  					}{},
  1486  					Bar: struct {
  1487  						A int32
  1488  					}{},
  1489  					A: 54321,
  1490  				},
  1491  				buildDocument(bsoncore.AppendInt64Element(nil, "a", 54321)),
  1492  				nil,
  1493  			},
  1494  			{
  1495  				"inline map",
  1496  				struct {
  1497  					Foo map[string]string `bson:",inline"`
  1498  				}{
  1499  					Foo: map[string]string{"foo": "bar"},
  1500  				},
  1501  				buildDocument(bsoncore.AppendStringElement(nil, "foo", "bar")),
  1502  				nil,
  1503  			},
  1504  			{
  1505  				"alternate name bson:name",
  1506  				struct {
  1507  					A string `bson:"foo"`
  1508  				}{
  1509  					A: "bar",
  1510  				},
  1511  				buildDocument(bsoncore.AppendStringElement(nil, "foo", "bar")),
  1512  				nil,
  1513  			},
  1514  			{
  1515  				"alternate name",
  1516  				struct {
  1517  					A string `bson:"foo"`
  1518  				}{
  1519  					A: "bar",
  1520  				},
  1521  				buildDocument(bsoncore.AppendStringElement(nil, "foo", "bar")),
  1522  				nil,
  1523  			},
  1524  			{
  1525  				"inline, omitempty",
  1526  				struct {
  1527  					A   string
  1528  					Foo zeroTest `bson:"omitempty,inline"`
  1529  				}{
  1530  					A:   "bar",
  1531  					Foo: zeroTest{true},
  1532  				},
  1533  				buildDocument(bsoncore.AppendStringElement(nil, "a", "bar")),
  1534  				nil,
  1535  			},
  1536  			{
  1537  				"struct{}",
  1538  				struct {
  1539  					A bool
  1540  					B int32
  1541  					C int64
  1542  					D uint16
  1543  					E uint64
  1544  					F float64
  1545  					G string
  1546  					H map[string]string
  1547  					I []byte
  1548  					K [2]string
  1549  					L struct {
  1550  						M string
  1551  					}
  1552  					Q  primitive.ObjectID
  1553  					T  []struct{}
  1554  					Y  json.Number
  1555  					Z  time.Time
  1556  					AA json.Number
  1557  					AB *url.URL
  1558  					AC primitive.Decimal128
  1559  					AD *time.Time
  1560  					AE testValueMarshaler
  1561  					AF Proxy
  1562  					AG testProxy
  1563  					AH map[string]interface{}
  1564  					AI primitive.CodeWithScope
  1565  				}{
  1566  					A: true,
  1567  					B: 123,
  1568  					C: 456,
  1569  					D: 789,
  1570  					E: 101112,
  1571  					F: 3.14159,
  1572  					G: "Hello, world",
  1573  					H: map[string]string{"foo": "bar"},
  1574  					I: []byte{0x01, 0x02, 0x03},
  1575  					K: [2]string{"baz", "qux"},
  1576  					L: struct {
  1577  						M string
  1578  					}{
  1579  						M: "foobar",
  1580  					},
  1581  					Q:  oid,
  1582  					T:  nil,
  1583  					Y:  json.Number("5"),
  1584  					Z:  now,
  1585  					AA: json.Number("10.1"),
  1586  					AB: murl,
  1587  					AC: decimal128,
  1588  					AD: &now,
  1589  					AE: testValueMarshaler{t: bsontype.String, buf: bsoncore.AppendString(nil, "hello, world")},
  1590  					AF: testProxy{ret: struct{ Hello string }{Hello: "world!"}},
  1591  					AG: testProxy{ret: struct{ Pi float64 }{Pi: 3.14159}},
  1592  					AH: nil,
  1593  					AI: primitive.CodeWithScope{Code: "var hello = 'world';", Scope: primitive.D{{"pi", 3.14159}}},
  1594  				},
  1595  				buildDocument(func(doc []byte) []byte {
  1596  					doc = bsoncore.AppendBooleanElement(doc, "a", true)
  1597  					doc = bsoncore.AppendInt32Element(doc, "b", 123)
  1598  					doc = bsoncore.AppendInt64Element(doc, "c", 456)
  1599  					doc = bsoncore.AppendInt32Element(doc, "d", 789)
  1600  					doc = bsoncore.AppendInt64Element(doc, "e", 101112)
  1601  					doc = bsoncore.AppendDoubleElement(doc, "f", 3.14159)
  1602  					doc = bsoncore.AppendStringElement(doc, "g", "Hello, world")
  1603  					doc = bsoncore.AppendDocumentElement(doc, "h", buildDocument(bsoncore.AppendStringElement(nil, "foo", "bar")))
  1604  					doc = bsoncore.AppendBinaryElement(doc, "i", 0x00, []byte{0x01, 0x02, 0x03})
  1605  					doc = bsoncore.AppendArrayElement(doc, "k",
  1606  						buildArray(bsoncore.AppendStringElement(bsoncore.AppendStringElement(nil, "0", "baz"), "1", "qux")),
  1607  					)
  1608  					doc = bsoncore.AppendDocumentElement(doc, "l", buildDocument(bsoncore.AppendStringElement(nil, "m", "foobar")))
  1609  					doc = bsoncore.AppendObjectIDElement(doc, "q", oid)
  1610  					doc = bsoncore.AppendNullElement(doc, "t")
  1611  					doc = bsoncore.AppendInt64Element(doc, "y", 5)
  1612  					doc = bsoncore.AppendDateTimeElement(doc, "z", now.UnixNano()/int64(time.Millisecond))
  1613  					doc = bsoncore.AppendDoubleElement(doc, "aa", 10.1)
  1614  					doc = bsoncore.AppendStringElement(doc, "ab", murl.String())
  1615  					doc = bsoncore.AppendDecimal128Element(doc, "ac", decimal128)
  1616  					doc = bsoncore.AppendDateTimeElement(doc, "ad", now.UnixNano()/int64(time.Millisecond))
  1617  					doc = bsoncore.AppendStringElement(doc, "ae", "hello, world")
  1618  					doc = bsoncore.AppendDocumentElement(doc, "af", buildDocument(bsoncore.AppendStringElement(nil, "hello", "world!")))
  1619  					doc = bsoncore.AppendDocumentElement(doc, "ag", buildDocument(bsoncore.AppendDoubleElement(nil, "pi", 3.14159)))
  1620  					doc = bsoncore.AppendNullElement(doc, "ah")
  1621  					doc = bsoncore.AppendCodeWithScopeElement(doc, "ai",
  1622  						"var hello = 'world';", buildDocument(bsoncore.AppendDoubleElement(nil, "pi", 3.14159)),
  1623  					)
  1624  					return doc
  1625  				}(nil)),
  1626  				nil,
  1627  			},
  1628  			{
  1629  				"struct{[]interface{}}",
  1630  				struct {
  1631  					A []bool
  1632  					B []int32
  1633  					C []int64
  1634  					D []uint16
  1635  					E []uint64
  1636  					F []float64
  1637  					G []string
  1638  					H []map[string]string
  1639  					I [][]byte
  1640  					K [1][2]string
  1641  					L []struct {
  1642  						M string
  1643  					}
  1644  					N  [][]string
  1645  					R  []primitive.ObjectID
  1646  					T  []struct{}
  1647  					W  []map[string]struct{}
  1648  					X  []map[string]struct{}
  1649  					Y  []map[string]struct{}
  1650  					Z  []time.Time
  1651  					AA []json.Number
  1652  					AB []*url.URL
  1653  					AC []primitive.Decimal128
  1654  					AD []*time.Time
  1655  					AE []testValueMarshaler
  1656  					AF []Proxy
  1657  					AG []testProxy
  1658  				}{
  1659  					A: []bool{true},
  1660  					B: []int32{123},
  1661  					C: []int64{456},
  1662  					D: []uint16{789},
  1663  					E: []uint64{101112},
  1664  					F: []float64{3.14159},
  1665  					G: []string{"Hello, world"},
  1666  					H: []map[string]string{{"foo": "bar"}},
  1667  					I: [][]byte{{0x01, 0x02, 0x03}},
  1668  					K: [1][2]string{{"baz", "qux"}},
  1669  					L: []struct {
  1670  						M string
  1671  					}{
  1672  						{
  1673  							M: "foobar",
  1674  						},
  1675  					},
  1676  					N:  [][]string{{"foo", "bar"}},
  1677  					R:  oids,
  1678  					T:  nil,
  1679  					W:  nil,
  1680  					X:  []map[string]struct{}{},   // Should be empty BSON Array
  1681  					Y:  []map[string]struct{}{{}}, // Should be BSON array with one element, an empty BSON SubDocument
  1682  					Z:  []time.Time{now, now},
  1683  					AA: []json.Number{json.Number("5"), json.Number("10.1")},
  1684  					AB: []*url.URL{murl},
  1685  					AC: []primitive.Decimal128{decimal128},
  1686  					AD: []*time.Time{&now, &now},
  1687  					AE: []testValueMarshaler{
  1688  						{t: bsontype.String, buf: bsoncore.AppendString(nil, "hello")},
  1689  						{t: bsontype.String, buf: bsoncore.AppendString(nil, "world")},
  1690  					},
  1691  					AF: []Proxy{
  1692  						testProxy{ret: struct{ Hello string }{Hello: "world!"}},
  1693  						testProxy{ret: struct{ Foo string }{Foo: "bar"}},
  1694  					},
  1695  					AG: []testProxy{
  1696  						{ret: struct{ One int64 }{One: 1234567890}},
  1697  						{ret: struct{ Pi float64 }{Pi: 3.14159}},
  1698  					},
  1699  				},
  1700  				buildDocument(func(doc []byte) []byte {
  1701  					doc = appendArrayElement(doc, "a", bsoncore.AppendBooleanElement(nil, "0", true))
  1702  					doc = appendArrayElement(doc, "b", bsoncore.AppendInt32Element(nil, "0", 123))
  1703  					doc = appendArrayElement(doc, "c", bsoncore.AppendInt64Element(nil, "0", 456))
  1704  					doc = appendArrayElement(doc, "d", bsoncore.AppendInt32Element(nil, "0", 789))
  1705  					doc = appendArrayElement(doc, "e", bsoncore.AppendInt64Element(nil, "0", 101112))
  1706  					doc = appendArrayElement(doc, "f", bsoncore.AppendDoubleElement(nil, "0", 3.14159))
  1707  					doc = appendArrayElement(doc, "g", bsoncore.AppendStringElement(nil, "0", "Hello, world"))
  1708  					doc = appendArrayElement(doc, "h", bsoncore.BuildDocumentElement(nil, "0", bsoncore.AppendStringElement(nil, "foo", "bar")))
  1709  					doc = appendArrayElement(doc, "i", bsoncore.AppendBinaryElement(nil, "0", 0x00, []byte{0x01, 0x02, 0x03}))
  1710  					doc = appendArrayElement(doc, "k",
  1711  						appendArrayElement(nil, "0",
  1712  							bsoncore.AppendStringElement(bsoncore.AppendStringElement(nil, "0", "baz"), "1", "qux")),
  1713  					)
  1714  					doc = appendArrayElement(doc, "l", bsoncore.BuildDocumentElement(nil, "0", bsoncore.AppendStringElement(nil, "m", "foobar")))
  1715  					doc = appendArrayElement(doc, "n",
  1716  						appendArrayElement(nil, "0",
  1717  							bsoncore.AppendStringElement(bsoncore.AppendStringElement(nil, "0", "foo"), "1", "bar")),
  1718  					)
  1719  					doc = appendArrayElement(doc, "r",
  1720  						bsoncore.AppendObjectIDElement(
  1721  							bsoncore.AppendObjectIDElement(
  1722  								bsoncore.AppendObjectIDElement(nil,
  1723  									"0", oids[0]),
  1724  								"1", oids[1]),
  1725  							"2", oids[2]),
  1726  					)
  1727  					doc = bsoncore.AppendNullElement(doc, "t")
  1728  					doc = bsoncore.AppendNullElement(doc, "w")
  1729  					doc = appendArrayElement(doc, "x", nil)
  1730  					doc = appendArrayElement(doc, "y", bsoncore.BuildDocumentElement(nil, "0", nil))
  1731  					doc = appendArrayElement(doc, "z",
  1732  						bsoncore.AppendDateTimeElement(
  1733  							bsoncore.AppendDateTimeElement(
  1734  								nil, "0", now.UnixNano()/int64(time.Millisecond)),
  1735  							"1", now.UnixNano()/int64(time.Millisecond)),
  1736  					)
  1737  					doc = appendArrayElement(doc, "aa", bsoncore.AppendDoubleElement(bsoncore.AppendInt64Element(nil, "0", 5), "1", 10.10))
  1738  					doc = appendArrayElement(doc, "ab", bsoncore.AppendStringElement(nil, "0", murl.String()))
  1739  					doc = appendArrayElement(doc, "ac", bsoncore.AppendDecimal128Element(nil, "0", decimal128))
  1740  					doc = appendArrayElement(doc, "ad",
  1741  						bsoncore.AppendDateTimeElement(
  1742  							bsoncore.AppendDateTimeElement(nil, "0", now.UnixNano()/int64(time.Millisecond)),
  1743  							"1", now.UnixNano()/int64(time.Millisecond)),
  1744  					)
  1745  					doc = appendArrayElement(doc, "ae",
  1746  						bsoncore.AppendStringElement(bsoncore.AppendStringElement(nil, "0", "hello"), "1", "world"),
  1747  					)
  1748  					doc = appendArrayElement(doc, "af",
  1749  						bsoncore.AppendDocumentElement(
  1750  							bsoncore.AppendDocumentElement(nil, "0",
  1751  								bsoncore.BuildDocument(nil, bsoncore.AppendStringElement(nil, "hello", "world!")),
  1752  							), "1",
  1753  							bsoncore.BuildDocument(nil, bsoncore.AppendStringElement(nil, "foo", "bar")),
  1754  						),
  1755  					)
  1756  					doc = appendArrayElement(doc, "ag",
  1757  						bsoncore.AppendDocumentElement(
  1758  							bsoncore.AppendDocumentElement(nil, "0",
  1759  								bsoncore.BuildDocument(nil, bsoncore.AppendInt64Element(nil, "one", 1234567890)),
  1760  							), "1",
  1761  							bsoncore.BuildDocument(nil, bsoncore.AppendDoubleElement(nil, "pi", 3.14159)),
  1762  						),
  1763  					)
  1764  					return doc
  1765  				}(nil)),
  1766  				nil,
  1767  			},
  1768  		}
  1769  
  1770  		for _, tc := range testCases {
  1771  			t.Run(tc.name, func(t *testing.T) {
  1772  				b := make(bsonrw.SliceWriter, 0, 512)
  1773  				vw, err := bsonrw.NewBSONValueWriter(&b)
  1774  				noerr(t, err)
  1775  				reg := buildDefaultRegistry()
  1776  				enc, err := reg.LookupEncoder(reflect.TypeOf(tc.value))
  1777  				noerr(t, err)
  1778  				err = enc.EncodeValue(EncodeContext{Registry: reg}, vw, reflect.ValueOf(tc.value))
  1779  				if !errors.Is(err, tc.err) {
  1780  					t.Errorf("Did not receive expected error. got %v; want %v", err, tc.err)
  1781  				}
  1782  				if diff := cmp.Diff([]byte(b), tc.b); diff != "" {
  1783  					t.Errorf("Bytes written differ: (-got +want)\n%s", diff)
  1784  					t.Errorf("Bytes\ngot: %v\nwant:%v\n", b, tc.b)
  1785  					t.Errorf("Readers\ngot: %v\nwant:%v\n", bsoncore.Document(b), bsoncore.Document(tc.b))
  1786  				}
  1787  			})
  1788  		}
  1789  	})
  1790  
  1791  	t.Run("error path", func(t *testing.T) {
  1792  		testCases := []struct {
  1793  			name  string
  1794  			value interface{}
  1795  			err   error
  1796  		}{
  1797  			{
  1798  				"duplicate name struct",
  1799  				struct {
  1800  					A int64
  1801  					B int64 `bson:"a"`
  1802  				}{
  1803  					A: 0,
  1804  					B: 54321,
  1805  				},
  1806  				fmt.Errorf("duplicated key a"),
  1807  			},
  1808  			{
  1809  				"inline map",
  1810  				struct {
  1811  					Foo map[string]string `bson:",inline"`
  1812  					Baz string
  1813  				}{
  1814  					Foo: map[string]string{"baz": "bar"},
  1815  					Baz: "hi",
  1816  				},
  1817  				fmt.Errorf("Key baz of inlined map conflicts with a struct field name"),
  1818  			},
  1819  		}
  1820  
  1821  		for _, tc := range testCases {
  1822  			t.Run(tc.name, func(t *testing.T) {
  1823  				b := make(bsonrw.SliceWriter, 0, 512)
  1824  				vw, err := bsonrw.NewBSONValueWriter(&b)
  1825  				noerr(t, err)
  1826  				reg := buildDefaultRegistry()
  1827  				enc, err := reg.LookupEncoder(reflect.TypeOf(tc.value))
  1828  				noerr(t, err)
  1829  				err = enc.EncodeValue(EncodeContext{Registry: reg}, vw, reflect.ValueOf(tc.value))
  1830  				if err == nil || !strings.Contains(err.Error(), tc.err.Error()) {
  1831  					t.Errorf("Did not receive expected error. got %v; want %v", err, tc.err)
  1832  				}
  1833  			})
  1834  		}
  1835  	})
  1836  
  1837  	t.Run("EmptyInterfaceEncodeValue/nil", func(t *testing.T) {
  1838  		val := reflect.New(tEmpty).Elem()
  1839  		llvrw := new(bsonrwtest.ValueReaderWriter)
  1840  		err := dve.EmptyInterfaceEncodeValue(EncodeContext{Registry: NewRegistryBuilder().Build()}, llvrw, val)
  1841  		noerr(t, err)
  1842  		if llvrw.Invoked != bsonrwtest.WriteNull {
  1843  			t.Errorf("Incorrect method called. got %v; want %v", llvrw.Invoked, bsonrwtest.WriteNull)
  1844  		}
  1845  	})
  1846  
  1847  	t.Run("EmptyInterfaceEncodeValue/LookupEncoder error", func(t *testing.T) {
  1848  		val := reflect.New(tEmpty).Elem()
  1849  		val.Set(reflect.ValueOf(int64(1234567890)))
  1850  		llvrw := new(bsonrwtest.ValueReaderWriter)
  1851  		got := dve.EmptyInterfaceEncodeValue(EncodeContext{Registry: NewRegistryBuilder().Build()}, llvrw, val)
  1852  		want := ErrNoEncoder{Type: tInt64}
  1853  		if !compareErrors(got, want) {
  1854  			t.Errorf("Did not receive expected error. got %v; want %v", got, want)
  1855  		}
  1856  	})
  1857  }
  1858  
  1859  type testValueMarshaler struct {
  1860  	t   bsontype.Type
  1861  	buf []byte
  1862  	err error
  1863  }
  1864  
  1865  func (tvm testValueMarshaler) MarshalBSONValue() (bsontype.Type, []byte, error) {
  1866  	return tvm.t, tvm.buf, tvm.err
  1867  }
  1868  
  1869  type testValueMarshalPtr struct {
  1870  	t   bsontype.Type
  1871  	buf []byte
  1872  	err error
  1873  }
  1874  
  1875  func (tvm *testValueMarshalPtr) MarshalBSONValue() (bsontype.Type, []byte, error) {
  1876  	return tvm.t, tvm.buf, tvm.err
  1877  }
  1878  
  1879  type testMarshaler struct {
  1880  	buf []byte
  1881  	err error
  1882  }
  1883  
  1884  func (tvm testMarshaler) MarshalBSON() ([]byte, error) {
  1885  	return tvm.buf, tvm.err
  1886  }
  1887  
  1888  type testMarshalPtr struct {
  1889  	buf []byte
  1890  	err error
  1891  }
  1892  
  1893  func (tvm *testMarshalPtr) MarshalBSON() ([]byte, error) {
  1894  	return tvm.buf, tvm.err
  1895  }
  1896  
  1897  type testProxy struct {
  1898  	ret interface{}
  1899  	err error
  1900  }
  1901  
  1902  func (tp testProxy) ProxyBSON() (interface{}, error) { return tp.ret, tp.err }
  1903  
  1904  type testProxyPtr struct {
  1905  	ret interface{}
  1906  	err error
  1907  }
  1908  
  1909  func (tp *testProxyPtr) ProxyBSON() (interface{}, error) { return tp.ret, tp.err }
  1910  

View as plain text