Skip to content

Commit 35af242

Browse files
committed
GODRIVER-1758 add missing error conversions (#512)
1 parent d7c4da3 commit 35af242

File tree

5 files changed

+99
-7
lines changed

5 files changed

+99
-7
lines changed

mongo/cursor.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ func (c *Cursor) next(ctx context.Context, nonBlocking bool) bool {
124124
// If we don't have a next batch
125125
if !c.bc.Next(ctx) {
126126
// Do we have an error? If so we return false.
127-
c.err = c.bc.Err()
127+
c.err = replaceErrors(c.bc.Err())
128128
if c.err != nil {
129129
return false
130130
}
@@ -176,7 +176,7 @@ func (c *Cursor) Err() error { return c.err }
176176
// the first call, any subsequent calls will not change the state.
177177
func (c *Cursor) Close(ctx context.Context) error {
178178
defer c.closeImplicitSession()
179-
return c.bc.Close(ctx)
179+
return replaceErrors(c.bc.Close(ctx))
180180
}
181181

182182
// All iterates the cursor and decodes each document into results. The results parameter must be a pointer to a slice.
@@ -219,7 +219,7 @@ func (c *Cursor) All(ctx context.Context, results interface{}) error {
219219
batch = c.bc.Batch()
220220
}
221221

222-
if err = c.bc.Err(); err != nil {
222+
if err = replaceErrors(c.bc.Err()); err != nil {
223223
return err
224224
}
225225

mongo/database.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,10 @@ func (db *Database) RunCommand(ctx context.Context, runCommand interface{}, opts
192192
}
193193

194194
err = op.Execute(ctx)
195+
// RunCommand can be used to run a write, thus execute may return a write error
196+
_, convErr := processWriteError(err)
195197
return &SingleResult{
196-
err: replaceErrors(err),
198+
err: convErr,
197199
rdr: bson.Raw(op.Result()),
198200
reg: db.registry,
199201
}

mongo/integration/cursor_test.go

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,58 @@ func TestCursor(t *testing.T) {
165165
assertCursorBatchLength(mt, cursor, len(getMoreBatch)-1)
166166
})
167167
})
168+
mt.RunOpts("all", noClientOpts, func(mt *mtest.T) {
169+
failpointOpts := mtest.NewOptions().Topologies(mtest.ReplicaSet).MinServerVersion("4.0")
170+
mt.RunOpts("getMore error", failpointOpts, func(mt *mtest.T) {
171+
failpointData := mtest.FailPointData{
172+
FailCommands: []string{"getMore"},
173+
ErrorCode: 100,
174+
}
175+
mt.SetFailPoint(mtest.FailPoint{
176+
ConfigureFailPoint: "failCommand",
177+
Mode: "alwaysOn",
178+
Data: failpointData,
179+
})
180+
initCollection(mt, mt.Coll)
181+
cursor, err := mt.Coll.Find(mtest.Background, bson.D{}, options.Find().SetBatchSize(2))
182+
assert.Nil(mt, err, "Find error: %v", err)
183+
defer cursor.Close(mtest.Background)
184+
185+
var docs []bson.D
186+
err = cursor.All(context.Background(), &docs)
187+
assert.NotNil(mt, err, "expected change stream error, got nil")
188+
189+
// make sure that a mongo.CommandError is returned instead of a driver.Error
190+
mongoErr, ok := err.(mongo.CommandError)
191+
assert.True(mt, ok, "expected mongo.CommandError, got: %T", err)
192+
assert.Equal(mt, failpointData.ErrorCode, mongoErr.Code, "expected code %v, got: %v", failpointData.ErrorCode, mongoErr.Code)
193+
})
194+
})
195+
mt.RunOpts("close", noClientOpts, func(mt *mtest.T) {
196+
failpointOpts := mtest.NewOptions().Topologies(mtest.ReplicaSet).MinServerVersion("4.0")
197+
mt.RunOpts("killCursors error", failpointOpts, func(mt *mtest.T) {
198+
failpointData := mtest.FailPointData{
199+
FailCommands: []string{"killCursors"},
200+
ErrorCode: 100,
201+
}
202+
mt.SetFailPoint(mtest.FailPoint{
203+
ConfigureFailPoint: "failCommand",
204+
Mode: "alwaysOn",
205+
Data: failpointData,
206+
})
207+
initCollection(mt, mt.Coll)
208+
cursor, err := mt.Coll.Find(mtest.Background, bson.D{}, options.Find().SetBatchSize(2))
209+
assert.Nil(mt, err, "Find error: %v", err)
210+
211+
err = cursor.Close(mtest.Background)
212+
assert.NotNil(mt, err, "expected change stream error, got nil")
213+
214+
// make sure that a mongo.CommandError is returned instead of a driver.Error
215+
mongoErr, ok := err.(mongo.CommandError)
216+
assert.True(mt, ok, "expected mongo.CommandError, got: %T", err)
217+
assert.Equal(mt, failpointData.ErrorCode, mongoErr.Code, "expected code %v, got: %v", failpointData.ErrorCode, mongoErr.Code)
218+
})
219+
})
168220
}
169221

