diff --git a/.evergreen/config.yml b/.evergreen/config.yml index 8c4bc4887e..f57ffb1e75 100644 --- a/.evergreen/config.yml +++ b/.evergreen/config.yml @@ -1741,10 +1741,6 @@ axes: display_name: "4.2" variables: VERSION: "4.2" - - id: "4.0" - display_name: "4.0" - variables: - VERSION: "4.0" - id: "rapid" display_name: "rapid" variables: @@ -2170,19 +2166,6 @@ buildvariants: tasks: - name: ".goleak" - - matrix_name: "tests-rhel-40-with-snappy-support" - tags: ["pullrequest"] - matrix_spec: { version: ["4.0"], os-ssl-40: ["rhel87-64"] } - display_name: "${version} ${os-ssl-40}" - tasks: - - name: ".test !.enterprise-auth !.zlib !.zstd" - - - matrix_name: "tests-windows-40-with-snappy-support" - matrix_spec: { version: ["4.0"], os-ssl-40: ["windows-64"] } - display_name: "${version} ${os-ssl-40}" - tasks: - - name: ".test !.enterprise-auth !.zlib !.zstd" - - matrix_name: "tests-rhel-44-plus-zlib-zstd-support" tags: ["pullrequest"] matrix_spec: { version: ["4.2", "4.4", "5.0", "6.0", "7.0", "8.0"], os-ssl-40: ["rhel87-64"] } diff --git a/README.md b/README.md index 247c7ee5f6..475c5d43d9 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ The MongoDB Go driver follows [semantic versioning](https://semver.org/) for its - Go 1.19 or higher. We aim to support the latest versions of Go. - Go 1.23 or higher is required to run the driver test suite. -- MongoDB 4.0 and higher. +- MongoDB 4.2 and higher. ## Installation diff --git a/internal/docexamples/examples_test.go b/internal/docexamples/examples_test.go index 9046971d90..387db97440 100644 --- a/internal/docexamples/examples_test.go +++ b/internal/docexamples/examples_test.go @@ -131,14 +131,8 @@ func TestDocumentationExamples(t *testing.T) { docexamples.ChangeStreamExamples(mt.T, csdb) }) - // Causal consistency examples cannot run on 4.0. - // TODO(GODRIVER-2238): Remove version filtering once failures on 4.0 sharded clusters are fixed. - mtOpts = mtest.NewOptions().MinServerVersion("4.2").Topologies(mtest.ReplicaSet) - mt.RunOpts("CausalConsistencyExamples/post4.2", mtOpts, func(mt *mtest.T) { - docexamples.CausalConsistencyExamples(mt.Client) - }) - mtOpts = mtest.NewOptions().MaxServerVersion("4.0").Topologies(mtest.ReplicaSet) - mt.RunOpts("CausalConsistencyExamples/pre4.0", mtOpts, func(mt *mtest.T) { + mtOpts = mtest.NewOptions().Topologies(mtest.ReplicaSet) + mt.RunOpts("CausalConsistencyExamples", mtOpts, func(mt *mtest.T) { docexamples.CausalConsistencyExamples(mt.Client) }) } diff --git a/internal/driverutil/description.go b/internal/driverutil/description.go index 899637997f..926de0bdf9 100644 --- a/internal/driverutil/description.go +++ b/internal/driverutil/description.go @@ -21,7 +21,7 @@ import ( ) const ( - MinWireVersion = 7 + MinWireVersion = 8 MaxWireVersion = 25 ) diff --git a/internal/integration/change_stream_test.go b/internal/integration/change_stream_test.go index 4bacc746bd..245174a6d0 100644 --- a/internal/integration/change_stream_test.go +++ b/internal/integration/change_stream_test.go @@ -259,34 +259,6 @@ func TestChangeStream_ReplicaSet(t *testing.T) { assert.Nil(mt, cs.Err(), "change stream error: %v", cs.Err()) }) - startAtOpTimeOpts := mtest.NewOptions().MinServerVersion("4.0").MaxServerVersion("4.0.6") - mt.RunOpts("include startAtOperationTime", startAtOpTimeOpts, func(mt *mtest.T) { - // $changeStream stage for ChangeStream against a server >=4.0 and <4.0.7 that has not received any results yet - // MUST include a startAtOperationTime option when resuming a changestream. - - cs, err := mt.Coll.Watch(context.Background(), mongo.Pipeline{}) - assert.Nil(mt, err, "Watch error: %v", err) - defer closeStream(cs) - - generateEvents(mt, 1) - // kill cursor to force resumable error - killChangeStreamCursor(mt, cs) - - mt.ClearEvents() - // change stream should resume once and get new change - assert.True(mt, cs.Next(context.Background()), "expected Next to return true, got false") - // Next should cause getMore, killCursors, and aggregate to run - assert.NotNil(mt, mt.GetStartedEvent(), "expected getMore event, got nil") - assert.NotNil(mt, mt.GetStartedEvent(), "expected killCursors event, got nil") - aggEvent := mt.GetStartedEvent() - assert.NotNil(mt, aggEvent, "expected aggregate event, got nil") - assert.Equal(mt, "aggregate", aggEvent.CommandName, "expected command name 'aggregate', got '%v'", aggEvent.CommandName) - - // check for startAtOperationTime in pipeline - csStage := aggEvent.Command.Lookup("pipeline").Array().Index(0).Document() // $changeStream stage - _, err = csStage.Lookup("$changeStream").Document().LookupErr("startAtOperationTime") - assert.Nil(mt, err, "startAtOperationTime not included in aggregate command") - }) mt.RunOpts("decode does not panic", noClientOpts, func(mt *mtest.T) { testCases := []struct { name string @@ -418,53 +390,6 @@ func TestChangeStream_ReplicaSet(t *testing.T) { }) } }) - - noPbrtOpts := mtest.NewOptions().MaxServerVersion("4.0.6") - mt.RunOpts("without PBRT support", noPbrtOpts, func(mt *mtest.T) { - collName := mt.Coll.Name() - dbName := mt.Coll.Database().Name() - cs, err := mt.Coll.Watch(context.Background(), mongo.Pipeline{}) - assert.Nil(mt, err, "Watch error: %v", err) - defer closeStream(cs) - - compareResumeTokens(mt, cs, nil) // should be no resume token because no PBRT - numEvents := 5 - generateEvents(mt, numEvents) - // iterate once to get a resume token - assert.True(mt, cs.Next(context.Background()), "expected Next to return true, got false") - token := cs.ResumeToken() - assert.NotNil(mt, token, "expected resume token, got nil") - - testCases := []struct { - name string - opts *options.ChangeStreamOptionsBuilder - iterateStream bool // whether or not resulting change stream should be iterated - initialToken bson.Raw - numDocsExpected int - }{ - {"resumeAfter", options.ChangeStream().SetResumeAfter(token), true, token, numEvents - 1}, - {"no options", nil, false, nil, 0}, - } - for _, tc := range testCases { - mt.Run(tc.name, func(mt *mtest.T) { - coll := mt.Client.Database(dbName).Collection(collName) - cs, err := coll.Watch(context.Background(), mongo.Pipeline{}, tc.opts) - assert.Nil(mt, err, "Watch error: %v", err) - defer closeStream(cs) - - compareResumeTokens(mt, cs, tc.initialToken) - if !tc.iterateStream { - return - } - - for i := 0; i < tc.numDocsExpected; i++ { - assert.True(mt, cs.Next(context.Background()), "expected Next to return true, got false") - // current resume token should always equal _id of current document - compareResumeTokens(mt, cs, cs.Current.Lookup("_id").Document()) - } - }) - } - }) }) }) mt.RunOpts("try next", noClientOpts, func(mt *mtest.T) { @@ -826,17 +751,6 @@ func generateEvents(mt *mtest.T, numEvents int) { } } -func killChangeStreamCursor(mt *mtest.T, cs *mongo.ChangeStream) { - mt.Helper() - - db := mt.Coll.Database().Client().Database("admin") - err := db.RunCommand(context.Background(), bson.D{ - {"killCursors", mt.Coll.Name()}, - {"cursors", bson.A{cs.ID()}}, - }).Err() - assert.Nil(mt, err, "killCursors error: %v", err) -} - // returns pbrt, operationTime from aggregate command response func getAggregateResponseInfo(mt *mtest.T) (bson.Raw, bson.Timestamp) { mt.Helper() diff --git a/internal/integration/primary_stepdown_test.go b/internal/integration/primary_stepdown_test.go index ac7f7b4f21..0e8bae6a2d 100644 --- a/internal/integration/primary_stepdown_test.go +++ b/internal/integration/primary_stepdown_test.go @@ -55,25 +55,16 @@ func TestConnectionsSurvivePrimaryStepDown(t *testing.T) { }) mt.RunOpts("server errors", noClientOpts, func(mt *mtest.T) { testCases := []struct { - name string - minVersion, maxVersion string - errCode int32 - poolCleared bool + name string + errCode int32 + poolCleared bool }{ - {"notPrimary keep pool", "4.2", "", errorNotPrimary, false}, - {"notPrimary reset pool", "4.0", "4.0", errorNotPrimary, true}, - {"shutdown in progress reset pool", "4.0", "", errorShutdownInProgress, true}, - {"interrupted at shutdown reset pool", "4.0", "", errorInterruptedAtShutdown, true}, + {"notPrimary keep pool", errorNotPrimary, false}, + {"shutdown in progress reset pool", errorShutdownInProgress, true}, + {"interrupted at shutdown reset pool", errorInterruptedAtShutdown, true}, } for _, tc := range testCases { - opts := mtest.NewOptions() - if tc.minVersion != "" { - opts.MinServerVersion(tc.minVersion) - } - if tc.maxVersion != "" { - opts.MaxServerVersion(tc.maxVersion) - } - mt.RunOpts(tc.name, opts, func(mt *mtest.T) { + mt.Run(tc.name, func(mt *mtest.T) { tpm := eventtest.NewTestPoolMonitor() mt.ResetClient(options.Client(). SetRetryWrites(false). diff --git a/internal/integration/sdam_error_handling_test.go b/internal/integration/sdam_error_handling_test.go index 9668f52bb6..737cb67830 100644 --- a/internal/integration/sdam_error_handling_test.go +++ b/internal/integration/sdam_error_handling_test.go @@ -36,7 +36,6 @@ func TestSDAMErrorHandling(t *testing.T) { baseMtOpts := func() *mtest.Options { mtOpts := mtest.NewOptions(). Topologies(mtest.ReplicaSet, mtest.Single). // Don't run on sharded clusters to avoid complexity of sharded failpoints. - MinServerVersion("4.0"). // 4.0+ is required to use failpoints on replica sets. ClientOptions(baseClientOpts()) if mtest.ClusterTopologyKind() == mtest.Sharded { @@ -241,7 +240,6 @@ func TestSDAMErrorHandling(t *testing.T) { // This causes the SDAM error handling code path to think we've already handled this state change and // ignore the error because it's stale. To avoid this altogether, we cap the test to <= 4.2. serverErrorsMtOpts := baseMtOpts(). - MinServerVersion("4.0"). // failCommand support MaxServerVersion("4.2"). ClientOptions(baseClientOpts().SetRetryWrites(false)) diff --git a/internal/spectest/skip.go b/internal/spectest/skip.go index 905254ba4a..189b38b447 100644 --- a/internal/spectest/skip.go +++ b/internal/spectest/skip.go @@ -841,6 +841,18 @@ var skipTests = map[string][]string{ "Support queryable encryption in Client.BulkWrite (GODRIVER-3403)": { "TestUnifiedSpec/crud/tests/unified/client-bulkWrite-qe.json", }, + + // Pre-4.2 SDAM tests + "Pre-4.2 SDAM tests": { + "TestSDAMSpec/errors/pre-42-InterruptedAtShutdown.json", + "TestSDAMSpec/errors/pre-42-InterruptedDueToReplStateChange.json", + "TestSDAMSpec/errors/pre-42-LegacyNotPrimary.json", + "TestSDAMSpec/errors/pre-42-NotPrimaryNoSecondaryOk.json", + "TestSDAMSpec/errors/pre-42-NotPrimaryOrSecondary.json", + "TestSDAMSpec/errors/pre-42-NotWritablePrimary.json", + "TestSDAMSpec/errors/pre-42-PrimarySteppedDown.json", + "TestSDAMSpec/errors/pre-42-ShutdownInProgress.json", + }, } // CheckSkip checks if the fully-qualified test name matches a list of skipped test names for a given reason. diff --git a/mongo/options/changestreamoptions.go b/mongo/options/changestreamoptions.go index 9e5bb93b02..92f19638c0 100644 --- a/mongo/options/changestreamoptions.go +++ b/mongo/options/changestreamoptions.go @@ -135,7 +135,7 @@ func (cso *ChangeStreamOptionsBuilder) SetShowExpandedEvents(see bool) *ChangeSt } // SetStartAtOperationTime sets the value for the StartAtOperationTime field. If specified, the change stream -// will only return changes that occurred at or after the given timestamp. This MongoDB versions >= 4.0. +// will only return changes that occurred at or after the given timestamp. // If this is specified, ResumeAfter and StartAfter must not be set. func (cso *ChangeStreamOptionsBuilder) SetStartAtOperationTime(t *bson.Timestamp) *ChangeStreamOptionsBuilder { cso.Opts = append(cso.Opts, func(opts *ChangeStreamOptions) error { diff --git a/mongo/options/listcollectionsoptions.go b/mongo/options/listcollectionsoptions.go index 14f96cc627..c69a6dc4db 100644 --- a/mongo/options/listcollectionsoptions.go +++ b/mongo/options/listcollectionsoptions.go @@ -65,8 +65,7 @@ func (lc *ListCollectionsOptionsBuilder) SetBatchSize(size int32) *ListCollectio // SetAuthorizedCollections sets the value for the AuthorizedCollections field. If true, and // NameOnly is true, limits the documents returned to only contain collections the user is -// authorized to use. The default value is false. This option is only valid for MongoDB server -// versions >= 4.0. Server versions < 4.0 ignore this option. +// authorized to use. The default value is false. func (lc *ListCollectionsOptionsBuilder) SetAuthorizedCollections(b bool) *ListCollectionsOptionsBuilder { lc.Opts = append(lc.Opts, func(opts *ListCollectionsOptions) error { opts.AuthorizedCollections = &b diff --git a/x/mongo/driver/integration/scram_test.go b/x/mongo/driver/integration/scram_test.go index d75623e051..5638dbfbd9 100644 --- a/x/mongo/driver/integration/scram_test.go +++ b/x/mongo/driver/integration/scram_test.go @@ -12,7 +12,6 @@ import ( "os" "testing" - "go.mongodb.org/mongo-driver/v2/internal/driverutil" "go.mongodb.org/mongo-driver/v2/internal/integtest" "go.mongodb.org/mongo-driver/v2/internal/serverselector" "go.mongodb.org/mongo-driver/v2/mongo/options" @@ -39,10 +38,6 @@ func TestSCRAM(t *testing.T) { noerr(t, err) defer serverConnection.Close() - if !driverutil.VersionRangeIncludes(*serverConnection.Description().WireVersion, 7) { - t.Skip("Skipping because MongoDB 4.0 is needed for SCRAM-SHA-256") - } - // Unicode constants for testing var romanFour = "\u2163" // ROMAN NUMERAL FOUR -> SASL prepped is "IV" var romanNine = "\u2168" // ROMAN NUMERAL NINE -> SASL prepped is "IX" diff --git a/x/mongo/driver/topology/fsm.go b/x/mongo/driver/topology/fsm.go index 530b2169e6..26e2fc320b 100644 --- a/x/mongo/driver/topology/fsm.go +++ b/x/mongo/driver/topology/fsm.go @@ -20,7 +20,7 @@ import ( var ( // MinSupportedMongoDBVersion is the version string for the lowest MongoDB version supported by the driver. - MinSupportedMongoDBVersion = "4.0" + MinSupportedMongoDBVersion = "4.2" // SupportedWireVersions is the range of wire versions supported by the driver. SupportedWireVersions = driverutil.NewVersionRange(driverutil.MinWireVersion, driverutil.MaxWireVersion) diff --git a/x/mongo/driver/topology/sdam_spec_test.go b/x/mongo/driver/topology/sdam_spec_test.go index 237e53c33c..eb10d40916 100644 --- a/x/mongo/driver/topology/sdam_spec_test.go +++ b/x/mongo/driver/topology/sdam_spec_test.go @@ -463,6 +463,8 @@ func runTest(t *testing.T, directory string, filename string) { assert.Nil(t, err, "ReadFile error: %v", err) t.Run(directory+"/"+filename, func(t *testing.T) { + spectest.CheckSkip(t) + var test testCase err = bson.UnmarshalExtJSON(content, false, &test) assert.Nil(t, err, "Unmarshal error: %v", err) diff --git a/x/mongo/driver/topology/topology_test.go b/x/mongo/driver/topology/topology_test.go index a4acb4732e..536bb933e8 100644 --- a/x/mongo/driver/topology/topology_test.go +++ b/x/mongo/driver/topology/topology_test.go @@ -126,7 +126,7 @@ func TestServerSelection(t *testing.T) { } want := fmt.Errorf( "server at %s reports wire version %d, but this version of the Go driver requires "+ - "at least 7 (MongoDB 4.0)", + "at least 8 (MongoDB 4.2)", desc.Servers[0].Addr.String(), desc.Servers[0].WireVersion.Max, )