From de7fae1c9d3afd0bd5b6e4ba6a241ac363a7467c Mon Sep 17 00:00:00 2001 From: Divjot Arora Date: Mon, 3 Aug 2020 16:47:47 -0400 Subject: [PATCH] GODRIVER-1706 Ensure codeName is propagated for errors (#458) --- mongo/errors.go | 7 +++- mongo/integration/collection_test.go | 12 ++++--- mongo/integration/crud_prose_test.go | 49 ++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/mongo/errors.go b/mongo/errors.go index 7f58c838e6..4f537c3b7d 100644 --- a/mongo/errors.go +++ b/mongo/errors.go @@ -201,7 +201,12 @@ func convertDriverWriteConcernError(wce *driver.WriteConcernError) *WriteConcern return nil } - return &WriteConcernError{Code: int(wce.Code), Message: wce.Message, Details: bson.Raw(wce.Details)} + return &WriteConcernError{ + Name: wce.Name, + Code: int(wce.Code), + Message: wce.Message, + Details: bson.Raw(wce.Details), + } } // BulkWriteError is an error that occurred during execution of one operation in a BulkWrite. This error type is only diff --git a/mongo/integration/collection_test.go b/mongo/integration/collection_test.go index 3f83674792..aea8132236 100644 --- a/mongo/integration/collection_test.go +++ b/mongo/integration/collection_test.go @@ -32,14 +32,16 @@ const ( errorModifiedID = 66 ) -func TestCollection(t *testing.T) { - mt := mtest.New(t, mtest.NewOptions().CreateClient(false)) - defer mt.Close() - +var ( // impossibleWc is a write concern that can't be satisfied and is used to test write concern errors // for various operations. It includes a timeout because legacy servers will wait for all W nodes to respond, // causing tests to hang. - impossibleWc := writeconcern.New(writeconcern.W(30), writeconcern.WTimeout(time.Second)) + impossibleWc = writeconcern.New(writeconcern.W(30), writeconcern.WTimeout(time.Second)) +) + +func TestCollection(t *testing.T) { + mt := mtest.New(t, mtest.NewOptions().CreateClient(false)) + defer mt.Close() mt.RunOpts("insert one", noClientOpts, func(mt *mtest.T) { mt.Run("success", func(mt *mtest.T) { diff --git a/mongo/integration/crud_prose_test.go b/mongo/integration/crud_prose_test.go index 8711b106d0..7353be5dbe 100644 --- a/mongo/integration/crud_prose_test.go +++ b/mongo/integration/crud_prose_test.go @@ -65,3 +65,52 @@ func TestAggregateSecondaryPreferredReadPreference(t *testing.T) { assert.NotNil(mt, err, "expected command %s to not contain $readPreference", evt.Command) }) } + +func TestErrorsCodeNamePropagated(t *testing.T) { + // Ensure the codeName field is propagated for both command and write concern errors. + + mtOpts := mtest.NewOptions(). + Topologies(mtest.ReplicaSet). + CreateClient(false) + mt := mtest.New(t, mtOpts) + defer mt.Close() + + mt.RunOpts("command error", mtest.NewOptions().MinServerVersion("3.4"), func(mt *mtest.T) { + // codeName is propagated in an ok:0 error. + + cmd := bson.D{ + {"insert", mt.Coll.Name()}, + {"documents", []bson.D{}}, + } + err := mt.DB.RunCommand(mtest.Background, cmd).Err() + assert.NotNil(mt, err, "expected RunCommand error, got nil") + + ce, ok := err.(mongo.CommandError) + assert.True(mt, ok, "expected error of type %T, got %v of type %T", mongo.CommandError{}, err, err) + expectedCodeName := "InvalidLength" + assert.Equal(mt, expectedCodeName, ce.Name, "expected error code name %q, got %q", expectedCodeName, ce.Name) + }) + + wcCollOpts := options.Collection(). + SetWriteConcern(impossibleWc) + wcMtOpts := mtest.NewOptions(). + CollectionOptions(wcCollOpts) + mt.RunOpts("write concern error", wcMtOpts, func(mt *mtest.T) { + // codeName is propagated for write concern errors. + + _, err := mt.Coll.InsertOne(mtest.Background, bson.D{}) + assert.NotNil(mt, err, "expected InsertOne error, got nil") + + we, ok := err.(mongo.WriteException) + assert.True(mt, ok, "expected error of type %T, got %v of type %T", mongo.WriteException{}, err, err) + wce := we.WriteConcernError + assert.NotNil(mt, wce, "expected write concern error, got %v", we) + + var expectedCodeName string + if codeNameVal, err := mt.GetSucceededEvent().Reply.LookupErr("writeConcernError", "codeName"); err == nil { + expectedCodeName = codeNameVal.StringValue() + } + + assert.Equal(mt, expectedCodeName, wce.Name, "expected code name %q, got %q", expectedCodeName, wce.Name) + }) +}