diff --git a/bson/bson_corpus_spec_test.go b/bson/bson_corpus_spec_test.go index 043aa2f019..5fce4cfd69 100644 --- a/bson/bson_corpus_spec_test.go +++ b/bson/bson_corpus_spec_test.go @@ -275,11 +275,7 @@ func runTest(t *testing.T, file string) { content, err := os.ReadFile(filepath) require.NoError(t, err) - // Remove ".json" from filename. - file = file[:len(file)-5] - testName := "bson_corpus--" + file - - t.Run(testName, func(t *testing.T) { + t.Run(file, func(t *testing.T) { var test testCase require.NoError(t, json.Unmarshal(content, &test)) @@ -429,7 +425,7 @@ func runTest(t *testing.T, file string) { }) } -func Test_BsonCorpus(t *testing.T) { +func TestBSONCorpus(t *testing.T) { jsonFiles, err := findJSONFilesInDir(dataDir) require.NoErrorf(t, err, "error finding JSON files in %s: %v", dataDir, err) diff --git a/internal/integration/unified/unified_spec_runner.go b/internal/integration/unified/unified_spec_runner.go index 2ca3f27fbd..01b64fd35a 100644 --- a/internal/integration/unified/unified_spec_runner.go +++ b/internal/integration/unified/unified_spec_runner.go @@ -24,71 +24,6 @@ import ( ) var ( - skippedTests = map[string]string{ - // GODRIVER-1773: This test runs a "find" with limit=4 and batchSize=3. It expects batchSize values of three for - // the "find" and one for the "getMore", but we send three for both. - "A successful find event with a getmore and the server kills the cursor (<= 4.4)": "See GODRIVER-1773", - - // GODRIVER-2577: The following spec tests require canceling ops immediately, but the current logic clears pools - // and cancels in-progress ops after two the heartbeat failures. - "Connection pool clear uses interruptInUseConnections=true after monitor timeout": "Godriver clears after multiple timeout", - "Error returned from connection pool clear with interruptInUseConnections=true is retryable": "Godriver clears after multiple timeout", - "Error returned from connection pool clear with interruptInUseConnections=true is retryable for write": "Godriver clears after multiple timeout", - - // TODO(GODRIVER-2843): Fix and unskip these test cases. - "Find operation with snapshot": "Test fails frequently. See GODRIVER-2843", - "Write commands with snapshot session do not affect snapshot reads": "Test fails frequently. See GODRIVER-2843", - - // TODO(GODRIVER-3043): Avoid Appending Write/Read Concern in Atlas Search - // Index Helper Commands. - "dropSearchIndex ignores read and write concern": "Sync GODRIVER-3074, but skip testing bug GODRIVER-3043", - "listSearchIndexes ignores read and write concern": "Sync GODRIVER-3074, but skip testing bug GODRIVER-3043", - "updateSearchIndex ignores the read and write concern": "Sync GODRIVER-3074, but skip testing bug GODRIVER-3043", - - // TODO(DRIVERS-2829): Create CSOT Legacy Timeout Analogues and Compatibility Field - "Reset server and pool after network timeout error during authentication": "Uses unsupported socketTimeoutMS", - "Ignore network timeout error on find": "Uses unsupported socketTimeoutMS", - "A successful find with options": "Uses unsupported maxTimeMS", - "estimatedDocumentCount with maxTimeMS": "Uses unsupported maxTimeMS", - "supports configuring getMore maxTimeMS": "Uses unsupported maxTimeMS", - - // TODO(GODRIVER-3137): Implement Gossip cluster time" - "unpin after TransientTransactionError error on commit": "Implement GODRIVER-3137", - - // TODO(GODRIVER-3034): Drivers should unpin connections when ending a session - "unpin on successful abort": "Implement GODRIVER-3034", - "unpin after non-transient error on abort": "Implement GODRIVER-3034", - "unpin after TransientTransactionError error on abort": "Implement GODRIVER-3034", - "unpin when a new transaction is started": "Implement GODRIVER-3034", - "unpin when a non-transaction write operation uses a session": "Implement GODRIVER-3034", - "unpin when a non-transaction read operation uses a session": "Implement GODRIVER-3034", - - // DRIVERS-2722: Setting "maxTimeMS" on a command that creates a cursor - // also limits the lifetime of the cursor. That may be surprising to - // users, so omit "maxTimeMS" from operations that return user-managed - // cursors. - "timeoutMS can be overridden for a find": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", - "timeoutMS can be configured for an operation - find on collection": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", - "timeoutMS can be configured for an operation - aggregate on collection": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", - "timeoutMS can be configured for an operation - aggregate on database": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", - "timeoutMS can be configured on a MongoClient - find on collection": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", - "timeoutMS can be configured on a MongoClient - aggregate on collection": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", - "timeoutMS can be configured on a MongoClient - aggregate on database": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", - "operation is retried multiple times for non-zero timeoutMS - find on collection": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", - "operation is retried multiple times for non-zero timeoutMS - aggregate on collection": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", - "operation is retried multiple times for non-zero timeoutMS - aggregate on database": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", - "timeoutMS applied to find command": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", - - // DRIVERS-2953: This test requires that the driver sends a "getMore" - // with "maxTimeMS" set. However, "getMore" can only include "maxTimeMS" - // for tailable awaitData cursors. Including "maxTimeMS" on "getMore" - // for any other cursor type results in a server error: - // - // (BadValue) cannot set maxTimeMS on getMore command for a non-awaitData cursor - // - "Non-tailable cursor lifetime remaining timeoutMS applied to getMore if timeoutMode is unset": "maxTimeMS can't be set on a getMore. See DRIVERS-2953", - } - logMessageValidatorTimeout = 10 * time.Millisecond lowHeartbeatFrequency = 500 * time.Millisecond ) @@ -171,6 +106,8 @@ func runTestFile(t *testing.T, filepath string, expectValidFail bool, opts ...*O CreateClient(false) mt.RunOpts(testCase.Description, mtOpts, func(mt *mtest.T) { + spectest.CheckSkip(mt.T) + // Skip CSOT spec 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. @@ -186,6 +123,7 @@ func runTestFile(t *testing.T, filepath string, expectValidFail bool, opts ...*O } } }() + err := testCase.Run(mt) if expectValidFail { if err != nil { @@ -285,9 +223,6 @@ func (tc *TestCase) Run(ls LoggerSkipper) error { if tc.SkipReason != nil { ls.Skipf("skipping for reason: %q", *tc.SkipReason) } - if skipReason, ok := skippedTests[tc.Description]; ok { - ls.Skipf("skipping due to known failure: %q", skipReason) - } // Validate that we support the schema declared by the test file before attempting to use its contents. if err := checkSchemaVersion(tc.schemaVersion); err != nil { diff --git a/internal/integration/unified_spec_test.go b/internal/integration/unified_spec_test.go index 2406426d9c..c8868dac51 100644 --- a/internal/integration/unified_spec_test.go +++ b/internal/integration/unified_spec_test.go @@ -27,6 +27,7 @@ import ( "go.mongodb.org/mongo-driver/v2/internal/failpoint" "go.mongodb.org/mongo-driver/v2/internal/integration/mtest" "go.mongodb.org/mongo-driver/v2/internal/integtest" + "go.mongodb.org/mongo-driver/v2/internal/spectest" "go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo/address" "go.mongodb.org/mongo-driver/v2/mongo/options" @@ -37,26 +38,11 @@ import ( ) const ( - gridFSFiles = "fs.files" - gridFSChunks = "fs.chunks" - spec1403SkipReason = "servers less than 4.2 do not have mongocryptd; see SPEC-1403" - godriver2123SkipReason = "failpoints and timeouts together cause failures; see GODRIVER-2123" + gridFSFiles = "fs.files" + gridFSChunks = "fs.chunks" ) -var ( - defaultHeartbeatInterval = 500 * time.Millisecond - skippedTestDescriptions = map[string]string{ - // SPEC-1403: This test checks to see if the correct error is thrown when auto encrypting with a server < 4.2. - // Currently, the test will fail because a server < 4.2 wouldn't have mongocryptd, so Client construction - // would fail with a mongocryptd spawn error. - "operation fails with maxWireVersion < 8": spec1403SkipReason, - // GODRIVER-2123: The two tests below use a failpoint and a socket or server selection timeout. - // The timeout causes the eventual clearing of the failpoint in the test runner to fail with an - // i/o timeout. - "Ignore network timeout error on find": godriver2123SkipReason, - "Network error on minPoolSize background creation": godriver2123SkipReason, - } -) +var defaultHeartbeatInterval = 500 * time.Millisecond type testFile struct { RunOn []mtest.RunOnBlock `bson:"runOn"` @@ -254,12 +240,11 @@ func runSpecTestCase(mt *mtest.T, test *testCase, testFile testFile) { // Start the test without setting client options so the setup will be done with a default client. mt.RunOpts(test.Description, opts, func(mt *mtest.T) { + spectest.CheckSkip(mt.T) + if len(test.SkipReason) > 0 { mt.Skip(test.SkipReason) } - if skipReason, ok := skippedTestDescriptions[test.Description]; ok { - mt.Skipf("skipping due to known failure: %v", skipReason) - } // work around for SERVER-39704: run a non-transactional distinct against each shard in a sharded cluster if mtest.ClusterTopologyKind() == mtest.Sharded && test.Description == "distinct" { diff --git a/internal/serverselector/server_selector_test.go b/internal/serverselector/server_selector_test.go index 886c3fe994..0d114d2516 100644 --- a/internal/serverselector/server_selector_test.go +++ b/internal/serverselector/server_selector_test.go @@ -296,11 +296,7 @@ func runTest(t *testing.T, testsDir string, directory string, filename string) { content, err := ioutil.ReadFile(filepath) require.NoError(t, err) - // Remove ".json" from filename. - filename = filename[:len(filename)-5] - testName := directory + "/" + filename + ":" - - t.Run(testName, func(t *testing.T) { + t.Run(directory+"/"+filename, func(t *testing.T) { var test testCase require.NoError(t, bson.UnmarshalExtJSON(content, true, &test)) diff --git a/internal/spectest/skip.go b/internal/spectest/skip.go new file mode 100644 index 0000000000..3c121f791b --- /dev/null +++ b/internal/spectest/skip.go @@ -0,0 +1,146 @@ +// Copyright (C) MongoDB, Inc. 2025-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package spectest + +import "testing" + +// skipTests is a map of "fully-qualified test name" to "the reason for skipping +// the test". +var skipTests = map[string]string{ + "TestURIOptionsSpec/single-threaded-options.json/Valid_options_specific_to_single-threaded_drivers_are_parsed_correctly": "The Go Driver is not single-threaded.", + // GODRIVER-2348: The wtimeoutMS write concern option is not supported. + "TestURIOptionsSpec/concern-options.json/Valid_read_and_write_concern_are_parsed_correctly": "The wtimeoutMS write concern option is not supported", + + // SPEC-1403: This test checks to see if the correct error is thrown when + // auto encrypting with a server < 4.2. Currently, the test will fail + // because a server < 4.2 wouldn't have mongocryptd, so Client construction + // would fail with a mongocryptd spawn error. + "TestClientSideEncryptionSpec/maxWireVersion.json/operation_fails_with_maxWireVersion_<_8": "Servers less than 4.2 do not have mongocryptd; see SPEC-1403", + + // GODRIVER-1827: These 2 tests assert that in-use connections are not + // closed until checked back into a closed pool, but the Go connection pool + // aggressively closes in-use connections. That behavior is currently + // required by the "Client.Disconnect" API, so skip the tests. + "TestCMAPSpec/pool-close-destroy-conns.json/When_a_pool_is_closed,_it_MUST_first_destroy_all_available_connections_in_that_pool": "Test requires that close does not aggressively close used connections", + "TestCMAPSpec/pool-close-destroy-conns.json/must_destroy_checked_in_connection_if_pool_has_been_closed": "Test requires that close does not aggressively close used connections", + + // GODRIVER-1826: The load-balancer SDAM error handling test "errors during + // authentication are processed" currently asserts that handshake errors + // trigger events "pool cleared" then "connection closed". However, the + // "error during minPoolSize population clears pool" test asserts that + // handshake errors trigger events "connection closed" then "pool cleared". + // The Go driver uses the same code path for creating all application + // connections, so those opposing event orders cannot be satisfied + // simultaneously. + // + // TODO(DRIVERS-1785): Re-enable this test once the spec test is updated to + // use the same event order as the "errors during authentication are + // processed" load-balancer SDAM spec test. + "TestCMAPSpec/pool-create-min-size-error.json/error_during_minPoolSize_population_clears_pool": "Event ordering is incompatible with load-balancer SDAM spec test (DRIVERS-1785)", + + // GODRIVER-1826: The Go connection pool does not currently always deliver + // connections created by maintain() to waiting check-outs. There is a race + // condition between the goroutine started by maintain() to check-in a + // requested connection and createConnections() picking up the next wantConn + // created by the waiting check-outs. Most of the time, createConnections() + // wins and starts creating new connections. That is not a problem for + // general use cases, but it prevents the "threads blocked by maxConnecting + // check out minPoolSize connections" test from passing. + // + // TODO(DRIVERS-2225): Re-enable this test once the spec test is updated to + // support the Go pool minPoolSize maintain() behavior. + "TestCMAPSpec/pool-checkout-minPoolSize-connection-maxConnecting.json/threads_blocked_by_maxConnecting_check_out_minPoolSize_connections": "Test requires that connections established by minPoolSize are immediately used to satisfy check-out requests (DRIVERS-2225)", + + // GODRIVER-1826: The Go connection pool currently delivers any available + // connection to the earliest waiting check-out request, independent of if + // that check-out request already requested a new connection. That behavior + // is currently incompatible with the "threads blocked by maxConnecting + // check out returned connections" test, which expects that check-out + // requests that request a new connection cannot be satisfied by a check-in. + // + // TODO(DRIVERS-2223): Re-enable this test once the spec test is updated to + // support the Go pool check-in behavior. + "TestCMAPSpec/pool-checkout-returned-connection-maxConnecting.json/threads_blocked_by_maxConnecting_check_out_returned_connections": "Test requires a checked-in connections cannot satisfy a check-out waiting on a new connection (DRIVERS-2223)", + + // TODO(GODRIVER-2129): Re-enable this test once GODRIVER-2129 is done. + "TestAuthSpec/connection-string.json/must_raise_an_error_when_the_hostname_canonicalization_is_invalid": "Support will be added with GODRIVER-2129.", + + // GODRIVER-1773: This test runs a "find" with limit=4 and batchSize=3. It + // expects batchSize values of three for the "find" and one for the + // "getMore", but we send three for both. + "TestUnifiedSpec/command-monitoring/find.json/A_successful_find_event_with_a_getmore_and_the_server_kills_the_cursor_(<=_4.4)": "See GODRIVER-1773", + "TestUnifiedSpec/unified-test-format/valid-pass/poc-command-monitoring.json/A_successful_find_event_with_a_getmore_and_the_server_kills_the_cursor_(<=_4.4)": "See GODRIVER-1773", + + // GODRIVER-2577: The following spec tests require canceling ops + // immediately, but the current logic clears pools and cancels in-progress + // ops after two the heartbeat failures. + "TestUnifiedSpec/server-discovery-and-monitoring/unified/interruptInUse-pool-clear.json/Connection_pool_clear_uses_interruptInUseConnections=true_after_monitor_timeout": "Go Driver clears after multiple timeout", + "TestUnifiedSpec/server-discovery-and-monitoring/unified/interruptInUse-pool-clear.json/Error_returned_from_connection_pool_clear_with_interruptInUseConnections=true_is_retryable": "Go Driver clears after multiple timeout", + "TestUnifiedSpec/server-discovery-and-monitoring/unified/interruptInUse-pool-clear.json/Error_returned_from_connection_pool_clear_with_interruptInUseConnections=true_is_retryable_for_write": "Go Driver clears after multiple timeout", + + // TODO(GODRIVER-2843): Fix and unskip these test cases. + "TestUnifiedSpec/sessions/snapshot-sessions.json/Find_operation_with_snapshot": "Test fails frequently. See GODRIVER-2843", + "TestUnifiedSpec/sessions/snapshot-sessions.json/Write_commands_with_snapshot_session_do_not_affect_snapshot_reads": "Test fails frequently. See GODRIVER-2843", + + // TODO(GODRIVER-3043): Avoid Appending Write/Read Concern in Atlas Search + // Index Helper Commands. + "TestUnifiedSpec/index-management/searchIndexIgnoresReadWriteConcern.json/dropSearchIndex_ignores_read_and_write_concern": "Sync GODRIVER-3074, but skip testing bug GODRIVER-3043", + "TestUnifiedSpec/index-management/searchIndexIgnoresReadWriteConcern.json/listSearchIndexes_ignores_read_and_write_concern": "Sync GODRIVER-3074, but skip testing bug GODRIVER-3043", + "TestUnifiedSpec/index-management/searchIndexIgnoresReadWriteConcern.json/updateSearchIndex_ignores_the_read_and_write_concern": "Sync GODRIVER-3074, but skip testing bug GODRIVER-3043", + + // TODO(DRIVERS-2829): Create CSOT Legacy Timeout Analogues and + // Compatibility Field + "TestUnifiedSpec/server-discovery-and-monitoring/unified/auth-network-timeout-error.json/Reset_server_and_pool_after_network_timeout_error_during_authentication": "Uses unsupported socketTimeoutMS", + "TestUnifiedSpec/server-discovery-and-monitoring/unified/find-network-timeout-error.json/Ignore_network_timeout_error_on_find": "Uses unsupported socketTimeoutMS", + "TestUnifiedSpec/command-monitoring/find.json/A_successful_find_with_options": "Uses unsupported maxTimeMS", + "TestUnifiedSpec/crud/unified/estimatedDocumentCount.json/estimatedDocumentCount_with_maxTimeMS": "Uses unsupported maxTimeMS", + "TestUnifiedSpec/run-command/runCursorCommand.json/supports_configuring_getMore_maxTimeMS": "Uses unsupported maxTimeMS", + + // TODO(GODRIVER-3137): Implement Gossip cluster time" + "TestUnifiedSpec/transactions/unified/mongos-unpin.json/unpin_after_TransientTransactionError_error_on_commit": "Implement GODRIVER-3137", + + // TODO(GODRIVER-3034): Drivers should unpin connections when ending a + // session. + "TestUnifiedSpec/transactions/unified/mongos-unpin.json/unpin_on_successful_abort": "Implement GODRIVER-3034", + "TestUnifiedSpec/transactions/unified/mongos-unpin.json/unpin_after_non-transient_error_on_abort": "Implement GODRIVER-3034", + "TestUnifiedSpec/transactions/unified/mongos-unpin.json/unpin_after_TransientTransactionError_error_on_abort": "Implement GODRIVER-3034", + "TestUnifiedSpec/transactions/unified/mongos-unpin.json/unpin_when_a_new_transaction_is_started": "Implement GODRIVER-3034", + "TestUnifiedSpec/transactions/unified/mongos-unpin.json/unpin_when_a_non-transaction_write_operation_uses_a_session": "Implement GODRIVER-3034", + "TestUnifiedSpec/transactions/unified/mongos-unpin.json/unpin_when_a_non-transaction_read_operation_uses_a_session": "Implement GODRIVER-3034", + + // DRIVERS-2722: Setting "maxTimeMS" on a command that creates a cursor also + // limits the lifetime of the cursor. That may be surprising to users, so + // omit "maxTimeMS" from operations that return user-managed cursors. + "TestUnifiedSpec/client-side-operations-timeout/gridfs-find.json/timeoutMS_can_be_overridden_for_a_find": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", + "TestUnifiedSpec/client-side-operations-timeout/override-operation-timeoutMS.json/timeoutMS_can_be_configured_for_an_operation_-_find_on_collection": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", + "TestUnifiedSpec/client-side-operations-timeout/override-operation-timeoutMS.json/timeoutMS_can_be_configured_for_an_operation_-_aggregate_on_collection": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", + "TestUnifiedSpec/client-side-operations-timeout/override-operation-timeoutMS.json/timeoutMS_can_be_configured_for_an_operation_-_aggregate_on_database": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", + "TestUnifiedSpec/client-side-operations-timeout/global-timeoutMS.json/timeoutMS_can_be_configured_on_a_MongoClient_-_find_on_collection": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", + "TestUnifiedSpec/client-side-operations-timeout/global-timeoutMS.json/timeoutMS_can_be_configured_on_a_MongoClient_-_aggregate_on_collection": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", + "TestUnifiedSpec/client-side-operations-timeout/global-timeoutMS.json/timeoutMS_can_be_configured_on_a_MongoClient_-_aggregate_on_database": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", + "TestUnifiedSpec/client-side-operations-timeout/retryability-timeoutMS.json/operation_is_retried_multiple_times_for_non-zero_timeoutMS_-_find_on_collection": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", + "TestUnifiedSpec/client-side-operations-timeout/retryability-timeoutMS.json/operation_is_retried_multiple_times_for_non-zero_timeoutMS_-_aggregate_on_collection": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", + "TestUnifiedSpec/client-side-operations-timeout/retryability-timeoutMS.json/operation_is_retried_multiple_times_for_non-zero_timeoutMS_-_aggregate_on_database": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", + "TestUnifiedSpec/client-side-operations-timeout/gridfs-find.json/timeoutMS_applied_to_find_command": "maxTimeMS is disabled on find and aggregate. See DRIVERS-2722.", + + // DRIVERS-2953: This test requires that the driver sends a "getMore" with + // "maxTimeMS" set. However, "getMore" can only include "maxTimeMS" for + // tailable awaitData cursors. Including "maxTimeMS" on "getMore" for any + // other cursor type results in a server error: + // + // (BadValue) cannot set maxTimeMS on getMore command for a non-awaitData cursor + // + "TestUnifiedSpec/client-side-operations-timeout/runCursorCommand.json/Non-tailable_cursor_lifetime_remaining_timeoutMS_applied_to_getMore_if_timeoutMode_is_unset": "maxTimeMS can't be set on a getMore. See DRIVERS-2953", +} + +// CheckSkip checks if the fully-qualified test name matches a skipped test +// name. If the test name matches, the reason is logged and the test is skipped. +func CheckSkip(t *testing.T) { + if reason := skipTests[t.Name()]; reason != "" { + t.Skipf("Skipping due to known failure: %q", reason) + } +} diff --git a/x/mongo/driver/auth/auth_spec_test.go b/x/mongo/driver/auth/auth_spec_test.go index e8d246ae34..1530cc3a74 100644 --- a/x/mongo/driver/auth/auth_spec_test.go +++ b/x/mongo/driver/auth/auth_spec_test.go @@ -18,11 +18,6 @@ import ( "go.mongodb.org/mongo-driver/v2/mongo/options" ) -var skippedTests = map[string]string{ - // GODRIVER-3175: Support will be added with GODRIVER-2129. - "must raise an error when the hostname canonicalization is invalid": "Support will be added with GODRIVER-2129.", -} - type credential struct { Username string Password *string @@ -53,53 +48,53 @@ func runTestsInFile(t *testing.T, dirname string, filename string) { var container testContainer require.NoError(t, json.Unmarshal(content, &container)) - for _, testCase := range container.Tests { - t.Run(filename, func(t *testing.T) { - runTest(t, testCase) - }) - } + t.Run(filename, func(t *testing.T) { + for _, testCase := range container.Tests { + testCase := testCase // Capture range variable. + + t.Run(testCase.Description, func(t *testing.T) { + spectest.CheckSkip(t) + + runTest(t, testCase) + }) + } + }) } func runTest(t *testing.T, test testCase) { - if skipReason, ok := skippedTests[test.Description]; ok { - t.Skipf("skipping due to known failure: %q", skipReason) - } - - t.Run(test.Description, func(t *testing.T) { - opts := options.Client().ApplyURI(test.URI) + opts := options.Client().ApplyURI(test.URI) - if test.Valid { - require.NoError(t, opts.Validate()) - } else { - require.Error(t, opts.Validate()) + if test.Valid { + require.NoError(t, opts.Validate()) + } else { + require.Error(t, opts.Validate()) - return - } + return + } - if test.Credential == nil { - require.Nil(t, opts.Auth) - return - } - require.NotNil(t, opts.Auth) - require.Equal(t, test.Credential.Username, opts.Auth.Username) - - if test.Credential.Password == nil { - require.False(t, opts.Auth.PasswordSet) - } else { - require.True(t, opts.Auth.PasswordSet) - require.Equal(t, *test.Credential.Password, opts.Auth.Password) - } + if test.Credential == nil { + require.Nil(t, opts.Auth) + return + } + require.NotNil(t, opts.Auth) + require.Equal(t, test.Credential.Username, opts.Auth.Username) + + if test.Credential.Password == nil { + require.False(t, opts.Auth.PasswordSet) + } else { + require.True(t, opts.Auth.PasswordSet) + require.Equal(t, *test.Credential.Password, opts.Auth.Password) + } - require.Equal(t, test.Credential.Source, opts.Auth.AuthSource) + require.Equal(t, test.Credential.Source, opts.Auth.AuthSource) - require.Equal(t, test.Credential.Mechanism, opts.Auth.AuthMechanism) + require.Equal(t, test.Credential.Mechanism, opts.Auth.AuthMechanism) - if len(test.Credential.MechProps) > 0 { - require.Equal(t, mapInterfaceToString(test.Credential.MechProps), opts.Auth.AuthMechanismProperties) - } else { - require.Equal(t, 0, len(opts.Auth.AuthMechanismProperties)) - } - }) + if len(test.Credential.MechProps) > 0 { + require.Equal(t, mapInterfaceToString(test.Credential.MechProps), opts.Auth.AuthMechanismProperties) + } else { + require.Equal(t, 0, len(opts.Auth.AuthMechanismProperties)) + } } // Convert each interface{} value in the map to a string. diff --git a/x/mongo/driver/connstring/connstring_spec_test.go b/x/mongo/driver/connstring/connstring_spec_test.go index 26c4f53450..037e3ac94a 100644 --- a/x/mongo/driver/connstring/connstring_spec_test.go +++ b/x/mongo/driver/connstring/connstring_spec_test.go @@ -89,18 +89,17 @@ func runTestsInFile(t *testing.T, dirname string, filename string, warningsError var container testContainer require.NoError(t, json.Unmarshal(content, &container)) - // Remove ".json" from filename. - filename = filename[:len(filename)-5] + t.Run(filename, func(t *testing.T) { + for _, testCase := range container.Tests { + testCase := testCase // Capture range variable. - for _, testCase := range container.Tests { - runTest(t, filename, testCase, warningsError) - } -} + t.Run(testCase.Description, func(t *testing.T) { + spectest.CheckSkip(t) -var skipDescriptions = map[string]struct{}{ - "Valid options specific to single-threaded drivers are parsed correctly": {}, - // GODRIVER-2348: the wtimeoutMS write concern option is not supported. - "Valid read and write concern are parsed correctly": {}, + runTest(t, testCase, warningsError) + }) + } + }) } var skipKeywords = []string{ @@ -113,64 +112,59 @@ var skipKeywords = []string{ "wTimeoutMS", } -func runTest(t *testing.T, filename string, test testCase, warningsError bool) { - t.Run(filename+"/"+test.Description, func(t *testing.T) { - if _, skip := skipDescriptions[test.Description]; skip { - t.Skip() - } - for _, keyword := range skipKeywords { - if strings.Contains(test.Description, keyword) { - t.Skipf("skipping because keyword %s", keyword) - } +func runTest(t *testing.T, test testCase, warningsError bool) { + for _, keyword := range skipKeywords { + if strings.Contains(test.Description, keyword) { + t.Skipf("skipping because keyword %s", keyword) } + } - cs, err := connstring.ParseAndValidate(test.URI) - // Since we don't have warnings in Go, we return warnings as errors. - // - // This is a bit unfortunate, but since we do raise warnings as errors with the newer - // URI options, but don't with some of the older things, we do a switch on the filename - // here. We are trying to not break existing user applications that have unrecognized - // options. - if test.Valid && !(test.Warning && warningsError) { - require.NoError(t, err) - } else { - require.Error(t, err) - return - } + cs, err := connstring.ParseAndValidate(test.URI) + // Since we don't have warnings in Go, we return warnings as errors. + // + // This is a bit unfortunate, but since we do raise warnings as errors with the newer + // URI options, but don't with some of the older things, we do a switch on the filename + // here. We are trying to not break existing user applications that have unrecognized + // options. + if test.Valid && !(test.Warning && warningsError) { + require.NoError(t, err) + } else { + require.Error(t, err) + return + } - require.Equal(t, test.URI, cs.Original) + require.Equal(t, test.URI, cs.Original) - if test.Hosts != nil { - require.Equal(t, hostsToStrings(test.Hosts), cs.Hosts) - } + if test.Hosts != nil { + require.Equal(t, hostsToStrings(test.Hosts), cs.Hosts) + } - if test.Auth != nil { - require.Equal(t, test.Auth.Username, cs.Username) + if test.Auth != nil { + require.Equal(t, test.Auth.Username, cs.Username) - if test.Auth.Password == nil { - require.False(t, cs.PasswordSet) - } else { - require.True(t, cs.PasswordSet) - require.Equal(t, *test.Auth.Password, cs.Password) - } + if test.Auth.Password == nil { + require.False(t, cs.PasswordSet) + } else { + require.True(t, cs.PasswordSet) + require.Equal(t, *test.Auth.Password, cs.Password) + } - if test.Auth.DB != cs.Database { - require.Equal(t, test.Auth.DB, cs.AuthSource) - } else { - require.Equal(t, test.Auth.DB, cs.Database) - } + if test.Auth.DB != cs.Database { + require.Equal(t, test.Auth.DB, cs.AuthSource) + } else { + require.Equal(t, test.Auth.DB, cs.Database) } + } - // Check that all options are present. - verifyConnStringOptions(t, cs, test.Options) + // Check that all options are present. + verifyConnStringOptions(t, cs, test.Options) - // Check that non-present options are unset. This will be redundant with the above checks - // for options that are present. - var ok bool + // Check that non-present options are unset. This will be redundant with the above checks + // for options that are present. + var ok bool - _, ok = test.Options["maxpoolsize"] - require.Equal(t, ok, cs.MaxPoolSizeSet) - }) + _, ok = test.Options["maxpoolsize"] + require.Equal(t, ok, cs.MaxPoolSizeSet) } // Test case for all connection string spec tests. diff --git a/x/mongo/driver/topology/sdam_spec_test.go b/x/mongo/driver/topology/sdam_spec_test.go index 9186aae157..6c190dda13 100644 --- a/x/mongo/driver/topology/sdam_spec_test.go +++ b/x/mongo/driver/topology/sdam_spec_test.go @@ -462,11 +462,7 @@ func runTest(t *testing.T, directory string, filename string) { content, err := ioutil.ReadFile(filepath) assert.Nil(t, err, "ReadFile error: %v", err) - // Remove ".json" from filename. - filename = filename[:len(filename)-5] - testName := directory + "/" + filename + ":" - - t.Run(testName, func(t *testing.T) { + t.Run(directory+"/"+filename, func(t *testing.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/server_rtt_test.go b/x/mongo/driver/topology/server_rtt_test.go index e13fe8f2c1..1152653501 100644 --- a/x/mongo/driver/topology/server_rtt_test.go +++ b/x/mongo/driver/topology/server_rtt_test.go @@ -35,10 +35,7 @@ func TestServerSelectionRTTSpec(t *testing.T) { content, err := ioutil.ReadFile(filepath) assert.Nil(t, err, "ReadFile error for %s: %v", filepath, err) - // Remove ".json" from filename. - testName := filename[:len(filename)-5] - - t.Run(testName, func(t *testing.T) { + t.Run(filename, func(t *testing.T) { var test testCase err = json.Unmarshal(content, &test) assert.Nil(t, err, "Unmarshal error: %v", err)