170222
type tryNextCursor interface {
@@ -198,12 +250,13 @@ func verifyOneGetmoreSent(mt *mtest.T, cursor tryNextCursor) {
198250

199251
// should be called in a test run with a mock deployment
200252
func tryNextGetmoreError(mt *mtest.T, cursor tryNextCursor) {
201-
getMoreRes := mtest.CreateCommandErrorResponse(mtest.CommandError{
253+
testErr := mtest.CommandError{
202254
Code: 100,
203255
Message: "getMore error",
204256
Name: "CursorError",
205257
Labels: []string{"NonResumableChangeStreamError"},
206-
})
258+
}
259+
getMoreRes := mtest.CreateCommandErrorResponse(testErr)
207260
mt.AddMockResponses(getMoreRes)
208261

209262
// first call to TryNext should return false because first batch was empty so batch cursor returns false
@@ -215,6 +268,14 @@ func tryNextGetmoreError(mt *mtest.T, cursor tryNextCursor) {
215268

216269
err := cursor.Err()
217270
assert.NotNil(mt, err, "expected change stream error, got nil")
271+
272+
// make sure that a mongo.CommandError is returned instead of a driver.Error
273+
mongoErr, ok := err.(mongo.CommandError)
274+
assert.True(mt, ok, "expected mongo.CommandError, got: %T", err)
275+
assert.Equal(mt, testErr.Code, mongoErr.Code, "expected code %v, got: %v", testErr.Code, mongoErr.Code)
276+
assert.Equal(mt, testErr.Message, mongoErr.Message, "expected message %v, got: %v", testErr.Message, mongoErr.Message)
277+
assert.Equal(mt, testErr.Name, mongoErr.Name, "expected name %v, got: %v", testErr.Name, mongoErr.Name)
278+
assert.Equal(mt, testErr.Labels, mongoErr.Labels, "expected labels %v, got: %v", testErr.Labels, mongoErr.Labels)
218279
}
219280

220281
func assertCursorBatchLength(mt *mtest.T, cursor *mongo.Cursor, expected int) {

mongo/integration/database_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,35 @@ func TestDatabase(t *testing.T) {
8888
assert.True(mt, ok, "expected command %v to contain a $readPreference document", evt.Command)
8989
assert.Equal(mt, expected, actual, "expected $readPreference document %v, got %v", expected, actual)
9090
})
91+
failpointOpts := mtest.NewOptions().MinServerVersion("4.0").Topologies(mtest.ReplicaSet)
92+
mt.RunOpts("gets result and error", failpointOpts, func(mt *mtest.T) {
93+
mt.SetFailPoint(mtest.FailPoint{
94+
ConfigureFailPoint: "failCommand",
95+
Mode: mtest.FailPointMode{
96+
Times: 1,
97+
},
98+
Data: mtest.FailPointData{
99+
FailCommands: []string{"insert"},
100+
WriteConcernError: &mtest.WriteConcernErrorData{
101+
Code: 100,
102+
},
103+
},
104+
})
105+
cmd := bson.D{
106+
{"insert", "test"},
107+
{"documents", bson.A{bson.D{{"a", 1}}}},
108+
}
109+
res, gotErr := mt.DB.RunCommand(mtest.Background, cmd).DecodeBytes()
110+
111+
n, ok := res.Lookup("n").Int32OK()
112+
assert.True(mt, ok, "expected n in response")
113+
assert.Equal(mt, int32(1), n, "expected n value 1, got %v", n)
114+
115+
writeExcept, ok := gotErr.(mongo.WriteException)
116+
assert.True(mt, ok, "expected WriteCommandError, got %T", gotErr)
117+
assert.NotNil(mt, writeExcept.WriteConcernError, "expected WriteConcernError to be non-nil")
118+
assert.Equal(mt, writeExcept.WriteConcernError.Code, 100, "expeced error code 100, got %v", writeExcept.WriteConcernError.Code)
119+
})
91120
})
92121

93122
dropOpts := mtest.NewOptions().DatabaseName("dropDb")

mongo/integration/mtest/deployment_helpers.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func CreateCommandErrorResponse(ce CommandError) bson.D {
7272
for _, label := range ce.Labels {
7373
labelsArr = append(labelsArr, label)
7474
}
75-
res = append(res, bson.E{Key: "labels", Value: labelsArr})
75+
res = append(res, bson.E{Key: "errorLabels", Value: labelsArr})
7676
}
7777
return res
7878
}

0 commit comments

Comments
 (0)