From 06a2e2ce45921dfe898eefaf1fbdd461c212d512 Mon Sep 17 00:00:00 2001 From: Bailey Pearson Date: Tue, 19 Nov 2024 13:56:43 -0700 Subject: [PATCH] fix(NODE-6469): pool is cleared before connection checkin on error (#4296) --- src/cmap/connect.ts | 19 +- src/cmap/connection_pool.ts | 4 +- ...ection_monitoring_and_pooling.spec.test.ts | 3 - .../connection_monitoring_and_pooling.test.ts | 7 - .../connection-logging.json | 228 -------------- .../pool-create-min-size-error.json | 8 +- .../pool-create-min-size-error.yml | 4 +- .../unified/pool-clear-application-error.json | 149 +++++++++ .../unified/pool-clear-application-error.yml | 88 ++++++ .../unified/pool-clear-checkout-error.json | 296 ++++++++++++++++++ .../unified/pool-clear-checkout-error.yml | 176 +++++++++++ .../pool-clear-min-pool-size-error.json | 230 ++++++++++++++ .../pool-clear-min-pool-size-error.yml | 144 +++++++++ .../unified/pool-cleared-error.yml | 2 +- 14 files changed, 1109 insertions(+), 249 deletions(-) delete mode 100644 test/integration/connection-monitoring-and-pooling/unified-cmap-node-specs/connection-logging.json create mode 100644 test/spec/server-discovery-and-monitoring/unified/pool-clear-application-error.json create mode 100644 test/spec/server-discovery-and-monitoring/unified/pool-clear-application-error.yml create mode 100644 test/spec/server-discovery-and-monitoring/unified/pool-clear-checkout-error.json create mode 100644 test/spec/server-discovery-and-monitoring/unified/pool-clear-checkout-error.yml create mode 100644 test/spec/server-discovery-and-monitoring/unified/pool-clear-min-pool-size-error.json create mode 100644 test/spec/server-discovery-and-monitoring/unified/pool-clear-min-pool-size-error.yml diff --git a/src/cmap/connect.ts b/src/cmap/connect.ts index f15d1096b49..938b524e082 100644 --- a/src/cmap/connect.ts +++ b/src/cmap/connect.ts @@ -113,7 +113,8 @@ export async function performInitialHandshake( } const start = new Date().getTime(); - const response = await conn.command(ns('admin.$cmd'), handshakeDoc, handshakeOptions); + + const response = await executeHandshake(handshakeDoc, handshakeOptions); if (!('isWritablePrimary' in response)) { // Provide hello-style response document. @@ -175,6 +176,22 @@ export async function performInitialHandshake( // Connection establishment is socket creation (tcp handshake, tls handshake, MongoDB handshake (saslStart, saslContinue)) // Once connection is established, command logging can log events (if enabled) conn.established = true; + + async function executeHandshake(handshakeDoc: Document, handshakeOptions: CommandOptions) { + try { + const handshakeResponse = await conn.command( + ns('admin.$cmd'), + handshakeDoc, + handshakeOptions + ); + return handshakeResponse; + } catch (error) { + if (error instanceof MongoError) { + error.addErrorLabel(MongoErrorLabel.HandshakeError); + } + throw error; + } + } } /** diff --git a/src/cmap/connection_pool.ts b/src/cmap/connection_pool.ts index 83449a91ef9..ff4a727be12 100644 --- a/src/cmap/connection_pool.ts +++ b/src/cmap/connection_pool.ts @@ -685,6 +685,7 @@ export class ConnectionPool extends TypedEventEmitter { }, error => { this[kPending]--; + this[kServer].handleError(error); this.emitAndLog( ConnectionPool.CONNECTION_CLOSED, new ConnectionClosedEvent( @@ -719,9 +720,6 @@ export class ConnectionPool extends TypedEventEmitter { // connection permits because that potentially delays the availability of // the connection to a checkout request this.createConnection((err, connection) => { - if (err) { - this[kServer].handleError(err); - } if (!err && connection) { this[kConnections].push(connection); process.nextTick(() => this.processWaitQueue()); diff --git a/test/integration/connection-monitoring-and-pooling/connection_monitoring_and_pooling.spec.test.ts b/test/integration/connection-monitoring-and-pooling/connection_monitoring_and_pooling.spec.test.ts index d869d05746c..3b7cdfeae97 100644 --- a/test/integration/connection-monitoring-and-pooling/connection_monitoring_and_pooling.spec.test.ts +++ b/test/integration/connection-monitoring-and-pooling/connection_monitoring_and_pooling.spec.test.ts @@ -69,9 +69,6 @@ describe('Connection Monitoring and Pooling Spec Tests (Integration) - logging', ) { return 'not applicable: waitQueueSize not supported'; } - if (test.description === 'Connection checkout fails due to error establishing connection') { - return 'TODO(NODE-5230): unskip this once event ordering issue is resolved'; - } return false; }); }); diff --git a/test/integration/connection-monitoring-and-pooling/connection_monitoring_and_pooling.test.ts b/test/integration/connection-monitoring-and-pooling/connection_monitoring_and_pooling.test.ts index 6e57d5a8267..524f505e005 100644 --- a/test/integration/connection-monitoring-and-pooling/connection_monitoring_and_pooling.test.ts +++ b/test/integration/connection-monitoring-and-pooling/connection_monitoring_and_pooling.test.ts @@ -1,6 +1,5 @@ import { loadSpecTests } from '../../spec'; import { type CmapTest, runCmapTestSuite } from '../../tools/cmap_spec_runner'; -import { runUnifiedSuite } from '../../tools/unified-spec-runner/runner'; describe('Connection Monitoring and Pooling (Node Driver)', function () { const cmapTests: CmapTest[] = loadSpecTests( @@ -17,10 +16,4 @@ describe('Connection Monitoring and Pooling (Node Driver)', function () { } ] }); - - // TODO(NODE-5230): Remove this once the actual unified tests (test/spec/connection-monitoring-and-pooling/logging) are passing - const unifiedTests = loadSpecTests( - '../integration/connection-monitoring-and-pooling/unified-cmap-node-specs' - ); - runUnifiedSuite(unifiedTests); }); diff --git a/test/integration/connection-monitoring-and-pooling/unified-cmap-node-specs/connection-logging.json b/test/integration/connection-monitoring-and-pooling/unified-cmap-node-specs/connection-logging.json deleted file mode 100644 index 26900e37458..00000000000 --- a/test/integration/connection-monitoring-and-pooling/unified-cmap-node-specs/connection-logging.json +++ /dev/null @@ -1,228 +0,0 @@ -{ - "description": "connection-logging", - "schemaVersion": "1.13", - "runOnRequirements": [ - { - "topologies": [ - "single" - ] - } - ], - "createEntities": [ - { - "client": { - "id": "failPointClient" - } - } - ], - "tests": [ - { - "description": "Connection checkout fails due to error establishing connection", - "runOnRequirements": [ - { - "auth": true, - "minServerVersion": "4.0" - } - ], - "operations": [ - { - "name": "createEntities", - "object": "testRunner", - "arguments": { - "entities": [ - { - "client": { - "id": "client", - "uriOptions": { - "retryReads": false, - "appname": "clientAppName", - "heartbeatFrequencyMS": 10000 - }, - "observeLogMessages": { - "connection": "debug" - } - } - } - ] - } - }, - { - "name": "failPoint", - "object": "testRunner", - "arguments": { - "client": "failPointClient", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "saslContinue" - ], - "closeConnection": true, - "appName": "clientAppName" - } - } - } - }, - { - "name": "listDatabases", - "object": "client", - "arguments": { - "filter": {} - }, - "expectError": { - "isClientError": true - } - } - ], - "expectLogMessages": [ - { - "client": "client", - "messages": [ - { - "level": "debug", - "component": "connection", - "data": { - "message": "Connection pool created", - "serverHost": { - "$$type": "string" - }, - "serverPort": { - "$$type": [ - "int", - "long" - ] - } - } - }, - { - "level": "debug", - "component": "connection", - "data": { - "message": "Connection pool ready", - "serverHost": { - "$$type": "string" - }, - "serverPort": { - "$$type": [ - "int", - "long" - ] - } - } - }, - { - "level": "debug", - "component": "connection", - "data": { - "message": "Connection checkout started", - "serverHost": { - "$$type": "string" - }, - "serverPort": { - "$$type": [ - "int", - "long" - ] - } - } - }, - { - "level": "debug", - "component": "connection", - "data": { - "message": "Connection created", - "driverConnectionId": { - "$$type": [ - "int", - "long" - ] - }, - "serverHost": { - "$$type": "string" - }, - "serverPort": { - "$$type": [ - "int", - "long" - ] - } - } - }, - { - "level": "debug", - "component": "connection", - "data": { - "message": "Connection closed", - "driverConnectionId": { - "$$type": [ - "int", - "long" - ] - }, - "serverHost": { - "$$type": "string" - }, - "serverPort": { - "$$type": [ - "int", - "long" - ] - }, - "reason": "An error occurred while using the connection", - "error": { - "$$exists": true - } - } - }, - { - "level": "debug", - "component": "connection", - "data": { - "message": "Connection checkout failed", - "serverHost": { - "$$type": "string" - }, - "serverPort": { - "$$type": [ - "int", - "long" - ] - }, - "durationMS": { - "$$type": [ - "double", - "int", - "long" - ] - }, - "reason": "An error occurred while trying to establish a new connection", - "error": { - "$$exists": true - } - } - }, - { - "level": "debug", - "component": "connection", - "data": { - "message": "Connection pool cleared", - "serverHost": { - "$$type": "string" - }, - "serverPort": { - "$$type": [ - "int", - "long" - ] - } - } - } - ] - } - ] - } - ] -} diff --git a/test/spec/connection-monitoring-and-pooling/cmap-format/pool-create-min-size-error.json b/test/spec/connection-monitoring-and-pooling/cmap-format/pool-create-min-size-error.json index 1c744b850c3..509b2a2356c 100644 --- a/test/spec/connection-monitoring-and-pooling/cmap-format/pool-create-min-size-error.json +++ b/test/spec/connection-monitoring-and-pooling/cmap-format/pool-create-min-size-error.json @@ -49,15 +49,15 @@ "type": "ConnectionCreated", "address": 42 }, + { + "type": "ConnectionPoolCleared", + "address": 42 + }, { "type": "ConnectionClosed", "address": 42, "connectionId": 42, "reason": "error" - }, - { - "type": "ConnectionPoolCleared", - "address": 42 } ], "ignore": [ diff --git a/test/spec/connection-monitoring-and-pooling/cmap-format/pool-create-min-size-error.yml b/test/spec/connection-monitoring-and-pooling/cmap-format/pool-create-min-size-error.yml index dd5890b1d91..f43c4ee154f 100644 --- a/test/spec/connection-monitoring-and-pooling/cmap-format/pool-create-min-size-error.yml +++ b/test/spec/connection-monitoring-and-pooling/cmap-format/pool-create-min-size-error.yml @@ -30,11 +30,11 @@ events: address: 42 - type: ConnectionCreated address: 42 + - type: ConnectionPoolCleared + address: 42 - type: ConnectionClosed address: 42 connectionId: 42 reason: error - - type: ConnectionPoolCleared - address: 42 ignore: - ConnectionPoolCreated diff --git a/test/spec/server-discovery-and-monitoring/unified/pool-clear-application-error.json b/test/spec/server-discovery-and-monitoring/unified/pool-clear-application-error.json new file mode 100644 index 00000000000..b8fd95fee39 --- /dev/null +++ b/test/spec/server-discovery-and-monitoring/unified/pool-clear-application-error.json @@ -0,0 +1,149 @@ +{ + "description": "pool-clear-application-error", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4", + "serverless": "forbid", + "topologies": [ + "single", + "replicaset", + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "initialData": [ + { + "collectionName": "find-network-error", + "databaseName": "sdam-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ], + "tests": [ + { + "description": "Pool is cleared before application connection is checked into the pool", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "closeConnection": true, + "appName": "findNetworkErrorTest" + } + } + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "poolClearedEvent", + "connectionCheckedInEvent" + ], + "uriOptions": { + "retryWrites": false, + "retryReads": false, + "appname": "findNetworkErrorTest" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "sdam-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "find-network-error" + } + } + ] + } + }, + { + "name": "find", + "object": "collection", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectError": { + "isError": true + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "connectionCheckedInEvent": {} + }, + "count": 1 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "cmap", + "events": [ + { + "poolClearedEvent": {} + }, + { + "connectionCheckedInEvent": {} + } + ] + } + ] + } + ] +} diff --git a/test/spec/server-discovery-and-monitoring/unified/pool-clear-application-error.yml b/test/spec/server-discovery-and-monitoring/unified/pool-clear-application-error.yml new file mode 100644 index 00000000000..43e425711e2 --- /dev/null +++ b/test/spec/server-discovery-and-monitoring/unified/pool-clear-application-error.yml @@ -0,0 +1,88 @@ +--- +description: pool-clear-application-error + +schemaVersion: "1.4" + +runOnRequirements: + # failCommand appName requirements + - minServerVersion: "4.4" + serverless: forbid + topologies: [ single, replicaset, sharded ] + +createEntities: + - client: + id: &setupClient setupClient + useMultipleMongoses: false + +initialData: &initialData + - collectionName: &collectionName find-network-error + databaseName: &databaseName sdam-tests + documents: + - _id: 1 + - _id: 2 + +tests: + - description: Pool is cleared before application connection is checked into the pool + operations: + - name: failPoint + object: testRunner + arguments: + client: *setupClient + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + closeConnection: true + appName: findNetworkErrorTest + - name: createEntities + object: testRunner + arguments: + entities: + - client: + id: &client client + useMultipleMongoses: false + observeEvents: + - poolClearedEvent + - connectionCheckedInEvent + uriOptions: + retryWrites: false + retryReads: false + appname: findNetworkErrorTest + - database: + id: &database database + client: *client + databaseName: *databaseName + - collection: + id: &collection collection + database: *database + collectionName: *collectionName + - name: find + object: *collection + arguments: + filter: + _id: 1 + expectError: + isError: true + - name: waitForEvent + object: testRunner + arguments: + client: *client + event: + poolClearedEvent: {} + count: 1 + - name: waitForEvent + object: testRunner + arguments: + client: *client + event: + connectionCheckedInEvent: {} + count: 1 + expectEvents: + - client: *client + eventType: cmap + events: + - poolClearedEvent: {} + - connectionCheckedInEvent: {} diff --git a/test/spec/server-discovery-and-monitoring/unified/pool-clear-checkout-error.json b/test/spec/server-discovery-and-monitoring/unified/pool-clear-checkout-error.json new file mode 100644 index 00000000000..126ee545333 --- /dev/null +++ b/test/spec/server-discovery-and-monitoring/unified/pool-clear-checkout-error.json @@ -0,0 +1,296 @@ +{ + "description": "pool-clear-on-error-checkout", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4", + "serverless": "forbid", + "topologies": [ + "single", + "replicaset", + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "tests": [ + { + "description": "Pool is cleared before connection is closed (authentication error)", + "runOnRequirements": [ + { + "auth": true + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "saslContinue" + ], + "appName": "authErrorTest", + "errorCode": 18 + } + } + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "connectionCheckOutStartedEvent", + "poolClearedEvent", + "connectionClosedEvent" + ], + "uriOptions": { + "retryWrites": false, + "appname": "authErrorTest" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "foo" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "bar" + } + } + ] + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + "expectError": { + "isError": true + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "connectionClosedEvent": {} + }, + "count": 1 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "cmap", + "events": [ + { + "connectionCheckOutStartedEvent": {} + }, + { + "poolClearedEvent": {} + }, + { + "connectionClosedEvent": {} + } + ] + } + ] + }, + { + "description": "Pool is cleared before connection is closed (handshake error)", + "runOnRequirements": [ + { + "topologies": [ + "single" + ] + } + ], + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "connectionCheckOutStartedEvent", + "poolClearedEvent", + "connectionClosedEvent", + "topologyDescriptionChangedEvent" + ], + "uriOptions": { + "retryWrites": false, + "appname": "authErrorTest", + "minPoolSize": 0, + "serverMonitoringMode": "poll", + "heartbeatFrequencyMS": 1000000 + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "foo" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "bar" + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "Unknown" + }, + "newDescription": { + "type": "Single" + } + } + }, + "count": 1 + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "hello", + "isMaster" + ], + "appName": "authErrorTest", + "closeConnection": true + } + } + } + }, + { + "name": "insertMany", + "object": "collection", + "arguments": { + "documents": [ + { + "_id": 3 + }, + { + "_id": 4 + } + ] + }, + "expectError": { + "isError": true + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "connectionClosedEvent": {} + }, + "count": 1 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "cmap", + "events": [ + { + "connectionCheckOutStartedEvent": {} + }, + { + "poolClearedEvent": {} + }, + { + "connectionClosedEvent": {} + } + ] + } + ] + } + ] +} diff --git a/test/spec/server-discovery-and-monitoring/unified/pool-clear-checkout-error.yml b/test/spec/server-discovery-and-monitoring/unified/pool-clear-checkout-error.yml new file mode 100644 index 00000000000..8df74b6a6f5 --- /dev/null +++ b/test/spec/server-discovery-and-monitoring/unified/pool-clear-checkout-error.yml @@ -0,0 +1,176 @@ +--- +description: pool-clear-on-error-checkout + +schemaVersion: "1.4" + +runOnRequirements: + # failCommand appName requirements + - minServerVersion: "4.4" + serverless: forbid + topologies: [ single, replicaset, sharded ] + +createEntities: + - client: + id: &setupClient setupClient + useMultipleMongoses: false + +tests: + - description: Pool is cleared before connection is closed (authentication error) + runOnRequirements: + - auth: true + + operations: + - name: failPoint + object: testRunner + arguments: + client: *setupClient + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - saslContinue + appName: authErrorTest + errorCode: 18 + - name: createEntities + object: testRunner + arguments: + entities: + - client: + id: &client client + useMultipleMongoses: false + observeEvents: + - connectionCheckOutStartedEvent + - poolClearedEvent + - connectionClosedEvent + uriOptions: + retryWrites: false + appname: authErrorTest + - database: + id: &database database + client: *client + databaseName: foo + - collection: + id: &collection collection + database: *database + collectionName: bar + - name: insertMany + object: *collection + arguments: + documents: + - _id: 3 + - _id: 4 + expectError: + isError: true + - name: waitForEvent + object: testRunner + arguments: + client: *client + event: + poolClearedEvent: {} + count: 1 + - name: waitForEvent + object: testRunner + arguments: + client: *client + event: + connectionClosedEvent: {} + count: 1 + expectEvents: + - client: *client + eventType: cmap + events: + - connectionCheckOutStartedEvent: {} + - poolClearedEvent: {} + - connectionClosedEvent: {} + + - description: Pool is cleared before connection is closed (handshake error) + runOnRequirements: + - topologies: [ single ] + operations: + - name: createEntities + object: testRunner + arguments: + entities: + - client: + id: &client client + useMultipleMongoses: false + observeEvents: + - connectionCheckOutStartedEvent + - poolClearedEvent + - connectionClosedEvent + - topologyDescriptionChangedEvent + uriOptions: + retryWrites: false + appname: authErrorTest + minPoolSize: 0 + # ensure that once we've connected to the server, the failCommand won't + # be triggered by monitors and will only be triggered by handshakes + serverMonitoringMode: poll + heartbeatFrequencyMS: 1000000 + - database: + id: &database database + client: *client + databaseName: foo + - collection: + id: &collection collection + database: *database + collectionName: bar + - name: waitForEvent + object: testRunner + arguments: + client: *client + event: + topologyDescriptionChangedEvent: + previousDescription: + type: "Unknown" + newDescription: + type: "Single" + count: 1 + + - name: failPoint + object: testRunner + arguments: + client: *setupClient + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - hello + - isMaster + appName: authErrorTest + closeConnection: true + + - name: insertMany + object: *collection + arguments: + documents: + - _id: 3 + - _id: 4 + expectError: + isError: true + - name: waitForEvent + object: testRunner + arguments: + client: *client + event: + poolClearedEvent: {} + count: 1 + - name: waitForEvent + object: testRunner + arguments: + client: *client + event: + connectionClosedEvent: {} + count: 1 + expectEvents: + - client: *client + eventType: cmap + events: + - connectionCheckOutStartedEvent: {} + - poolClearedEvent: {} + - connectionClosedEvent: {} + diff --git a/test/spec/server-discovery-and-monitoring/unified/pool-clear-min-pool-size-error.json b/test/spec/server-discovery-and-monitoring/unified/pool-clear-min-pool-size-error.json new file mode 100644 index 00000000000..11c6be5bc16 --- /dev/null +++ b/test/spec/server-discovery-and-monitoring/unified/pool-clear-min-pool-size-error.json @@ -0,0 +1,230 @@ +{ + "description": "pool-cleared-on-min-pool-size-population-error", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "4.4", + "serverless": "forbid", + "topologies": [ + "single" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "setupClient", + "useMultipleMongoses": false + } + } + ], + "tests": [ + { + "description": "Pool is cleared on authentication error during minPoolSize population", + "runOnRequirements": [ + { + "auth": true + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "saslContinue" + ], + "appName": "authErrorTest", + "errorCode": 18 + } + } + } + }, + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeEvents": [ + "connectionCreatedEvent", + "poolClearedEvent", + "connectionClosedEvent" + ], + "uriOptions": { + "appname": "authErrorTest", + "minPoolSize": 1 + } + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "connectionClosedEvent": {} + }, + "count": 1 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "cmap", + "events": [ + { + "connectionCreatedEvent": {} + }, + { + "poolClearedEvent": {} + }, + { + "connectionClosedEvent": {} + } + ] + } + ] + }, + { + "description": "Pool is cleared on handshake error during minPoolSize population", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeEvents": [ + "topologyDescriptionChangedEvent", + "connectionCreatedEvent", + "poolClearedEvent", + "connectionClosedEvent", + "connectionReadyEvent" + ], + "uriOptions": { + "appname": "authErrorTest", + "minPoolSize": 5, + "maxConnecting": 1, + "serverMonitoringMode": "poll", + "heartbeatFrequencyMS": 1000000 + } + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "Unknown" + }, + "newDescription": { + "type": "Single" + } + } + }, + "count": 1 + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "setupClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "hello", + "isMaster" + ], + "appName": "authErrorTest", + "closeConnection": true + } + } + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "poolClearedEvent": {} + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "connectionClosedEvent": {} + }, + "count": 1 + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "cmap", + "events": [ + { + "connectionCreatedEvent": {} + }, + { + "connectionReadyEvent": {} + }, + { + "connectionCreatedEvent": {} + }, + { + "poolClearedEvent": {} + }, + { + "connectionClosedEvent": {} + } + ] + } + ] + } + ] +} diff --git a/test/spec/server-discovery-and-monitoring/unified/pool-clear-min-pool-size-error.yml b/test/spec/server-discovery-and-monitoring/unified/pool-clear-min-pool-size-error.yml new file mode 100644 index 00000000000..7e7ef0c590b --- /dev/null +++ b/test/spec/server-discovery-and-monitoring/unified/pool-clear-min-pool-size-error.yml @@ -0,0 +1,144 @@ +--- +description: pool-cleared-on-min-pool-size-population-error + +schemaVersion: "1.4" + +runOnRequirements: + # failCommand appName requirements + - minServerVersion: "4.4" + serverless: forbid + topologies: [ single ] + +createEntities: + - client: + id: &setupClient setupClient + useMultipleMongoses: false + +tests: + - description: Pool is cleared on authentication error during minPoolSize population + runOnRequirements: + # failCommand appName requirements + - auth: true + operations: + - name: failPoint + object: testRunner + arguments: + client: *setupClient + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - saslContinue + appName: authErrorTest + errorCode: 18 + - name: createEntities + object: testRunner + arguments: + entities: + - client: + id: &client client + observeEvents: + - connectionCreatedEvent + - poolClearedEvent + - connectionClosedEvent + uriOptions: + appname: authErrorTest + minPoolSize: 1 + - name: waitForEvent + object: testRunner + arguments: + client: *client + event: + poolClearedEvent: {} + count: 1 + - name: waitForEvent + object: testRunner + arguments: + client: *client + event: + connectionClosedEvent: {} + count: 1 + expectEvents: + - client: *client + eventType: cmap + events: + - connectionCreatedEvent: {} + - poolClearedEvent: {} + - connectionClosedEvent: {} + + - description: Pool is cleared on handshake error during minPoolSize population + operations: + - name: createEntities + object: testRunner + arguments: + entities: + - client: + id: &client client + observeEvents: + - topologyDescriptionChangedEvent + - connectionCreatedEvent + - poolClearedEvent + - connectionClosedEvent + - connectionReadyEvent + uriOptions: + appname: authErrorTest + minPoolSize: 5 + maxConnecting: 1 + # ensure that once we've connected to the server, the failCommand won't + # be triggered by monitors and will only be triggered by handshakes + serverMonitoringMode: poll + heartbeatFrequencyMS: 1000000 + + - name: waitForEvent + object: testRunner + arguments: + client: *client + event: + topologyDescriptionChangedEvent: + previousDescription: + type: "Unknown" + newDescription: + type: "Single" + count: 1 + + - name: failPoint + object: testRunner + arguments: + client: *setupClient + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - hello + - isMaster + appName: authErrorTest + closeConnection: true + + - name: waitForEvent + object: testRunner + arguments: + client: *client + event: + poolClearedEvent: {} + count: 1 + - name: waitForEvent + object: testRunner + arguments: + client: *client + event: + connectionClosedEvent: {} + count: 1 + expectEvents: + - client: *client + eventType: cmap + events: + - connectionCreatedEvent: {} + - connectionReadyEvent: {} + - connectionCreatedEvent: {} + - poolClearedEvent: {} + - connectionClosedEvent: {} + diff --git a/test/spec/server-discovery-and-monitoring/unified/pool-cleared-error.yml b/test/spec/server-discovery-and-monitoring/unified/pool-cleared-error.yml index 7a98e2b324a..f3bad7959eb 100644 --- a/test/spec/server-discovery-and-monitoring/unified/pool-cleared-error.yml +++ b/test/spec/server-discovery-and-monitoring/unified/pool-cleared-error.yml @@ -200,7 +200,7 @@ tests: event: poolClearedEvent: {} count: 1 - # Perform an operation to ensure the node still useable. + # Perform an operation to ensure the node still usable. - name: insertOne object: *collection arguments: