44 changes: 31 additions & 13 deletions .evergreen/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -186,24 +186,29 @@ functions:
script: |
${PREPARE_SHELL}
find $MONGO_ORCHESTRATION_HOME -name \*.log | xargs tar czf mongodb-logs.tar.gz
- command: ec2.assume_role
params:
role_arn: ${assume_role_arn}
- command: s3.put
params:
aws_key: ${aws_key}
aws_secret: ${aws_secret}
aws_key: ${AWS_ACCESS_KEY_ID}
aws_secret: ${AWS_SECRET_ACCESS_KEY}
aws_session_token: ${AWS_SESSION_TOKEN}
local_file: mongodb-logs.tar.gz
remote_file: ${UPLOAD_BUCKET}/${build_variant}/${revision}/${version_id}/${build_id}/logs/${task_id}-${execution}-mongodb-logs.tar.gz
bucket: mciuploads
remote_file: ${build_variant}/${revision}/${version_id}/${build_id}/logs/${task_id}-${execution}-mongodb-logs.tar.gz
bucket: ${aws_bucket}
permissions: public-read
content_type: ${content_type|application/x-gzip}
display_name: "mongodb-logs.tar.gz"
- command: s3.put
params:
aws_key: ${aws_key}
aws_secret: ${aws_secret}
aws_key: ${AWS_ACCESS_KEY_ID}
aws_secret: ${AWS_SECRET_ACCESS_KEY}
aws_session_token: ${AWS_SESSION_TOKEN}
optional: true
local_file: ${PROJECT_DIRECTORY}/fuzz.tgz
remote_file: ${UPLOAD_BUCKET}/${build_variant}/${revision}/${version_id}/${build_id}/${task_id}-${execution}-fuzz.tgz
bucket: mciuploads
remote_file: ${build_variant}/${revision}/${version_id}/${build_id}/${task_id}-${execution}-fuzz.tgz
bucket: ${aws_bucket}
permissions: public-read
content_type: application/x-gzip
display_name: "fuzz.tgz"
Expand All @@ -216,12 +221,13 @@ functions:
find . -name \*.suite | xargs tar czf test_suite.tgz
- command: s3.put
params:
aws_key: ${aws_key}
aws_secret: ${aws_secret}
aws_key: ${AWS_ACCESS_KEY_ID}
aws_secret: ${AWS_SECRET_ACCESS_KEY}
aws_session_token: ${AWS_SESSION_TOKEN}
local_file: src/go.mongodb.org/mongo-driver/test_suite.tgz
optional: true
remote_file: ${UPLOAD_BUCKET}/${build_variant}/${revision}/${version_id}/${build_id}/logs/${task_id}-${execution}-test_suite.tgz
bucket: mciuploads
remote_file: ${build_variant}/${revision}/${version_id}/${build_id}/logs/${task_id}-${execution}-test_suite.tgz
bucket: ${aws_bucket}
permissions: public-read
content_type: ${content_type|text/plain}
display_name: "test_suite.tgz"
Expand Down Expand Up @@ -377,7 +383,7 @@ functions:
params:
shell: "bash"
working_dir: src/go.mongodb.org/mongo-driver
include_expansions_in_env: ["TOPOLOGY", "AUTH", "SSL", "MONGODB_URI", "CRYPT_SHARED_LIB_PATH", "SKIP_CRYPT_SHARED_LIB", "RACE", "MONGO_GO_DRIVER_COMPRESSOR", "REQUIRE_API_VERSION", "LOAD_BALANCER"]
include_expansions_in_env: ["TOPOLOGY", "AUTH", "SSL", "SKIP_CSOT_TESTS", "MONGODB_URI", "CRYPT_SHARED_LIB_PATH", "SKIP_CRYPT_SHARED_LIB", "RACE", "MONGO_GO_DRIVER_COMPRESSOR", "REQUIRE_API_VERSION", "LOAD_BALANCER"]
script: |
${PREPARE_SHELL}
bash ${PROJECT_DIRECTORY}/.evergreen/run-tests.sh
Expand Down Expand Up @@ -2090,6 +2096,8 @@ axes:
GCC_PATH: "/cygdrive/c/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/bin"
GO_DIST: "C:\\golang\\go1.22"
VENV_BIN_DIR: "Scripts"
# CSOT tests are unreliable on our slow Windows hosts.
SKIP_CSOT_TESTS: true
- id: "rhel87-64"
display_name: "RHEL 8.7"
run_on: rhel8.7-large
Expand All @@ -2101,6 +2109,8 @@ axes:
batchtime: 1440 # Run at most once per 24 hours.
variables:
GO_DIST: "/opt/golang/go1.22"
# CSOT tests are unreliable on our slow macOS hosts.
SKIP_CSOT_TESTS: true

