Skip to content

Commit

Permalink
GODRIVER-3470 Add UnmarshalBSON initialization tests
Browse files Browse the repository at this point in the history
  • Loading branch information
prestonvasquez committed Feb 3, 2025
1 parent f1e8a1d commit 7d2be3c
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 29 deletions.
24 changes: 24 additions & 0 deletions bson/unmarshal_value_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"go.mongodb.org/mongo-driver/bson/bsoncodec"
"go.mongodb.org/mongo-driver/bson/bsontype"
"go.mongodb.org/mongo-driver/internal/assert"
"go.mongodb.org/mongo-driver/internal/require"
"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
)

Expand Down Expand Up @@ -93,6 +94,29 @@ func TestUnmarshalValue(t *testing.T) {
})
}

func TestInitializedPointerDataWithBSONNull(t *testing.T) {
// Set up the test case with initialized pointers.
tc := unmarshalBehaviorTestCase{
BSONValuePtrTracker: &unmarshalBSONValueCallTracker{},
BSONPtrTracker: &unmarshalBSONCallTracker{},
}

// Create BSON data where the '*_ptr_tracker' fields are explicitly set to
// null.
bytes := docToBytes(D{
{Key: "bv_ptr_tracker", Value: nil},
{Key: "b_ptr_tracker", Value: nil},
})

// Unmarshal the BSON data into the test case struct. This should set the
// pointer fields to nil due to the BSON null value.
err := Unmarshal(bytes, &tc)
require.NoError(t, err)

assert.Nil(t, tc.BSONValuePtrTracker)
assert.Nil(t, tc.BSONPtrTracker)
}

// tests covering GODRIVER-2779
func BenchmarkSliceCodecUnmarshal(b *testing.B) {
benchmarks := []struct {
Expand Down
68 changes: 39 additions & 29 deletions bson/unmarshaling_cases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,9 @@ package bson

import (
"reflect"
"testing"

"go.mongodb.org/mongo-driver/bson/bsonrw"
"go.mongodb.org/mongo-driver/bson/bsontype"
"go.mongodb.org/mongo-driver/internal/assert"
"go.mongodb.org/mongo-driver/internal/require"
)

type unmarshalingTestCase struct {
Expand Down Expand Up @@ -121,12 +118,21 @@ func unmarshalingTestCases() []unmarshalingTestCase {
name: "nil pointer and non-pointer type with literal null BSON",
sType: reflect.TypeOf(unmarshalBehaviorTestCase{}),
want: &unmarshalBehaviorTestCase{
Tracker: unmarshalCallTracker{
unmarshalCalled: true,
BSONValueTracker: unmarshalBSONValueCallTracker{
called: true,
},
PtrTracker: nil,
BSONValuePtrTracker: nil,
BSONTracker: unmarshalBSONCallTracker{
called: true,
},
BSONPtrTracker: nil,
},
data: docToBytes(D{{Key: "tracker", Value: nil}, {Key: "ptr_tracker", Value: nil}}),
data: docToBytes(D{
{Key: "bv_tracker", Value: nil},
{Key: "bv_ptr_tracker", Value: nil},
{Key: "b_tracker", Value: nil},
{Key: "b_ptr_tracker", Value: nil},
}),
},
// GODRIVER-2252
// Test that a struct of pointer types with UnmarshalBSON functions defined marshal and
Expand Down Expand Up @@ -284,34 +290,38 @@ func (ms *myString) UnmarshalBSON(bytes []byte) error {
return nil
}

type unmarshalCallTracker struct {
unmarshalCalled bool
}

type unmarshalBehaviorTestCase struct {
Tracker unmarshalCallTracker `bson:"tracker"`
PtrTracker *unmarshalCallTracker `bson:"ptr_tracker"`
// unmarshalBSONValueCallTracker is a test struct that tracks whether the
// UnmarshalBSONValue method has been called.
type unmarshalBSONValueCallTracker struct {
called bool // called is set to true when UnmarshalBSONValue is invoked.
}

func (ms *unmarshalCallTracker) UnmarshalBSONValue(bsontype.Type, []byte) error {
ms.unmarshalCalled = true
var _ ValueUnmarshaler = &unmarshalBSONValueCallTracker{}

return nil
// unmarshalBSONCallTracker is a test struct that tracks whether the
// UnmarshalBSON method has been called.
type unmarshalBSONCallTracker struct {
called bool // called is set to true when UnmarshalBSON is invoked.
}

func TestInitializedPointerDataWithBSONNull(t *testing.T) {
// Set up the test case with an initialized pointer.
tc := unmarshalBehaviorTestCase{
PtrTracker: &unmarshalCallTracker{},
}
// Ensure unmarshalBSONCallTracker implements the Unmarshaler interface.
var _ Unmarshaler = &unmarshalBSONCallTracker{}

// Create BSON data where the 'ptr_tracker' field is explicitly set to null.
bytes := docToBytes(D{{Key: "ptr_tracker", Value: nil}})
// unmarshalBehaviorTestCase holds instances of call trackers for testing BSON
// unmarshaling behavior.
type unmarshalBehaviorTestCase struct {
BSONValueTracker unmarshalBSONValueCallTracker `bson:"bv_tracker"` // BSON value unmarshaling by value.
BSONValuePtrTracker *unmarshalBSONValueCallTracker `bson:"bv_ptr_tracker"` // BSON value unmarshaling by pointer.
BSONTracker unmarshalBSONCallTracker `bson:"b_tracker"` // BSON unmarshaling by value.
BSONPtrTracker *unmarshalBSONCallTracker `bson:"b_ptr_tracker"` // BSON unmarshaling by pointer.
}

// Unmarshal the BSON data into the test case struct.
// This should set PtrTracker to nil due to the BSON null value.
err := Unmarshal(bytes, &tc)
require.NoError(t, err)
func (tracker *unmarshalBSONValueCallTracker) UnmarshalBSONValue(bsontype.Type, []byte) error {
tracker.called = true
return nil
}

assert.Nil(t, tc.PtrTracker)
func (tracker *unmarshalBSONCallTracker) UnmarshalBSON([]byte) error {
tracker.called = true
return nil
}

0 comments on commit 7d2be3c

Please sign in to comment.