Skip to content

Commit

Permalink
GODRIVER-3307 Simplify MarshalValue and UnmarshalValue test case setup.
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewdale committed Jan 1, 2025
1 parent a9eddec commit e0ea3b6
Show file tree
Hide file tree
Showing 3 changed files with 195 additions and 99 deletions.
228 changes: 159 additions & 69 deletions bson/marshal_value_cases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,169 @@ package bson

import (
"io"
"testing"

"go.mongodb.org/mongo-driver/v2/internal/assert"
"go.mongodb.org/mongo-driver/v2/x/bsonx/bsoncore"
)

var marshalValueTestCases = []marshalValueTestCase{
{
name: "double",
val: 3.14,
bsontype: TypeDouble,
bytes: bsoncore.AppendDouble(nil, 3.14),
},
{
name: "string",
val: "hello world",
bsontype: TypeString,
bytes: bsoncore.AppendString(nil, "hello world"),
},
{
name: "binary",
val: Binary{1, []byte{1, 2}},
bsontype: TypeBinary,
bytes: bsoncore.AppendBinary(nil, 1, []byte{1, 2}),
},
{
name: "undefined",
val: Undefined{},
bsontype: TypeUndefined,
bytes: []byte{},
},
{
name: "object id",
val: ObjectID{103, 116, 166, 161, 70, 33, 67, 139, 164, 144, 255, 112},
bsontype: TypeObjectID,
bytes: bsoncore.AppendObjectID(nil, ObjectID{103, 116, 166, 161, 70, 33, 67, 139, 164, 144, 255, 112}),
},
{
name: "boolean",
val: true,
bsontype: TypeBoolean,
bytes: bsoncore.AppendBoolean(nil, true),
},
{
name: "datetime",
val: DateTime(5),
bsontype: TypeDateTime,
bytes: bsoncore.AppendDateTime(nil, 5),
},
{
name: "null",
val: Null{},
bsontype: TypeNull,
bytes: []byte{},
},
{
name: "regex",
val: Regex{Pattern: "pattern", Options: "imx"},
bsontype: TypeRegex,
bytes: bsoncore.AppendRegex(nil, "pattern", "imx"),
},
{
name: "dbpointer",
val: DBPointer{
DB: "db",
Pointer: ObjectID{103, 116, 166, 161, 70, 33, 67, 139, 164, 144, 255, 112},
},
bsontype: TypeDBPointer,
bytes: bsoncore.AppendDBPointer(
nil,
"db",
ObjectID{103, 116, 166, 161, 70, 33, 67, 139, 164, 144, 255, 112},
),
},
{
name: "javascript",
val: JavaScript("js"),
bsontype: TypeJavaScript,
bytes: bsoncore.AppendJavaScript(nil, "js"),
},
{
name: "symbol",
val: Symbol("symbol"),
bsontype: TypeSymbol,
bytes: bsoncore.AppendSymbol(nil, "symbol"),
},
{
name: "code with scope",
val: CodeWithScope{Code: "code", Scope: D{{"a", "b"}}},
bsontype: TypeCodeWithScope,
bytes: bsoncore.AppendCodeWithScope(
nil,
"code",
bsoncore.NewDocumentBuilder().
AppendString("a", "b").
Build()),
},
{
name: "int32",
val: 5,
bsontype: TypeInt32,
bytes: bsoncore.AppendInt32(nil, 5),
},
{
name: "int64",
val: int64(5),
bsontype: TypeInt64,
bytes: bsoncore.AppendInt64(nil, 5),
},
{
name: "timestamp",
val: Timestamp{T: 1, I: 5},
bsontype: TypeTimestamp,
bytes: bsoncore.AppendTimestamp(nil, 1, 5),
},
{
name: "decimal128",
val: NewDecimal128(5, 10),
bsontype: TypeDecimal128,
bytes: bsoncore.AppendDecimal128(nil, 5, 10),
},
{
name: "min key",
val: MinKey{},
bsontype: TypeMinKey,
bytes: []byte{},
},
{
name: "max key",
val: MaxKey{},
bsontype: TypeMaxKey,
bytes: []byte{},
},
{
name: "struct",
val: marshalValueStruct{Foo: 10},
bsontype: TypeEmbeddedDocument,
bytes: bsoncore.NewDocumentBuilder().
AppendInt32("foo", 10).
Build(),
},
{
name: "D",
val: D{{"foo", int32(10)}},
bsontype: TypeEmbeddedDocument,
bytes: bsoncore.NewDocumentBuilder().
AppendInt32("foo", 10).
Build(),
},
{
name: "M",
val: M{"foo": int32(10)},
bsontype: TypeEmbeddedDocument,
bytes: bsoncore.NewDocumentBuilder().
AppendInt32("foo", 10).
Build(),
},
{
name: "ValueMarshaler",
val: marshalValueMarshaler{Foo: 10},
bsontype: TypeInt32,
bytes: bsoncore.AppendInt32(nil, 10),
},
}