# OSes that require >= 4.0 for SSL
- id: os-ssl-40
Expand All @@ -2114,6 +2124,8 @@ axes:
GCC_PATH: "/cygdrive/c/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/bin"
GO_DIST: "C:\\golang\\go1.22"
VENV_BIN_DIR: "Scripts"
# CSOT tests are unreliable on our slow Windows hosts.
SKIP_CSOT_TESTS: true
- id: "rhel87-64"
display_name: "RHEL 8.7"
run_on: rhel8.7-large
Expand All @@ -2125,6 +2137,8 @@ axes:
batchtime: 1440 # Run at most once per 24 hours.
variables:
GO_DIST: "/opt/golang/go1.22"
# CSOT tests are unreliable on our slow macOS hosts.
SKIP_CSOT_TESTS: true

- id: ocsp-rhel-87
display_name: OS
Expand All @@ -2146,6 +2160,8 @@ axes:
GCC_PATH: "/cygdrive/c/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/bin"
GO_DIST: "C:\\golang\\go1.22"
SKIP_ECS_AUTH_TEST: true
# CSOT tests are unreliable on our slow Windows hosts.
SKIP_CSOT_TESTS: true
- id: "ubuntu2004-64"
display_name: "Ubuntu 20.04"
run_on: ubuntu2004-test
Expand All @@ -2160,6 +2176,8 @@ axes:
SKIP_ECS_AUTH_TEST: true
SKIP_EC2_AUTH_TEST: true
SKIP_WEB_IDENTITY_AUTH_TEST: true
# CSOT tests are unreliable on our slow macOS hosts.
SKIP_CSOT_TESTS: true

- id: os-faas-80
display_name: OS
Expand Down
1 change: 1 addition & 0 deletions .evergreen/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ fi

AUTH=${AUTH} \
SSL=${SSL} \
SKIP_CSOT_TESTS=${SKIP_CSOT_TESTS} \
MONGO_GO_DRIVER_CA_FILE=${MONGO_GO_DRIVER_CA_FILE} \
MONGO_GO_DRIVER_KEY_FILE=${MONGO_GO_DRIVER_KEY_FILE} \
MONGO_GO_DRIVER_PKCS8_ENCRYPTED_KEY_FILE=${MONGO_GO_DRIVER_PKCS8_ENCRYPTED_KEY_FILE} \
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ defaults:

env:
# Changes per branch
SILK_ASSET_GROUP: mongodb-go-driver-v1
EVERGREEN_PROJECT: mongo-go-driver-v1
SILK_ASSET_GROUP: mongodb-go-driver-1.17
EVERGREEN_PROJECT: mongo-go-driver-release

jobs:
pre-publish:
Expand Down
5 changes: 3 additions & 2 deletions mongo/cursor.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,9 @@ func (c *Cursor) Close(ctx context.Context) error {
}

