Skip to content

Commit b2724c6

Browse files
authored
GODRIVER-2589 Clarify *Cursor.All() behavior in comment. (#1804) (#1827)
1 parent ff1792e commit b2724c6

File tree

2 files changed

+62
-29
lines changed

2 files changed

+62
-29
lines changed

mongo/cursor.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,9 @@ func (c *Cursor) Close(ctx context.Context) error {
293293
}
294294

295295
// All iterates the cursor and decodes each document into results. The results parameter must be a pointer to a slice.
296-
// The slice pointed to by results will be completely overwritten. This method will close the cursor after retrieving
297-
// all documents. If the cursor has been iterated, any previously iterated documents will not be included in results.
296+
// The slice pointed to by results will be completely overwritten. A nil slice pointer will not be modified if the cursor
297+
// has been closed, exhausted, or is empty. This method will close the cursor after retrieving all documents. If the
298+
// cursor has been iterated, any previously iterated documents will not be included in results.
298299
//
299300
// This method requires driver version >= 1.1.0.
300301
func (c *Cursor) All(ctx context.Context, results interface{}) error {

mongo/cursor_test.go

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -104,37 +104,69 @@ func TestCursor(t *testing.T) {
104104
t.Run("TestAll", func(t *testing.T) {
105105
t.Run("errors if argument is not pointer to slice", func(t *testing.T) {
106106
cursor, err := newCursor(newTestBatchCursor(1, 5), nil, nil)
107-
assert.Nil(t, err, "newCursor error: %v", err)
107+
require.NoError(t, err, "newCursor error: %v", err)
108108
err = cursor.All(context.Background(), []bson.D{})
109-
assert.NotNil(t, err, "expected error, got nil")
109+
assert.Error(t, err, "expected error, got nil")
110110
})
111111

112112
t.Run("fills slice with all documents", func(t *testing.T) {
113113
cursor, err := newCursor(newTestBatchCursor(1, 5), nil, nil)
114-
assert.Nil(t, err, "newCursor error: %v", err)
114+
require.NoError(t, err, "newCursor error: %v", err)
115115

116116
var docs []bson.D
117117
err = cursor.All(context.Background(), &docs)
118-
assert.Nil(t, err, "All error: %v", err)
119-
assert.Equal(t, 5, len(docs), "expected 5 docs, got %v", len(docs))
118+
require.NoError(t, err, "All error: %v", err)
119+
assert.Len(t, docs, 5, "expected 5 docs, got %v", len(docs))
120120

121121
for index, doc := range docs {
122122
expected := bson.D{{"foo", int32(index)}}
123123
assert.Equal(t, expected, doc, "expected doc %v, got %v", expected, doc)
124124
}
125125
})
126126

127+
t.Run("nil slice", func(t *testing.T) {
128+
cursor, err := newCursor(newTestBatchCursor(0, 0), nil, nil)
129+
require.NoError(t, err, "newCursor error: %v", err)
130+
131+
var docs []bson.D
132+
err = cursor.All(context.Background(), &docs)
133+
require.NoError(t, err, "All error: %v", err)
134+
assert.Nil(t, docs, "expected nil docs")
135+
})
136+
137+
t.Run("empty slice", func(t *testing.T) {
138+
cursor, err := newCursor(newTestBatchCursor(0, 0), nil, nil)
139+
require.NoError(t, err, "newCursor error: %v", err)
140+
141+
docs := []bson.D{}
142+
err = cursor.All(context.Background(), &docs)
143+
require.NoError(t, err, "All error: %v", err)
144+
assert.NotNil(t, docs, "expected non-nil docs")
145+
assert.Len(t, docs, 0, "expected 0 docs, got %v", len(docs))
146+
})
147+
148+
t.Run("empty slice overwritten", func(t *testing.T) {
149+
cursor, err := newCursor(newTestBatchCursor(0, 0), nil, nil)
150+
require.NoError(t, err, "newCursor error: %v", err)
151+
152+
docs := []bson.D{{{"foo", "bar"}}, {{"hello", "world"}, {"pi", 3.14159}}}
153+
err = cursor.All(context.Background(), &docs)
154+
require.NoError(t, err, "All error: %v", err)
155+
assert.NotNil(t, docs, "expected non-nil docs")
156+
assert.Len(t, docs, 0, "expected 0 docs, got %v", len(docs))
157+
})
158+
127159
t.Run("decodes each document into slice type", func(t *testing.T) {
128160
cursor, err := newCursor(newTestBatchCursor(1, 5), nil, nil)
129-
assert.Nil(t, err, "newCursor error: %v", err)
161+
require.NoError(t, err, "newCursor error: %v", err)
130162

131163
type Document struct {
132164
Foo int32 `bson:"foo"`
133165
}
134166
var docs []Document
135167
err = cursor.All(context.Background(), &docs)
136-
assert.Nil(t, err, "All error: %v", err)
137-
assert.Equal(t, 5, len(docs), "expected 5 documents, got %v", len(docs))
168+
require.NoError(t, err, "All error: %v", err)
169+
assert.Len(t, docs, 5, "expected 5 documents, got %v", len(docs))
138170

139171
for index, doc := range docs {
140172
expected := Document{Foo: int32(index)}
@@ -144,11 +176,11 @@ func TestCursor(t *testing.T) {
144176

145177
t.Run("multiple batches are included", func(t *testing.T) {
146178
cursor, err := newCursor(newTestBatchCursor(2, 5), nil, nil)
147-
assert.Nil(t, err, "newCursor error: %v", err)
179+
require.NoError(t, err, "newCursor error: %v", err)
148180
var docs []bson.D
149181
err = cursor.All(context.Background(), &docs)
150-
assert.Nil(t, err, "All error: %v", err)
151-
assert.Equal(t, 10, len(docs), "expected 10 docs, got %v", len(docs))
182+
require.NoError(t, err, "All error: %v", err)
183+
assert.Len(t, docs, 10, "expected 10 docs, got %v", len(docs))
152184

153185
for index, doc := range docs {
154186
expected := bson.D{{"foo", int32(index)}}
@@ -161,31 +193,31 @@ func TestCursor(t *testing.T) {
161193

162194
tbc := newTestBatchCursor(1, 5)
163195
cursor, err := newCursor(tbc, nil, nil)
164-
assert.Nil(t, err, "newCursor error: %v", err)
196+
require.NoError(t, err, "newCursor error: %v", err)
165197

166198
err = cursor.All(context.Background(), &docs)
167-
assert.Nil(t, err, "All error: %v", err)
199+
require.NoError(t, err, "All error: %v", err)
168200
assert.True(t, tbc.closed, "expected batch cursor to be closed but was not")
169201
})
170202

171203
t.Run("does not error given interface as parameter", func(t *testing.T) {
172204
var docs interface{} = []bson.D{}
173205

174206
cursor, err := newCursor(newTestBatchCursor(1, 5), nil, nil)
175-
assert.Nil(t, err, "newCursor error: %v", err)
207+
require.NoError(t, err, "newCursor error: %v", err)
176208

177209
err = cursor.All(context.Background(), &docs)
178-
assert.Nil(t, err, "expected Nil, got error: %v", err)
179-
assert.Equal(t, 5, len(docs.([]bson.D)), "expected 5 documents, got %v", len(docs.([]bson.D)))
210+
require.NoError(t, err, "All error: %v", err)
211+
assert.Len(t, docs.([]bson.D), 5, "expected 5 documents, got %v", len(docs.([]bson.D)))
180212
})
181213
t.Run("errors when not given pointer to slice", func(t *testing.T) {
182214
var docs interface{} = "test"
183215

184216
cursor, err := newCursor(newTestBatchCursor(1, 5), nil, nil)
185-
assert.Nil(t, err, "newCursor error: %v", err)
217+
require.NoError(t, err, "newCursor error: %v", err)
186218

187219
err = cursor.All(context.Background(), &docs)
188-
assert.NotNil(t, err, "expected error, got: %v", err)
220+
assert.Error(t, err, "expected error, got: %v", err)
189221
})
190222
t.Run("with BSONOptions", func(t *testing.T) {
191223
cursor, err := newCursor(
@@ -194,15 +226,15 @@ func TestCursor(t *testing.T) {
194226
UseJSONStructTags: true,
195227
},
196228
nil)
197-
require.NoError(t, err, "newCursor error")
229+
require.NoError(t, err, "newCursor error: %v", err)
198230

199231
type myDocument struct {
200232
A int32 `json:"foo"`
201233
}
202234
var got []myDocument
203235

204236
err = cursor.All(context.Background(), &got)
205-
require.NoError(t, err, "All error")
237+
require.NoError(t, err, "All error: %v", err)
206238

207239
want := []myDocument{{A: 0}, {A: 1}, {A: 2}, {A: 3}, {A: 4}}
208240

@@ -220,18 +252,18 @@ func TestNewCursorFromDocuments(t *testing.T) {
220252
bson.D{{"_id", 2}, {"quux", "quuz"}},
221253
}
222254
cur, err := NewCursorFromDocuments(findResult, nil, nil)
223-
assert.Nil(t, err, "NewCursorFromDocuments error: %v", err)
255+
require.NoError(t, err, "NewCursorFromDocuments error: %v", err)
224256

225257
// Assert that decoded documents are as expected.
226258
var i int
227259
for cur.Next(context.Background()) {
228260
docBytes, err := bson.Marshal(findResult[i])
229-
assert.Nil(t, err, "Marshal error: %v", err)
261+
require.NoError(t, err, "Marshal error: %v", err)
230262
expectedDecoded := bson.Raw(docBytes)
231263

232264
var decoded bson.Raw
233265
err = cur.Decode(&decoded)
234-
assert.Nil(t, err, "Decode error: %v", err)
266+
require.NoError(t, err, "Decode error: %v", err)
235267
assert.Equal(t, expectedDecoded, decoded,
236268
"expected decoded document %v of Cursor to be %v, got %v",
237269
i, expectedDecoded, decoded)
@@ -240,26 +272,26 @@ func TestNewCursorFromDocuments(t *testing.T) {
240272
assert.Equal(t, 3, i, "expected 3 calls to cur.Next, got %v", i)
241273

242274
// Check for error on Cursor.
243-
assert.Nil(t, cur.Err(), "Cursor error: %v", cur.Err())
275+
require.NoError(t, cur.Err(), "Cursor error: %v", cur.Err())
244276

245277
// Assert that a call to cur.Close will not fail.
246278
err = cur.Close(context.Background())
247-
assert.Nil(t, err, "Close error: %v", err)
279+
require.NoError(t, err, "Close error: %v", err)
248280
})
249281

250282
// Mock an error in a Cursor.
251283
t.Run("mock Find with error", func(t *testing.T) {
252284
mockErr := fmt.Errorf("mock error")
253285
findResult := []interface{}{bson.D{{"_id", 0}, {"foo", "bar"}}}
254286
cur, err := NewCursorFromDocuments(findResult, mockErr, nil)
255-
assert.Nil(t, err, "NewCursorFromDocuments error: %v", err)
287+
require.NoError(t, err, "NewCursorFromDocuments error: %v", err)
256288

257289
// Assert that a call to Next will return false because of existing error.
258290
next := cur.Next(context.Background())
259291
assert.False(t, next, "expected call to Next to return false, got true")
260292

261293
// Check for error on Cursor.
262-
assert.NotNil(t, cur.Err(), "expected Cursor error, got nil")
294+
assert.Error(t, cur.Err(), "expected Cursor error, got nil")
263295
assert.Equal(t, mockErr, cur.Err(), "expected Cursor error %v, got %v",
264296
mockErr, cur.Err())
265297
})

0 commit comments

Comments
 (0)