Skip to content

Commit 0178864

Browse files
authored
GODRIVER-2589 Clarify *Cursor.All() behavior in comment. (mongodb#1804)
1 parent 8192e81 commit 0178864

File tree

2 files changed

+62
-29
lines changed

2 files changed

+62
-29
lines changed

mongo/cursor.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,9 @@ func (c *Cursor) Close(ctx context.Context) error {
286286
}
287287

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

mongo/cursor_test.go

+59-27
Original file line numberDiff line numberDiff line change
@@ -97,37 +97,69 @@ func TestCursor(t *testing.T) {
9797
t.Run("TestAll", func(t *testing.T) {
9898
t.Run("errors if argument is not pointer to slice", func(t *testing.T) {
9999
cursor, err := newCursor(newTestBatchCursor(1, 5), nil, nil)
100-
assert.Nil(t, err, "newCursor error: %v", err)
100+
require.NoError(t, err, "newCursor error: %v", err)
101101
err = cursor.All(context.Background(), []bson.D{})
102-
assert.NotNil(t, err, "expected error, got nil")
102+
assert.Error(t, err, "expected error, got nil")
103103
})
104104

105105
t.Run("fills slice with all documents", 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

109109
var docs []bson.D
110110
err = cursor.All(context.Background(), &docs)
111-
assert.Nil(t, err, "All error: %v", err)
112-
assert.Equal(t, 5, len(docs), "expected 5 docs, got %v", len(docs))
111+
require.NoError(t, err, "All error: %v", err)
112+
assert.Len(t, docs, 5, "expected 5 docs, got %v", len(docs))
113113

114114
for index, doc := range docs {
115115
expected := bson.D{{"foo", int32(index)}}
116116
assert.Equal(t, expected, doc, "expected doc %v, got %v", expected, doc)
117117
}
118118
})
119119

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

124156
type Document struct {
125157
Foo int32 `bson:"foo"`
126158
}
127159
var docs []Document
128160
err = cursor.All(context.Background(), &docs)
129-
assert.Nil(t, err, "All error: %v", err)
130-
assert.Equal(t, 5, len(docs), "expected 5 documents, got %v", len(docs))
161+
require.NoError(t, err, "All error: %v", err)
162+
assert.Len(t, docs, 5, "expected 5 documents, got %v", len(docs))
131163

132164
for index, doc := range docs {
133165
expected := Document{Foo: int32(index)}
@@ -137,11 +169,11 @@ func TestCursor(t *testing.T) {
137169

138170
t.Run("multiple batches are included", func(t *testing.T) {
139171
cursor, err := newCursor(newTestBatchCursor(2, 5), nil, nil)
140-
assert.Nil(t, err, "newCursor error: %v", err)
172+
require.NoError(t, err, "newCursor error: %v", err)
141173
var docs []bson.D
142174
err = cursor.All(context.Background(), &docs)
143-
assert.Nil(t, err, "All error: %v", err)
144-
assert.Equal(t, 10, len(docs), "expected 10 docs, got %v", len(docs))
175+
require.NoError(t, err, "All error: %v", err)
176+
assert.Len(t, docs, 10, "expected 10 docs, got %v", len(docs))
145177

146178
for index, doc := range docs {
147179
expected := bson.D{{"foo", int32(index)}}
@@ -154,31 +186,31 @@ func TestCursor(t *testing.T) {
154186

155187
tbc := newTestBatchCursor(1, 5)
156188
cursor, err := newCursor(tbc, nil, nil)
157-
assert.Nil(t, err, "newCursor error: %v", err)
189+
require.NoError(t, err, "newCursor error: %v", err)
158190

159191
err = cursor.All(context.Background(), &docs)
160-
assert.Nil(t, err, "All error: %v", err)
192+
require.NoError(t, err, "All error: %v", err)
161193
assert.True(t, tbc.closed, "expected batch cursor to be closed but was not")
162194
})
163195

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

167199
cursor, err := newCursor(newTestBatchCursor(1, 5), nil, nil)
168-
assert.Nil(t, err, "newCursor error: %v", err)
200+
require.NoError(t, err, "newCursor error: %v", err)
169201

170202
err = cursor.All(context.Background(), &docs)
171-
assert.Nil(t, err, "expected Nil, got error: %v", err)
172-
assert.Equal(t, 5, len(docs.([]bson.D)), "expected 5 documents, got %v", len(docs.([]bson.D)))
203+
require.NoError(t, err, "All error: %v", err)
204+
assert.Len(t, docs.([]bson.D), 5, "expected 5 documents, got %v", len(docs.([]bson.D)))
173205
})
174206
t.Run("errors when not given pointer to slice", func(t *testing.T) {
175207
var docs interface{} = "test"
176208

177209
cursor, err := newCursor(newTestBatchCursor(1, 5), nil, nil)
178-
assert.Nil(t, err, "newCursor error: %v", err)
210+
require.NoError(t, err, "newCursor error: %v", err)
179211

180212
err = cursor.All(context.Background(), &docs)
181-
assert.NotNil(t, err, "expected error, got: %v", err)
213+
assert.Error(t, err, "expected error, got: %v", err)
182214
})
183215
t.Run("with BSONOptions", func(t *testing.T) {
184216
cursor, err := newCursor(
@@ -187,15 +219,15 @@ func TestCursor(t *testing.T) {
187219
UseJSONStructTags: true,
188220
},
189221
nil)
190-
require.NoError(t, err, "newCursor error")
222+
require.NoError(t, err, "newCursor error: %v", err)
191223

192224
type myDocument struct {
193225
A int32 `json:"foo"`
194226
}
195227
var got []myDocument
196228

197229
err = cursor.All(context.Background(), &got)
198-
require.NoError(t, err, "All error")
230+
require.NoError(t, err, "All error: %v", err)
199231

200232
want := []myDocument{{A: 0}, {A: 1}, {A: 2}, {A: 3}, {A: 4}}
201233

@@ -213,18 +245,18 @@ func TestNewCursorFromDocuments(t *testing.T) {
213245
bson.D{{"_id", 2}, {"quux", "quuz"}},
214246
}
215247
cur, err := NewCursorFromDocuments(findResult, nil, nil)
216-
assert.Nil(t, err, "NewCursorFromDocuments error: %v", err)
248+
require.NoError(t, err, "NewCursorFromDocuments error: %v", err)
217249

218250
// Assert that decoded documents are as expected.
219251
var i int
220252
for cur.Next(context.Background()) {
221253
docBytes, err := bson.Marshal(findResult[i])
222-
assert.Nil(t, err, "Marshal error: %v", err)
254+
require.NoError(t, err, "Marshal error: %v", err)
223255
expectedDecoded := bson.Raw(docBytes)
224256

225257
var decoded bson.Raw
226258
err = cur.Decode(&decoded)
227-
assert.Nil(t, err, "Decode error: %v", err)
259+
require.NoError(t, err, "Decode error: %v", err)
228260
assert.Equal(t, expectedDecoded, decoded,
229261
"expected decoded document %v of Cursor to be %v, got %v",
230262
i, expectedDecoded, decoded)
@@ -233,26 +265,26 @@ func TestNewCursorFromDocuments(t *testing.T) {
233265
assert.Equal(t, 3, i, "expected 3 calls to cur.Next, got %v", i)
234266

235267
// Check for error on Cursor.
236-
assert.Nil(t, cur.Err(), "Cursor error: %v", cur.Err())
268+
require.NoError(t, cur.Err(), "Cursor error: %v", cur.Err())
237269

238270
// Assert that a call to cur.Close will not fail.
239271
err = cur.Close(context.Background())
240-
assert.Nil(t, err, "Close error: %v", err)
272+
require.NoError(t, err, "Close error: %v", err)
241273
})
242274

243275
// Mock an error in a Cursor.
244276
t.Run("mock Find with error", func(t *testing.T) {
245277
mockErr := fmt.Errorf("mock error")
246278
findResult := []interface{}{bson.D{{"_id", 0}, {"foo", "bar"}}}
247279
cur, err := NewCursorFromDocuments(findResult, mockErr, nil)
248-
assert.Nil(t, err, "NewCursorFromDocuments error: %v", err)
280+
require.NoError(t, err, "NewCursorFromDocuments error: %v", err)
249281

250282
// Assert that a call to Next will return false because of existing error.
251283
next := cur.Next(context.Background())
252284
assert.False(t, next, "expected call to Next to return false, got true")
253285

254286
// Check for error on Cursor.
255-
assert.NotNil(t, cur.Err(), "expected Cursor error, got nil")
287+
assert.Error(t, cur.Err(), "expected Cursor error, got nil")
256288
assert.Equal(t, mockErr, cur.Err(), "expected Cursor error %v, got %v",
257289
mockErr, cur.Err())
258290
})

0 commit comments

Comments
 (0)