// helper type for testing MarshalValue that implements io.Reader
type marshalValueInterfaceInner struct {
Foo int
Expand Down Expand Up @@ -59,70 +216,3 @@ type marshalValueTestCase struct {
bsontype Type
bytes []byte
}

func newMarshalValueTestCases(t *testing.T) []marshalValueTestCase {
t.Helper()

var (
oid = NewObjectID()
regex = Regex{Pattern: "pattern", Options: "imx"}
dbPointer = DBPointer{DB: "db", Pointer: NewObjectID()}
codeWithScope = CodeWithScope{Code: "code", Scope: D{{"a", "b"}}}
decimal128h, decimal128l = NewDecimal128(5, 10).GetBytes()
structTest = marshalValueStruct{Foo: 10}
)
idx, scopeCore := bsoncore.AppendDocumentStart(nil)
scopeCore = bsoncore.AppendStringElement(scopeCore, "a", "b")
scopeCore, err := bsoncore.AppendDocumentEnd(scopeCore, idx)
assert.Nil(t, err, "Document error: %v", err)
structCore, err := Marshal(structTest)
assert.Nil(t, err, "Marshal error: %v", err)

return []marshalValueTestCase{
{"double", 3.14, TypeDouble, bsoncore.AppendDouble(nil, 3.14)},
{"string", "hello world", TypeString, bsoncore.AppendString(nil, "hello world")},
{"binary", Binary{1, []byte{1, 2}}, TypeBinary, bsoncore.AppendBinary(nil, 1, []byte{1, 2})},
{"undefined", Undefined{}, TypeUndefined, []byte{}},
{"object id", oid, TypeObjectID, bsoncore.AppendObjectID(nil, oid)},
{"boolean", true, TypeBoolean, bsoncore.AppendBoolean(nil, true)},
{"datetime", DateTime(5), TypeDateTime, bsoncore.AppendDateTime(nil, 5)},
{"null", Null{}, TypeNull, []byte{}},
{"regex", regex, TypeRegex, bsoncore.AppendRegex(nil, regex.Pattern, regex.Options)},
{"dbpointer", dbPointer, TypeDBPointer, bsoncore.AppendDBPointer(nil, dbPointer.DB, dbPointer.Pointer)},
{"javascript", JavaScript("js"), TypeJavaScript, bsoncore.AppendJavaScript(nil, "js")},
{"symbol", Symbol("symbol"), TypeSymbol, bsoncore.AppendSymbol(nil, "symbol")},
{"code with scope", codeWithScope, TypeCodeWithScope, bsoncore.AppendCodeWithScope(nil, "code", scopeCore)},
{"int32", 5, TypeInt32, bsoncore.AppendInt32(nil, 5)},
{"int64", int64(5), TypeInt64, bsoncore.AppendInt64(nil, 5)},
{"timestamp", Timestamp{T: 1, I: 5}, TypeTimestamp, bsoncore.AppendTimestamp(nil, 1, 5)},
{"decimal128", NewDecimal128(decimal128h, decimal128l), TypeDecimal128, bsoncore.AppendDecimal128(nil, decimal128h, decimal128l)},
{"min key", MinKey{}, TypeMinKey, []byte{}},
{"max key", MaxKey{}, TypeMaxKey, []byte{}},
{"struct", structTest, TypeEmbeddedDocument, structCore},
{"D", D{{"foo", int32(10)}}, TypeEmbeddedDocument, structCore},
{"M", M{"foo": int32(10)}, TypeEmbeddedDocument, structCore},
{"ValueMarshaler", marshalValueMarshaler{Foo: 10}, TypeInt32, bsoncore.AppendInt32(nil, 10)},
}

}

func newMarshalValueTestCasesWithInterfaceCore(t *testing.T) []marshalValueTestCase {
t.Helper()

marshalValueTestCases := newMarshalValueTestCases(t)

interfaceTest := marshalValueInterfaceOuter{
Reader: marshalValueInterfaceInner{
Foo: 10,
},
}
interfaceCore, err := Marshal(interfaceTest)
assert.Nil(t, err, "Marshal error: %v", err)

marshalValueTestCases = append(
marshalValueTestCases,
marshalValueTestCase{"interface", interfaceTest, TypeEmbeddedDocument, interfaceCore},
)

return marshalValueTestCases
}
40 changes: 26 additions & 14 deletions bson/marshal_value_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,44 @@
package bson

import (
"slices"
"strings"
"testing"

"go.mongodb.org/mongo-driver/v2/internal/assert"
"go.mongodb.org/mongo-driver/v2/x/bsonx/bsoncore"
)

func TestMarshalValue(t *testing.T) {
t.Parallel()

marshalValueTestCases := newMarshalValueTestCasesWithInterfaceCore(t)

t.Run("MarshalValue", func(t *testing.T) {
t.Parallel()
testCases := slices.Clone(marshalValueTestCases)
testCases = append(testCases, marshalValueTestCase{
name: "interface",
val: marshalValueInterfaceOuter{
Reader: marshalValueInterfaceInner{
Foo: 10,
},
},
bsontype: TypeEmbeddedDocument,
bytes: bsoncore.NewDocumentBuilder().
AppendDocument("reader", bsoncore.NewDocumentBuilder().
AppendInt32("foo", 10).
Build()).
Build(),
})

for _, tc := range marshalValueTestCases {
tc := tc
for _, tc := range testCases {
tc := tc

t.Run(tc.name, func(t *testing.T) {
t.Parallel()
t.Run(tc.name, func(t *testing.T) {
t.Parallel()

valueType, valueBytes, err := MarshalValue(tc.val)
assert.Nil(t, err, "MarshalValue error: %v", err)
compareMarshalValueResults(t, tc, valueType, valueBytes)
})
}
})
valueType, valueBytes, err := MarshalValue(tc.val)
assert.Nil(t, err, "MarshalValue error: %v", err)
compareMarshalValueResults(t, tc, valueType, valueBytes)
})
}
}

func compareMarshalValueResults(t *testing.T, tc marshalValueTestCase, gotType Type, gotBytes []byte) {
Expand Down
26 changes: 10 additions & 16 deletions bson/unmarshal_value_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,18 @@ import (
func TestUnmarshalValue(t *testing.T) {
t.Parallel()

unmarshalValueTestCases := newMarshalValueTestCases(t)
for _, tc := range marshalValueTestCases {
tc := tc

t.Run("UnmarshalValue", func(t *testing.T) {
t.Parallel()
t.Run(tc.name, func(t *testing.T) {
t.Parallel()

for _, tc := range unmarshalValueTestCases {
tc := tc

t.Run(tc.name, func(t *testing.T) {
t.Parallel()

gotValue := reflect.New(reflect.TypeOf(tc.val))
err := UnmarshalValue(tc.bsontype, tc.bytes, gotValue.Interface())
assert.Nil(t, err, "UnmarshalValueWithRegistry error: %v", err)
assert.Equal(t, tc.val, gotValue.Elem().Interface(), "value mismatch; expected %s, got %s", tc.val, gotValue.Elem())
})
}
})
gotValue := reflect.New(reflect.TypeOf(tc.val))
err := UnmarshalValue(tc.bsontype, tc.bytes, gotValue.Interface())
assert.Nil(t, err, "UnmarshalValueWithRegistry error: %v", err)
assert.Equal(t, tc.val, gotValue.Elem().Interface(), "value mismatch; expected %s, got %s", tc.val, gotValue.Elem())
})
}
}

// tests covering GODRIVER-2779
Expand Down

0 comments on commit e0ea3b6

Please sign in to comment.