// All iterates the cursor and decodes each document into results. The results parameter must be a pointer to a slice.
// The slice pointed to by results will be completely overwritten. This method will close the cursor after retrieving
// all documents. If the cursor has been iterated, any previously iterated documents will not be included in results.
// The slice pointed to by results will be completely overwritten. A nil slice pointer will not be modified if the cursor
// has been closed, exhausted, or is empty. This method will close the cursor after retrieving all documents. If the
// cursor has been iterated, any previously iterated documents will not be included in results.
//
// This method requires driver version >= 1.1.0.
func (c *Cursor) All(ctx context.Context, results interface{}) error {
Expand Down
86 changes: 59 additions & 27 deletions mongo/cursor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,37 +97,69 @@ func TestCursor(t *testing.T) {
t.Run("TestAll", func(t *testing.T) {
t.Run("errors if argument is not pointer to slice", func(t *testing.T) {
cursor, err := newCursor(newTestBatchCursor(1, 5), nil, nil)
assert.Nil(t, err, "newCursor error: %v", err)
require.NoError(t, err, "newCursor error: %v", err)
err = cursor.All(context.Background(), []bson.D{})
assert.NotNil(t, err, "expected error, got nil")
assert.Error(t, err, "expected error, got nil")
})

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

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

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

t.Run("nil slice", func(t *testing.T) {
cursor, err := newCursor(newTestBatchCursor(0, 0), nil, nil)
require.NoError(t, err, "newCursor error: %v", err)

var docs []bson.D
err = cursor.All(context.Background(), &docs)
require.NoError(t, err, "All error: %v", err)
assert.Nil(t, docs, "expected nil docs")
})

t.Run("empty slice", func(t *testing.T) {
cursor, err := newCursor(newTestBatchCursor(0, 0), nil, nil)
require.NoError(t, err, "newCursor error: %v", err)

docs := []bson.D{}
err = cursor.All(context.Background(), &docs)
require.NoError(t, err, "All error: %v", err)
assert.NotNil(t, docs, "expected non-nil docs")
assert.Len(t, docs, 0, "expected 0 docs, got %v", len(docs))
})

t.Run("empty slice overwritten", func(t *testing.T) {
cursor, err := newCursor(newTestBatchCursor(0, 0), nil, nil)
require.NoError(t, err, "newCursor error: %v", err)

docs := []bson.D{{{"foo", "bar"}}, {{"hello", "world"}, {"pi", 3.14159}}}
err = cursor.All(context.Background(), &docs)
require.NoError(t, err, "All error: %v", err)
assert.NotNil(t, docs, "expected non-nil docs")
assert.Len(t, docs, 0, "expected 0 docs, got %v", len(docs))
})

t.Run("decodes each document into slice type", func(t *testing.T) {
cursor, err := newCursor(newTestBatchCursor(1, 5), nil, nil)
assert.Nil(t, err, "newCursor error: %v", err)
require.NoError(t, err, "newCursor error: %v", err)

type Document struct {
Foo int32 `bson:"foo"`
}
var docs []Document
err = cursor.All(context.Background(), &docs)
assert.Nil(t, err, "All error: %v", err)
assert.Equal(t, 5, len(docs), "expected 5 documents, got %v", len(docs))
require.NoError(t, err, "All error: %v", err)
assert.Len(t, docs, 5, "expected 5 documents, got %v", len(docs))

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

t.Run("multiple batches are included", func(t *testing.T) {
cursor, err := newCursor(newTestBatchCursor(2, 5), nil, nil)
assert.Nil(t, err, "newCursor error: %v", err)
require.NoError(t, err, "newCursor error: %v", err)
var docs []bson.D
err = cursor.All(context.Background(), &docs)
assert.Nil(t, err, "All error: %v", err)
assert.Equal(t, 10, len(docs), "expected 10 docs, got %v", len(docs))
require.NoError(t, err, "All error: %v", err)
assert.Len(t, docs, 10, "expected 10 docs, got %v", len(docs))

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

tbc := newTestBatchCursor(1, 5)
cursor, err := newCursor(tbc, nil, nil)
assert.Nil(t, err, "newCursor error: %v", err)
require.NoError(t, err, "newCursor error: %v", err)

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

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

cursor, err := newCursor(newTestBatchCursor(1, 5), nil, nil)
assert.Nil(t, err, "newCursor error: %v", err)
require.NoError(t, err, "newCursor error: %v", err)

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

cursor, err := newCursor(newTestBatchCursor(1, 5), nil, nil)
assert.Nil(t, err, "newCursor error: %v", err)
require.NoError(t, err, "newCursor error: %v", err)

err = cursor.All(context.Background(), &docs)
assert.NotNil(t, err, "expected error, got: %v", err)
assert.Error(t, err, "expected error, got: %v", err)
})
t.Run("with BSONOptions", func(t *testing.T) {
cursor, err := newCursor(
Expand All @@ -187,15 +219,15 @@ func TestCursor(t *testing.T) {
UseJSONStructTags: true,
},
nil)
require.NoError(t, err, "newCursor error")
require.NoError(t, err, "newCursor error: %v", err)

type myDocument struct {
A int32 `json:"foo"`
}
var got []myDocument

err = cursor.All(context.Background(), &got)
require.NoError(t, err, "All error")
require.NoError(t, err, "All error: %v", err)

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

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

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

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

// Check for error on Cursor.
assert.Nil(t, cur.Err(), "Cursor error: %v", cur.Err())
require.NoError(t, cur.Err(), "Cursor error: %v", cur.Err())

// Assert that a call to cur.Close will not fail.
err = cur.Close(context.Background())
assert.Nil(t, err, "Close error: %v", err)
require.NoError(t, err, "Close error: %v", err)
})

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

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

// Check for error on Cursor.
assert.NotNil(t, cur.Err(), "expected Cursor error, got nil")
assert.Error(t, cur.Err(), "expected Cursor error, got nil")
assert.Equal(t, mockErr, cur.Err(), "expected Cursor error %v, got %v",
mockErr, cur.Err())
})
Expand Down
8 changes: 8 additions & 0 deletions mongo/integration/csot_prose_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package integration

import (
"context"
"os"
"strings"
"testing"
"time"
Expand All @@ -22,6 +23,13 @@ import (
)

func TestCSOTProse(t *testing.T) {
// Skip CSOT tests when SKIP_CSOT_TESTS=true. In Evergreen, we typically set
// that environment variable on Windows and macOS because the CSOT spec
// tests are unreliable on those hosts.
if os.Getenv("SKIP_CSOT_TESTS") == "true" {
t.Skip("Skipping CSOT test because SKIP_CSOT_TESTS=true")
}

mt := mtest.New(t, mtest.NewOptions().CreateClient(false))

mt.RunOpts("1. multi-batch writes", mtest.NewOptions().MinServerVersion("4.4").
Expand Down
Loading