From d9a1e55b65064bc0324e5b7fc3540ed48b16e441 Mon Sep 17 00:00:00 2001 From: Qingyang Hu Date: Fri, 1 Dec 2023 19:15:04 -0500 Subject: [PATCH] WIP --- bson/marshal.go | 22 ----- bson/mgocompat/bson_test.go | 191 ++++++++++++++++++++++++++++-------- 2 files changed, 148 insertions(+), 65 deletions(-) diff --git a/bson/marshal.go b/bson/marshal.go index aa1d82bffe..a4671da680 100644 --- a/bson/marshal.go +++ b/bson/marshal.go @@ -64,28 +64,6 @@ func Marshal(val interface{}) ([]byte, error) { return buf.Bytes(), nil } -// MarshalWithRegistry returns the BSON encoding of val as a BSON document. If val is not a type that can be transformed -// into a document, MarshalValueWithRegistry should be used instead. -// -// Deprecated: Use [NewEncoder] and specify the Registry by calling [Encoder.SetRegistry] instead: -// -// buf := new(bytes.Buffer) -// vw, err := bsonrw.NewBSONValueWriter(buf) -// if err != nil { -// panic(err) -// } -// enc, err := bson.NewEncoder(vw) -// if err != nil { -// panic(err) -// } -// enc.SetRegistry(reg) -// -// See [Encoder] for more examples. -func MarshalWithRegistry(r *bsoncodec.Registry, val interface{}) ([]byte, error) { - dst := make([]byte, 0) - return MarshalAppendWithRegistry(r, dst, val) -} - // MarshalWithContext returns the BSON encoding of val as a BSON document using EncodeContext ec. If val is not a type // that can be transformed into a document, MarshalValueWithContext should be used instead. // diff --git a/bson/mgocompat/bson_test.go b/bson/mgocompat/bson_test.go index 949420bd6d..4ef95d4560 100644 --- a/bson/mgocompat/bson_test.go +++ b/bson/mgocompat/bson_test.go @@ -294,12 +294,18 @@ func TestPtrInline(t *testing.T) { }, } + buf := new(bytes.Buffer) for i, cs := range cases { t.Run(strconv.Itoa(i), func(t *testing.T) { - data, err := bson.MarshalWithRegistry(Registry, cs.In) + buf.Reset() + vw, err := bsonrw.NewBSONValueWriter(buf) + assert.Nil(t, err, "expected nil error, got: %v", err) + enc := bson.NewEncoder(vw) + enc.SetRegistry(Registry) + err = enc.Encode(cs.In) assert.Nil(t, err, "expected nil error, got: %v", err) var dataBSON bson.M - err = bson.UnmarshalWithRegistry(Registry, data, &dataBSON) + err = bson.UnmarshalWithRegistry(Registry, buf.Bytes(), &dataBSON) assert.Nil(t, err, "expected nil error, got: %v", err) assert.True(t, reflect.DeepEqual(cs.Out, dataBSON), "expected: %v, got: %v", cs.Out, dataBSON) @@ -377,12 +383,18 @@ var oneWayMarshalItems = []testItemType{ } func TestOneWayMarshalItems(t *testing.T) { + buf := new(bytes.Buffer) for i, item := range oneWayMarshalItems { t.Run(strconv.Itoa(i), func(t *testing.T) { - data, err := bson.MarshalWithRegistry(Registry, item.obj) + buf.Reset() + vw, err := bsonrw.NewBSONValueWriter(buf) + assert.Nil(t, err, "expected nil error, got: %v", err) + enc := bson.NewEncoder(vw) + enc.SetRegistry(Registry) + err = enc.Encode(item.obj) assert.Nil(t, err, "expected nil error, got: %v", err) - assert.Equal(t, wrapInDoc(item.data), string(data), "expected: %v, got: %v", bson.Raw(wrapInDoc(item.data)), bson.Raw(data)) + assert.Equal(t, wrapInDoc(item.data), buf.String(), "expected: %v, got: %v", bson.Raw(wrapInDoc(item.data)), bson.Raw(buf.Bytes())) }) } } @@ -408,11 +420,17 @@ var structSampleItems = []testItemType{ } func TestMarshalStructSampleItems(t *testing.T) { + buf := new(bytes.Buffer) for i, item := range structSampleItems { t.Run(strconv.Itoa(i), func(t *testing.T) { - data, err := bson.MarshalWithRegistry(Registry, item.obj) + buf.Reset() + vw, err := bsonrw.NewBSONValueWriter(buf) + assert.Nil(t, err, "expected nil error, got: %v", err) + enc := bson.NewEncoder(vw) + enc.SetRegistry(Registry) + err = enc.Encode(item.obj) assert.Nil(t, err, "expected nil error, got: %v", err) - assert.Equal(t, item.data, string(data), "expected: %v, got: %v", item.data, string(data)) + assert.Equal(t, item.data, buf.String(), "expected: %v, got: %v", item.data, buf.String()) }) } } @@ -428,13 +446,18 @@ func TestUnmarshalStructSampleItems(t *testing.T) { func Test64bitInt(t *testing.T) { var i int64 = (1 << 31) if int(i) > 0 { - data, err := bson.MarshalWithRegistry(Registry, bson.M{"i": int(i)}) + buf := new(bytes.Buffer) + vw, err := bsonrw.NewBSONValueWriter(buf) + assert.Nil(t, err, "expected nil error, got: %v", err) + enc := bson.NewEncoder(vw) + enc.SetRegistry(Registry) + err = enc.Encode(bson.M{"i": int(i)}) assert.Nil(t, err, "expected nil error, got: %v", err) want := wrapInDoc("\x12i\x00\x00\x00\x00\x80\x00\x00\x00\x00") - assert.Equal(t, want, string(data), "expected: %v, got: %v", want, string(data)) + assert.Equal(t, want, buf.String(), "expected: %v, got: %v", want, buf.String()) var result struct{ I int } - err = bson.UnmarshalWithRegistry(Registry, data, &result) + err = bson.UnmarshalWithRegistry(Registry, buf.Bytes(), &result) assert.Nil(t, err, "expected nil error, got: %v", err) assert.Equal(t, i, int64(result.I), "expected: %v, got: %v", i, int64(result.I)) } @@ -564,11 +587,17 @@ var structItems = []testItemType{ } func TestMarshalStructItems(t *testing.T) { + buf := new(bytes.Buffer) for i, item := range structItems { t.Run(strconv.Itoa(i), func(t *testing.T) { - data, err := bson.MarshalWithRegistry(Registry, item.obj) + buf.Reset() + vw, err := bsonrw.NewBSONValueWriter(buf) assert.Nil(t, err, "expected nil error, got: %v", err) - assert.Equal(t, wrapInDoc(item.data), string(data), "expected: %v, got: %v", wrapInDoc(item.data), string(data)) + enc := bson.NewEncoder(vw) + enc.SetRegistry(Registry) + err = enc.Encode(item.obj) + assert.Nil(t, err, "expected nil error, got: %v", err) + assert.Equal(t, wrapInDoc(item.data), buf.String(), "expected: %v, got: %v", wrapInDoc(item.data), buf.String()) }) } } @@ -634,11 +663,17 @@ var marshalItems = []testItemType{ } func TestMarshalOneWayItems(t *testing.T) { + buf := new(bytes.Buffer) for i, item := range marshalItems { t.Run(strconv.Itoa(i), func(t *testing.T) { - data, err := bson.MarshalWithRegistry(Registry, item.obj) + buf.Reset() + vw, err := bsonrw.NewBSONValueWriter(buf) assert.Nil(t, err, "expected nil error, got: %v", err) - assert.Equal(t, wrapInDoc(item.data), string(data), "expected: %v, got: %v", wrapInDoc(item.data), string(data)) + enc := bson.NewEncoder(vw) + enc.SetRegistry(Registry) + err = enc.Encode(item.obj) + assert.Nil(t, err, "expected nil error, got: %v", err) + assert.Equal(t, wrapInDoc(item.data), buf.String(), "expected: %v, got: %v", wrapInDoc(item.data), buf.String()) }) } } @@ -741,12 +776,18 @@ var marshalErrorItems = []testItemType{ } func TestMarshalErrorItems(t *testing.T) { + buf := new(bytes.Buffer) for i, item := range marshalErrorItems { t.Run(strconv.Itoa(i), func(t *testing.T) { - data, err := bson.MarshalWithRegistry(Registry, item.obj) + buf.Reset() + vw, err := bsonrw.NewBSONValueWriter(buf) + assert.Nil(t, err, "expected nil error, got: %v", err) + enc := bson.NewEncoder(vw) + enc.SetRegistry(Registry) + err = enc.Encode(item.obj) assert.NotNil(t, err, "expected error") - assert.Nil(t, data, " expected nil data, got: %v", data) + assert.Nil(t, buf.Bytes(), " expected nil data, got: %v", buf.Bytes()) }) } } @@ -1000,11 +1041,16 @@ func TestUnmarshalSetterErrSetZero(t *testing.T) { setterResult["foo"] = ErrSetZero defer delete(setterResult, "field") - data, err := bson.MarshalWithRegistry(Registry, bson.M{"field": "foo"}) + buf := new(bytes.Buffer) + vw, err := bsonrw.NewBSONValueWriter(buf) + assert.Nil(t, err, "expected nil error, got: %v", err) + enc := bson.NewEncoder(vw) + enc.SetRegistry(Registry) + err = enc.Encode(bson.M{"field": "foo"}) assert.Nil(t, err, "expected nil error, got: %v", err) m := map[string]*setterType{} - err = bson.UnmarshalWithRegistry(Registry, data, m) + err = bson.UnmarshalWithRegistry(Registry, buf.Bytes(), m) assert.Nil(t, err, "expected nil error, got: %v", err) value, ok := m["field"] @@ -1032,27 +1078,38 @@ type docWithGetterField struct { } func TestMarshalAllItemsWithGetter(t *testing.T) { + buf := new(bytes.Buffer) for i, item := range allItems { if item.data == "" { continue } t.Run(strconv.Itoa(i), func(t *testing.T) { + buf.Reset() obj := &docWithGetterField{} obj.Field = &typeWithGetter{result: item.obj.(bson.M)["_"]} - data, err := bson.MarshalWithRegistry(Registry, obj) + vw, err := bsonrw.NewBSONValueWriter(buf) + assert.Nil(t, err, "expected nil error, got: %v", err) + enc := bson.NewEncoder(vw) + enc.SetRegistry(Registry) + err = enc.Encode(obj) assert.Nil(t, err, "expected nil error, got: %v", err) - assert.Equal(t, wrapInDoc(item.data), string(data), - "expected value at %v to be: %v, got: %v", i, wrapInDoc(item.data), string(data)) + assert.Equal(t, wrapInDoc(item.data), buf.String(), + "expected value at %v to be: %v, got: %v", i, wrapInDoc(item.data), buf.String()) }) } } func TestMarshalWholeDocumentWithGetter(t *testing.T) { obj := &typeWithGetter{result: sampleItems[0].obj} - data, err := bson.MarshalWithRegistry(Registry, obj) + buf := new(bytes.Buffer) + vw, err := bsonrw.NewBSONValueWriter(buf) + assert.Nil(t, err, "expected nil error, got: %v", err) + enc := bson.NewEncoder(vw) + enc.SetRegistry(Registry) + err = enc.Encode(obj) assert.Nil(t, err, "expected nil error, got: %v", err) - assert.Equal(t, sampleItems[0].data, string(data), - "expected: %v, got: %v", sampleItems[0].data, string(data)) + assert.Equal(t, sampleItems[0].data, buf.String(), + "expected: %v, got: %v", sampleItems[0].data, buf.String()) } func TestGetterErrors(t *testing.T) { @@ -1060,14 +1117,24 @@ func TestGetterErrors(t *testing.T) { obj1 := &docWithGetterField{} obj1.Field = &typeWithGetter{sampleItems[0].obj, e} - data, err := bson.MarshalWithRegistry(Registry, obj1) + buf := new(bytes.Buffer) + vw, err := bsonrw.NewBSONValueWriter(buf) + assert.Nil(t, err, "expected nil error, got: %v", err) + enc := bson.NewEncoder(vw) + enc.SetRegistry(Registry) + err = enc.Encode(obj1) assert.Equal(t, e, err, "expected error: %v, got: %v", e, err) - assert.Nil(t, data, "expected nil data, got: %v", data) + assert.Nil(t, buf.Bytes(), "expected nil data, got: %v", buf.Bytes()) obj2 := &typeWithGetter{sampleItems[0].obj, e} - data, err = bson.MarshalWithRegistry(Registry, obj2) + buf.Reset() + vw, err = bsonrw.NewBSONValueWriter(buf) + assert.Nil(t, err, "expected nil error, got: %v", err) + enc = bson.NewEncoder(vw) + enc.SetRegistry(Registry) + err = enc.Encode(obj2) assert.Equal(t, e, err, "expected error: %v, got: %v", e, err) - assert.Nil(t, data, "expected nil data, got: %v", data) + assert.Nil(t, buf.Bytes(), "expected nil data, got: %v", buf.Bytes()) } type intGetter int64 @@ -1082,20 +1149,30 @@ type typeWithIntGetter struct { func TestMarshalShortWithGetter(t *testing.T) { obj := typeWithIntGetter{42} - data, err := bson.MarshalWithRegistry(Registry, obj) + buf := new(bytes.Buffer) + vw, err := bsonrw.NewBSONValueWriter(buf) + assert.Nil(t, err, "expected nil error, got: %v", err) + enc := bson.NewEncoder(vw) + enc.SetRegistry(Registry) + err = enc.Encode(obj) assert.Nil(t, err, "expected nil error, got: %v", err) m := bson.M{} - err = bson.UnmarshalWithRegistry(Registry, data, &m) + err = bson.UnmarshalWithRegistry(Registry, buf.Bytes(), &m) assert.Nil(t, err, "expected nil error, got: %v", err) assert.Equal(t, 42, m["v"], "expected m[\"v\"] to be: %v, got: %v", 42, m["v"]) } func TestMarshalWithGetterNil(t *testing.T) { obj := docWithGetterField{} - data, err := bson.MarshalWithRegistry(Registry, obj) + buf := new(bytes.Buffer) + vw, err := bsonrw.NewBSONValueWriter(buf) + assert.Nil(t, err, "expected nil error, got: %v", err) + enc := bson.NewEncoder(vw) + enc.SetRegistry(Registry) + err = enc.Encode(obj) assert.Nil(t, err, "expected nil error, got: %v", err) m := bson.M{} - err = bson.UnmarshalWithRegistry(Registry, data, &m) + err = bson.UnmarshalWithRegistry(Registry, buf.Bytes(), &m) assert.Nil(t, err, "expected nil error, got: %v", err) want := bson.M{"_": ""} assert.Equal(t, want, m, "expected m[\"v\"] to be: %v, got: %v", want, m) @@ -1539,9 +1616,14 @@ var oneWayCrossItems = []crossTypeItem{ func testCrossPair(t *testing.T, dump interface{}, load interface{}) { zero := makeZeroDoc(load) - data, err := bson.MarshalWithRegistry(Registry, dump) + buf := new(bytes.Buffer) + vw, err := bsonrw.NewBSONValueWriter(buf) assert.Nil(t, err, "expected nil error, got: %v", err) - err = bson.UnmarshalWithRegistry(Registry, data, zero) + enc := bson.NewEncoder(vw) + enc.SetRegistry(Registry) + err = enc.Encode(dump) + assert.Nil(t, err, "expected nil error, got: %v", err) + err = bson.UnmarshalWithRegistry(Registry, buf.Bytes(), zero) assert.Nil(t, err, "expected nil error, got: %v", err) assert.True(t, reflect.DeepEqual(load, zero), "expected: %v, got: %v", load, zero) @@ -1649,11 +1731,17 @@ func TestMarshalNotRespectNil(t *testing.T) { assert.Nil(t, testStruct1.BSlice, "expected nil byte slice, got: %v", testStruct1.BSlice) assert.Nil(t, testStruct1.Map, "expected nil map, got: %v", testStruct1.Map) - b, _ := bson.MarshalWithRegistry(Registry, testStruct1) + buf := new(bytes.Buffer) + vw, err := bsonrw.NewBSONValueWriter(buf) + assert.Nil(t, err, "expected nil error, got: %v", err) + enc := bson.NewEncoder(vw) + enc.SetRegistry(Registry) + err = enc.Encode(testStruct1) + assert.Nil(t, err, "expected nil error, got: %v", err) testStruct2 := T{} - _ = bson.UnmarshalWithRegistry(Registry, b, &testStruct2) + _ = bson.UnmarshalWithRegistry(Registry, buf.Bytes(), &testStruct2) assert.NotNil(t, testStruct2.Slice, "expected non-nil slice") assert.NotNil(t, testStruct2.BSlice, "expected non-nil byte slice") @@ -1677,15 +1765,21 @@ func TestMarshalRespectNil(t *testing.T) { assert.Nil(t, testStruct1.MapPtr, "expected nil map ptr, got: %v", testStruct1.MapPtr) assert.Nil(t, testStruct1.Ptr, "expected nil ptr, got: %v", testStruct1.Ptr) - b, _ := bson.MarshalWithRegistry(RegistryRespectNilValues, testStruct1) + buf := new(bytes.Buffer) + vw, err := bsonrw.NewBSONValueWriter(buf) + assert.Nil(t, err, "expected nil error, got: %v", err) + enc := bson.NewEncoder(vw) + enc.SetRegistry(Registry) + err = enc.Encode(testStruct1) + assert.Nil(t, err, "expected nil error, got: %v", err) testStruct2 := T{} - _ = bson.UnmarshalWithRegistry(RegistryRespectNilValues, b, &testStruct2) + _ = bson.UnmarshalWithRegistry(RegistryRespectNilValues, buf.Bytes(), &testStruct2) - assert.Nil(t, testStruct2.Slice, "expected nil slice, got: %v", testStruct2.Slice) + assert.Len(t, testStruct2.Slice, 0, "expected empty slice, got: %v", testStruct2.Slice) assert.Nil(t, testStruct2.SlicePtr, "expected nil slice ptr, got: %v", testStruct2.SlicePtr) - assert.Nil(t, testStruct2.Map, "expected nil map, got: %v", testStruct2.Map) + assert.Len(t, testStruct2.Map, 0, "expected empty map, got: %v", testStruct2.Map) assert.Nil(t, testStruct2.MapPtr, "expected nil map ptr, got: %v", testStruct2.MapPtr) assert.Nil(t, testStruct2.Ptr, "expected nil ptr, got: %v", testStruct2.Ptr) @@ -1701,11 +1795,17 @@ func TestMarshalRespectNil(t *testing.T) { assert.NotNil(t, testStruct1.Map, "expected non-nil map") assert.NotNil(t, testStruct1.MapPtr, "expected non-nil map ptr") - b, _ = bson.MarshalWithRegistry(RegistryRespectNilValues, testStruct1) + buf.Reset() + vw, err = bsonrw.NewBSONValueWriter(buf) + assert.Nil(t, err, "expected nil error, got: %v", err) + enc = bson.NewEncoder(vw) + enc.SetRegistry(Registry) + err = enc.Encode(testStruct1) + assert.Nil(t, err, "expected nil error, got: %v", err) testStruct2 = T{} - _ = bson.UnmarshalWithRegistry(RegistryRespectNilValues, b, &testStruct2) + _ = bson.UnmarshalWithRegistry(RegistryRespectNilValues, buf.Bytes(), &testStruct2) assert.NotNil(t, testStruct2.Slice, "expected non-nil slice") assert.NotNil(t, testStruct2.SlicePtr, "expected non-nil slice ptr") @@ -1732,11 +1832,16 @@ func TestInlineWithPointerToSelf(t *testing.T) { Value: "", } - bytes, err := bson.MarshalWithRegistry(Registry, x1) + buf := new(bytes.Buffer) + vw, err := bsonrw.NewBSONValueWriter(buf) + assert.Nil(t, err, "expected nil error, got: %v", err) + enc := bson.NewEncoder(vw) + enc.SetRegistry(Registry) + err = enc.Encode(x1) assert.Nil(t, err, "expected nil error, got: %v", err) var x2 InlineLoop - err = bson.UnmarshalWithRegistry(Registry, bytes, &x2) + err = bson.UnmarshalWithRegistry(Registry, buf.Bytes(), &x2) assert.Nil(t, err, "expected nil error, got: %v", err) assert.Equal(t, x1, x2, "Expected %v, got %v", x1, x2) }