diff --git a/test/integration/command-monitoring/.gitkeep b/test/integration/command-logging-and-monitoring/.gitkeep similarity index 100% rename from test/integration/command-monitoring/.gitkeep rename to test/integration/command-logging-and-monitoring/.gitkeep diff --git a/test/integration/command-monitoring/command_monitoring.spec.test.ts b/test/integration/command-logging-and-monitoring/command_monitoring.spec.test.ts similarity index 76% rename from test/integration/command-monitoring/command_monitoring.spec.test.ts rename to test/integration/command-logging-and-monitoring/command_monitoring.spec.test.ts index 1311b0d625..208e689966 100644 --- a/test/integration/command-monitoring/command_monitoring.spec.test.ts +++ b/test/integration/command-logging-and-monitoring/command_monitoring.spec.test.ts @@ -12,7 +12,9 @@ import { runUnifiedSuite } from '../../tools/unified-spec-runner/runner'; const SKIP = ['A successful unordered bulk write with an unacknowledged write concern']; describe('Command Monitoring Spec (unified)', () => { - runUnifiedSuite(loadSpecTests(path.join('command-monitoring', 'unified')), ({ description }) => - SKIP.includes(description) ? `TODO(NODE-4261): support skip reasons in unified tests` : false + runUnifiedSuite( + loadSpecTests(path.join('command-logging-and-monitoring', 'monitoring')), + ({ description }) => + SKIP.includes(description) ? `TODO(NODE-4261): support skip reasons in unified tests` : false ); }); diff --git a/test/integration/command-monitoring/command_monitoring.test.ts b/test/integration/command-logging-and-monitoring/command_monitoring.test.ts similarity index 99% rename from test/integration/command-monitoring/command_monitoring.test.ts rename to test/integration/command-logging-and-monitoring/command_monitoring.test.ts index 5eb1f7a98d..82c1637557 100644 --- a/test/integration/command-monitoring/command_monitoring.test.ts +++ b/test/integration/command-logging-and-monitoring/command_monitoring.test.ts @@ -366,14 +366,14 @@ describe('Command Monitoring', function () { { maxPoolSize: 1, monitorCommands: true } ); - const desiredEvents = ['getnonce']; + const desiredEvents = ['hello']; client.on('commandStarted', filterForCommands(desiredEvents, started)); client.on('commandSucceeded', filterForCommands(desiredEvents, succeeded)); client.on('commandFailed', filterForCommands(desiredEvents, failed)); return client .db(this.configuration.db) - .command({ getnonce: true }) + .command({ hello: 1, speculativeAuthenticate: { saslStart: 1 } }) .then(r => { expect(r).to.exist; expect(started).to.have.length(1); diff --git a/test/spec/command-logging-and-monitoring/README.rst b/test/spec/command-logging-and-monitoring/README.rst new file mode 100644 index 0000000000..e3687be676 --- /dev/null +++ b/test/spec/command-logging-and-monitoring/README.rst @@ -0,0 +1,60 @@ +.. role:: javascript(code) + :language: javascript + +============================== +Command Logging and Monitoring +============================== + +.. contents:: + +-------- + +Testing +======= + +Automated Tests +^^^^^^^^^^^^^^^ +There are tests in the `Unified Test Format <../../unified-test-format/unified-test-format.rst>`__ for both logging and +monitoring in `/logging <./logging>`_ and `/monitoring <./monitoring>`_, respectively. Drivers MUST run the logging +tests with their max document length setting (as described in the +`logging specification <../../logging/logging.rst#configurable-max-document-length>`__) set to a large value e.g. 10,000; +this is necessary in order for the driver to emit the full server reply (and to allow matching against that reply) on +certain MongoDB versions and topologies. + +Prose Tests +^^^^^^^^^^^ +Drivers MUST implement the following logging prose tests. These tests require the ability to capture log message data in a +structured form as described in the +`Unified Test Format specification <../../unified-test-format/unified-test-format.rst#expectedLogMessage>`__. + +Note: the following tests mention string "length"; this refers to length in terms of whatever unit the driver has chosen +to support for specifying max document length as discussed in the +`logging specification <../../logging/logging.rst#configurable-max-document-length>`__. + +*Test 1: Default truncation limit* + +1. Configure logging with a minimum severity level of "debug" for the "command" component. Do not explicitly configure the max document length. +2. Construct an array ``docs`` containing the document ``{"x" : "y"}`` repeated 100 times. +3. Insert ``docs`` to a collection via ``insertMany``. +4. Inspect the resulting "command started" log message and assert that the "command" value is a string of length 1000 + (length of trailing ellipsis). +5. Inspect the resulting "command succeeded" log message and assert that the "reply" value is a string of length <= 1000 + (length of trailing ellipsis). +6. Run ``find()`` on the collection where the document was inserted. +7. Inspect the resulting "command succeeded" log message and assert that the reply is a string of length 1000 + (length of trailing ellipsis). + +*Test 2: Explicitly configured truncation limit* + +1. Configure logging with a minimum severity level of "debug" for the "command" component. Set the max document length to 5. +2. Run the command ``{"hello": true}``. +3. Inspect the resulting "command started" log message and assert that the "command" value is a string of length 5 + (length of trailing ellipsis). +4. Inspect the resulting "command succeeded" log message and assert that the "reply" value is a string of length 5 + (length of trailing ellipsis). +5. If the driver attaches raw server responses to failures and can access these via log messages to assert on, run the command + ``{"notARealCommand": true}``. Inspect the resulting "command failed" log message and confirm that the server error is + a string of length 5 + (length of trailing ellipsis). + +*Test 3: Truncation with multi-byte codepoints* + +A specific test case is not provided here due to the allowed variations in truncation logic as well as varying extended JSON whitespace usage. +Drivers MUST write language-specific tests that confirm truncation of commands, replies, and (if applicable) server responses included in error +messages work as expected when the data being truncated includes multi-byte Unicode codepoints. +If the driver uses anything other than Unicode codepoints as the unit for max document length, there also MUST be tests confirming that cases +where the max length falls in the middle of a multi-byte codepoint are handled gracefully. diff --git a/test/spec/command-logging-and-monitoring/logging/command.json b/test/spec/command-logging-and-monitoring/logging/command.json new file mode 100644 index 0000000000..3d5c2570be --- /dev/null +++ b/test/spec/command-logging-and-monitoring/logging/command.json @@ -0,0 +1,213 @@ +{ + "description": "command-logging", + "schemaVersion": "1.13", + "createEntities": [ + { + "client": { + "id": "client", + "observeLogMessages": { + "command": "debug" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "logging-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "logging-tests-collection" + } + } + ], + "initialData": [ + { + "collectionName": "logging-tests-collection", + "databaseName": "logging-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ], + "tests": [ + { + "description": "A successful command", + "operations": [ + { + "name": "runCommand", + "object": "database", + "arguments": { + "command": { + "ping": 1 + }, + "commandName": "ping" + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-tests", + "commandName": "ping", + "command": { + "$$matchAsDocument": { + "$$matchAsRoot": { + "ping": 1, + "$db": "logging-tests" + } + } + }, + "requestId": { + "$$type": [ + "int", + "long" + ] + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command succeeded", + "commandName": "ping", + "reply": { + "$$type": "string" + }, + "requestId": { + "$$type": [ + "int", + "long" + ] + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + }, + "durationMS": { + "$$type": [ + "double", + "int", + "long" + ] + } + } + } + ] + } + ] + }, + { + "description": "A failed command", + "operations": [ + { + "name": "find", + "object": "collection", + "arguments": { + "filter": { + "$or": true + } + }, + "expectError": { + "isClientError": false + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-tests", + "commandName": "find", + "command": { + "$$type": "string" + }, + "requestId": { + "$$type": [ + "int", + "long" + ] + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command failed", + "commandName": "find", + "failure": { + "$$exists": true + }, + "requestId": { + "$$type": [ + "int", + "long" + ] + }, + "serverHost": { + "$$type": "string" + }, + "serverPort": { + "$$type": [ + "int", + "long" + ] + }, + "durationMS": { + "$$type": [ + "double", + "int", + "long" + ] + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/command-logging-and-monitoring/logging/command.yml b/test/spec/command-logging-and-monitoring/logging/command.yml new file mode 100644 index 0000000000..b21a4c6090 --- /dev/null +++ b/test/spec/command-logging-and-monitoring/logging/command.yml @@ -0,0 +1,94 @@ +description: "command-logging" + +schemaVersion: "1.13" + +createEntities: + - client: + id: &client client + observeLogMessages: + command: debug + - database: + id: &database database + client: *client + databaseName: &databaseName logging-tests + - collection: + id: &collection collection + database: *database + collectionName: &collectionName logging-tests-collection + +initialData: + - collectionName: *collectionName + databaseName: *databaseName + documents: + - { _id: 1, x: 11 } + +tests: + - description: "A successful command" + operations: + - name: runCommand + object: *database + arguments: + command: { ping: 1 } + commandName: &commandName ping + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: *commandName + command: + $$matchAsDocument: + $$matchAsRoot: + ping: 1 + $db: *databaseName + requestId: { $$type: [int, long] } + serverHost: { $$type: string } + serverPort: { $$type: [int, long] } + + - level: debug + component: command + data: + message: "Command succeeded" + commandName: *commandName + reply: { $$type: string } + requestId: { $$type: [int, long] } + serverHost: { $$type: string } + serverPort: { $$type: [int, long] } + durationMS: { $$type: [double, int, long] } + + - description: "A failed command" + operations: + - name: &commandName find + object: *collection + arguments: + filter: { $or: true } + expectError: + isClientError: false + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: *commandName + command: { $$type: string } + requestId: { $$type: [int, long] } + serverHost: { $$type: string } + serverPort: { $$type: [int, long] } + + - level: debug + component: command + data: + message: "Command failed" + commandName: *commandName + failure: { $$exists: true } + requestId: { $$type: [int, long] } + serverHost: { $$type: string } + serverPort: { $$type: [int, long] } + durationMS: { $$type: [double, int, long] } + diff --git a/test/spec/command-logging-and-monitoring/logging/driver-connection-id.json b/test/spec/command-logging-and-monitoring/logging/driver-connection-id.json new file mode 100644 index 0000000000..40db98d6fa --- /dev/null +++ b/test/spec/command-logging-and-monitoring/logging/driver-connection-id.json @@ -0,0 +1,146 @@ +{ + "description": "driver-connection-id", + "schemaVersion": "1.13", + "createEntities": [ + { + "client": { + "id": "client", + "observeLogMessages": { + "command": "debug" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "logging-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "logging-tests-collection" + } + } + ], + "initialData": [ + { + "collectionName": "logging-tests-collection", + "databaseName": "logging-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ], + "tests": [ + { + "description": "A successful command", + "operations": [ + { + "name": "runCommand", + "object": "database", + "arguments": { + "command": { + "ping": 1 + }, + "commandName": "ping" + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-tests", + "commandName": "ping", + "driverConnectionId": { + "$$type": [ + "int", + "long" + ] + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command succeeded", + "commandName": "ping", + "driverConnectionId": { + "$$type": [ + "int", + "long" + ] + } + } + } + ] + } + ] + }, + { + "description": "A failed command", + "operations": [ + { + "name": "find", + "object": "collection", + "arguments": { + "filter": { + "$or": true + } + }, + "expectError": { + "isClientError": false + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-tests", + "commandName": "find", + "driverConnectionId": { + "$$type": [ + "int", + "long" + ] + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command failed", + "commandName": "find", + "driverConnectionId": { + "$$type": [ + "int", + "long" + ] + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/command-logging-and-monitoring/logging/driver-connection-id.yml b/test/spec/command-logging-and-monitoring/logging/driver-connection-id.yml new file mode 100644 index 0000000000..f299edabaf --- /dev/null +++ b/test/spec/command-logging-and-monitoring/logging/driver-connection-id.yml @@ -0,0 +1,76 @@ +# This is a separate test so that drivers that do not implement CMAP can easily skip it. +description: "driver-connection-id" + +schemaVersion: "1.13" + +createEntities: + - client: + id: &client client + observeLogMessages: + command: debug + - database: + id: &database database + client: *client + databaseName: &databaseName logging-tests + - collection: + id: &collection collection + database: *database + collectionName: &collectionName logging-tests-collection + +initialData: + - collectionName: *collectionName + databaseName: *databaseName + documents: + - { _id: 1, x: 11 } + +tests: + - description: "A successful command" + operations: + - name: runCommand + object: *database + arguments: + command: { ping: 1 } + commandName: &commandName ping + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: *commandName + driverConnectionId: { $$type: [int, long] } + + - level: debug + component: command + data: + message: "Command succeeded" + commandName: *commandName + driverConnectionId: { $$type: [int, long] } + + - description: "A failed command" + operations: + - name: &commandName find + object: *collection + arguments: + filter: { $or: true } + expectError: + isClientError: false + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: *commandName + driverConnectionId: { $$type: [int, long] } + + - level: debug + component: command + data: + message: "Command failed" + commandName: *commandName + driverConnectionId: { $$type: [int, long] } diff --git a/test/spec/command-logging-and-monitoring/logging/no-handshake-messages.json b/test/spec/command-logging-and-monitoring/logging/no-handshake-messages.json new file mode 100644 index 0000000000..a61e208798 --- /dev/null +++ b/test/spec/command-logging-and-monitoring/logging/no-handshake-messages.json @@ -0,0 +1,94 @@ +{ + "description": "no-handshake-command-logs", + "schemaVersion": "1.13", + "tests": [ + { + "description": "Handshake commands should not generate log messages", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeLogMessages": { + "command": "debug" + }, + "observeEvents": [ + "connectionCreatedEvent", + "connectionReadyEvent" + ] + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "logging-tests" + } + } + ] + } + }, + { + "name": "runCommand", + "object": "database", + "arguments": { + "command": { + "ping": 1 + }, + "commandName": "ping" + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "connectionCreatedEvent": {} + }, + "count": 1 + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "connectionReadyEvent": {} + }, + "count": 1 + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-tests", + "commandName": "ping" + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command succeeded", + "commandName": "ping" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/command-logging-and-monitoring/logging/no-handshake-messages.yml b/test/spec/command-logging-and-monitoring/logging/no-handshake-messages.yml new file mode 100644 index 0000000000..bb7dd18e09 --- /dev/null +++ b/test/spec/command-logging-and-monitoring/logging/no-handshake-messages.yml @@ -0,0 +1,58 @@ +description: "no-handshake-command-logs" + +schemaVersion: "1.13" + +tests: + - description: "Handshake commands should not generate log messages" + operations: + - name: createEntities + object: testRunner + arguments: + entities: + - client: + id: &client client + observeLogMessages: + command: debug + observeEvents: + - connectionCreatedEvent + - connectionReadyEvent + - database: + id: &database database + client: *client + databaseName: &databaseName logging-tests + - name: runCommand + object: *database + arguments: + command: { ping: 1 } + commandName: &commandName ping + - name: waitForEvent + object: testRunner + arguments: + client: *client + event: + connectionCreatedEvent: {} + count: 1 + - name: waitForEvent + object: testRunner + arguments: + client: *client + event: + connectionReadyEvent: {} + count: 1 + expectLogMessages: + # since the ping happens after the handshake, seeing events for only the ping + # implies the driver did not emit any log messages for the handshake. + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: *commandName + + - level: debug + component: command + data: + message: "Command succeeded" + commandName: *commandName diff --git a/test/spec/command-logging-and-monitoring/logging/no-heartbeat-messages.json b/test/spec/command-logging-and-monitoring/logging/no-heartbeat-messages.json new file mode 100644 index 0000000000..525be9171d --- /dev/null +++ b/test/spec/command-logging-and-monitoring/logging/no-heartbeat-messages.json @@ -0,0 +1,91 @@ +{ + "description": "no-heartbeat-command-logs", + "schemaVersion": "1.13", + "runOnRequirements": [ + { + "topologies": [ + "single", + "replicaset", + "sharded" + ] + } + ], + "tests": [ + { + "description": "Heartbeat commands should not generate log messages", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeLogMessages": { + "command": "debug" + }, + "observeEvents": [ + "serverDescriptionChangedEvent" + ] + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "logging-tests" + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": {} + }, + "count": 1 + } + }, + { + "name": "runCommand", + "object": "database", + "arguments": { + "command": { + "ping": 1 + }, + "commandName": "ping" + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-tests", + "commandName": "ping" + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command succeeded", + "commandName": "ping" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/command-logging-and-monitoring/logging/no-heartbeat-messages.yml b/test/spec/command-logging-and-monitoring/logging/no-heartbeat-messages.yml new file mode 100644 index 0000000000..7d35fbe003 --- /dev/null +++ b/test/spec/command-logging-and-monitoring/logging/no-heartbeat-messages.yml @@ -0,0 +1,58 @@ +description: "no-heartbeat-command-logs" + +schemaVersion: "1.13" + +# no heartbeats in load balanced mode. +runOnRequirements: + - topologies: + - single + - replicaset + - sharded + +tests: + - description: "Heartbeat commands should not generate log messages" + operations: + - name: createEntities + object: testRunner + arguments: + entities: + - client: + id: &client client + observeLogMessages: + command: debug + observeEvents: + - serverDescriptionChangedEvent + - database: + id: &database database + client: *client + databaseName: &databaseName logging-tests + - name: waitForEvent + object: testRunner + arguments: + client: *client + event: + # a server description change implies that a heartbeat has happened. + serverDescriptionChangedEvent: {} + count: 1 + - name: runCommand + object: *database + arguments: + command: { ping: 1 } + commandName: &commandName ping + expectLogMessages: + # since the ping happens after the heartbeat, seeing events for only the ping + # implies the driver did not emit a log message for the heartbeat. + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: *commandName + + - level: debug + component: command + data: + message: "Command succeeded" + commandName: *commandName diff --git a/test/spec/command-logging-and-monitoring/logging/operation-id.json b/test/spec/command-logging-and-monitoring/logging/operation-id.json new file mode 100644 index 0000000000..b1a3cec3d9 --- /dev/null +++ b/test/spec/command-logging-and-monitoring/logging/operation-id.json @@ -0,0 +1,198 @@ +{ + "description": "operation-id", + "schemaVersion": "1.13", + "createEntities": [ + { + "client": { + "id": "client", + "observeLogMessages": { + "command": "debug" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "logging-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "logging-tests-collection" + } + } + ], + "initialData": [ + { + "collectionName": "logging-tests-collection", + "databaseName": "logging-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ], + "tests": [ + { + "description": "Successful bulk write command log messages include operationIds", + "operations": [ + { + "name": "bulkWrite", + "object": "collection", + "arguments": { + "requests": [ + { + "insertOne": { + "document": { + "x": 1 + } + } + }, + { + "deleteOne": { + "filter": { + "x": 1 + } + } + } + ] + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-tests", + "commandName": "insert", + "operationId": { + "$$type": [ + "int", + "long" + ] + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command succeeded", + "commandName": "insert", + "operationId": { + "$$type": [ + "int", + "long" + ] + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-tests", + "commandName": "delete", + "operationId": { + "$$type": [ + "int", + "long" + ] + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command succeeded", + "commandName": "delete", + "operationId": { + "$$type": [ + "int", + "long" + ] + } + } + } + ] + } + ] + }, + { + "description": "Failed bulk write command log message includes operationId", + "operations": [ + { + "name": "bulkWrite", + "object": "collection", + "arguments": { + "requests": [ + { + "updateOne": { + "filter": { + "x": 1 + }, + "update": [ + { + "$invalidOperator": true + } + ] + } + } + ] + }, + "expectError": { + "isClientError": false + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-tests", + "commandName": "update", + "operationId": { + "$$type": [ + "int", + "long" + ] + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command failed", + "commandName": "update", + "operationId": { + "$$type": [ + "int", + "long" + ] + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/command-logging-and-monitoring/logging/operation-id.yml b/test/spec/command-logging-and-monitoring/logging/operation-id.yml new file mode 100644 index 0000000000..f763e03b14 --- /dev/null +++ b/test/spec/command-logging-and-monitoring/logging/operation-id.yml @@ -0,0 +1,99 @@ +# This test only applies to drivers that generate operationIds to enable users to link +# together bulk writes. +description: "operation-id" + +schemaVersion: "1.13" + +createEntities: + - client: + id: &client client + observeLogMessages: + command: debug + - database: + id: &database database + client: *client + databaseName: &databaseName logging-tests + - collection: + id: &collection collection + database: *database + collectionName: &collectionName logging-tests-collection + +initialData: + - collectionName: *collectionName + databaseName: *databaseName + documents: + - { _id: 1, x: 11 } + +tests: + - description: "Successful bulk write command log messages include operationIds" + operations: + - name: bulkWrite + object: *collection + arguments: + requests: + - insertOne: + document: { x: 1 } + - deleteOne: + filter: { x: 1 } + + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: insert + operationId: { $$type: [int, long] } + + - level: debug + component: command + data: + message: "Command succeeded" + commandName: insert + operationId: { $$type: [int, long] } + + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: delete + operationId: { $$type: [int, long] } + + - level: debug + component: command + data: + message: "Command succeeded" + commandName: delete + operationId: { $$type: [int, long] } + + - description: "Failed bulk write command log message includes operationId" + operations: + - name: bulkWrite + object: *collection + arguments: + requests: + - updateOne: + filter: { x: 1 } + update: [{ $invalidOperator: true }] + expectError: + isClientError: false + + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: update + operationId: { $$type: [int, long] } + - level: debug + component: command + data: + message: "Command failed" + commandName: update + operationId: { $$type: [int, long] } diff --git a/test/spec/command-logging-and-monitoring/logging/pre-42-server-connection-id.json b/test/spec/command-logging-and-monitoring/logging/pre-42-server-connection-id.json new file mode 100644 index 0000000000..d5ebd86590 --- /dev/null +++ b/test/spec/command-logging-and-monitoring/logging/pre-42-server-connection-id.json @@ -0,0 +1,119 @@ +{ + "description": "pre-42-server-connection-id", + "schemaVersion": "1.13", + "runOnRequirements": [ + { + "maxServerVersion": "4.0.99" + } + ], + "createEntities": [ + { + "client": { + "id": "client", + "observeLogMessages": { + "command": "debug" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "logging-server-connection-id-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "logging-tests-collection" + } + } + ], + "initialData": [ + { + "databaseName": "logging-server-connection-id-tests", + "collectionName": "logging-tests-collection", + "documents": [] + } + ], + "tests": [ + { + "description": "command log messages do not include server connection id", + "operations": [ + { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "x": 1 + } + } + }, + { + "name": "find", + "object": "collection", + "arguments": { + "filter": { + "$or": true + } + }, + "expectError": { + "isError": true + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "commandName": "insert", + "serverConnectionId": { + "$$exists": false + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command succeeded", + "commandName": "insert", + "serverConnectionId": { + "$$exists": false + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "commandName": "find", + "serverConnectionId": { + "$$exists": false + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command failed", + "commandName": "find", + "serverConnectionId": { + "$$exists": false + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/command-logging-and-monitoring/logging/pre-42-server-connection-id.yml b/test/spec/command-logging-and-monitoring/logging/pre-42-server-connection-id.yml new file mode 100644 index 0000000000..7dc80eea07 --- /dev/null +++ b/test/spec/command-logging-and-monitoring/logging/pre-42-server-connection-id.yml @@ -0,0 +1,66 @@ +description: "pre-42-server-connection-id" + +schemaVersion: "1.13" + +runOnRequirements: + - maxServerVersion: "4.0.99" + +createEntities: + - client: + id: &client client + observeLogMessages: + command: debug + - database: + id: &database database + client: *client + databaseName: &databaseName logging-server-connection-id-tests + - collection: + id: &collection collection + database: *database + collectionName: &collectionName logging-tests-collection + +initialData: + - databaseName: *databaseName + collectionName: *collectionName + documents: [] + +tests: + - description: "command log messages do not include server connection id" + operations: + - name: insertOne + object: *collection + arguments: + document: { x: 1 } + - name: find + object: *collection + arguments: + filter: { $or: true } + expectError: + isError: true + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + commandName: insert + serverConnectionId: { $$exists: false } + - level: debug + component: command + data: + message: "Command succeeded" + commandName: insert + serverConnectionId: { $$exists: false } + - level: debug + component: command + data: + message: "Command started" + commandName: find + serverConnectionId: { $$exists: false } + - level: debug + component: command + data: + message: "Command failed" + commandName: find + serverConnectionId: { $$exists: false } diff --git a/test/spec/command-logging-and-monitoring/logging/redacted-commands.json b/test/spec/command-logging-and-monitoring/logging/redacted-commands.json new file mode 100644 index 0000000000..43b9ff74f2 --- /dev/null +++ b/test/spec/command-logging-and-monitoring/logging/redacted-commands.json @@ -0,0 +1,1438 @@ +{ + "description": "redacted-commands", + "schemaVersion": "1.13", + "runOnRequirements": [ + { + "minServerVersion": "5.0", + "auth": false + } + ], + "createEntities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeLogMessages": { + "command": "debug" + } + } + }, + { + "client": { + "id": "failPointClient", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "logging-redaction-tests" + } + } + ], + "tests": [ + { + "description": "authenticate command and resulting server-generated error are redacted", + "operations": [ + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "authenticate", + "command": { + "authenticate": 1, + "mechanism": "MONGODB-X509", + "user": "CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry", + "db": "$external" + } + }, + "expectError": { + "isClientError": false + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "authenticate", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "failureIsRedacted": true, + "data": { + "message": "Command failed", + "commandName": "authenticate", + "failure": { + "$$exists": true + } + } + } + ] + } + ] + }, + { + "description": "network error in response to authenticate is not redacted", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "failPointClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "authenticate" + ], + "closeConnection": true + } + } + } + }, + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "authenticate", + "command": { + "authenticate": 1, + "mechanism": "MONGODB-X509", + "user": "CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry" + } + }, + "expectError": { + "isClientError": true + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "authenticate", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "failureIsRedacted": false, + "data": { + "message": "Command failed", + "commandName": "authenticate", + "failure": { + "$$exists": true + } + } + } + ] + } + ] + }, + { + "description": "saslStart command and resulting server-generated error are redacted", + "operations": [ + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "saslStart", + "command": { + "saslStart": 1, + "payload": "definitely-invalid-payload", + "db": "admin" + } + }, + "expectError": { + "isClientError": false + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "saslStart", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "failureIsRedacted": true, + "data": { + "message": "Command failed", + "commandName": "saslStart", + "failure": { + "$$exists": true + } + } + } + ] + } + ] + }, + { + "description": "network error in response to saslStart is not redacted", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "failPointClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "saslStart" + ], + "closeConnection": true + } + } + } + }, + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "saslStart", + "command": { + "saslStart": 1, + "payload": "ZmFrZXNhc2xwYXlsb2Fk", + "mechanism": "MONGODB-X509" + } + }, + "expectError": { + "isClientError": true + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "saslStart", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "failureIsRedacted": false, + "data": { + "message": "Command failed", + "commandName": "saslStart", + "failure": { + "$$exists": true + } + } + } + ] + } + ] + }, + { + "description": "saslContinue command and resulting server-generated error are redacted", + "operations": [ + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "saslContinue", + "command": { + "saslContinue": 1, + "conversationId": 0, + "payload": "definitely-invalid-payload" + } + }, + "expectError": { + "isClientError": false + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "saslContinue", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "failureIsRedacted": true, + "data": { + "message": "Command failed", + "commandName": "saslContinue", + "failure": { + "$$exists": true + } + } + } + ] + } + ] + }, + { + "description": "network error in response to saslContinue is not redacted", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "failPointClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "saslContinue" + ], + "closeConnection": true + } + } + } + }, + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "saslContinue", + "command": { + "saslContinue": 1, + "conversationId": 0, + "payload": "ZmFrZXNhc2xwYXlsb2Fk" + } + }, + "expectError": { + "isClientError": true + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "saslContinue", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "failureIsRedacted": false, + "data": { + "message": "Command failed", + "commandName": "saslContinue", + "failure": { + "$$exists": true + } + } + } + ] + } + ] + }, + { + "description": "getnonce command and server reply are redacted", + "runOnRequirements": [ + { + "maxServerVersion": "6.1.99" + } + ], + "operations": [ + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "getnonce", + "command": { + "getnonce": 1 + } + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "getnonce", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command succeeded", + "commandName": "getnonce", + "reply": { + "$$matchAsDocument": {} + } + } + } + ] + } + ] + }, + { + "description": "network error in response to getnonce is not redacted", + "runOnRequirements": [ + { + "maxServerVersion": "6.1.99" + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "failPointClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "getnonce" + ], + "closeConnection": true + } + } + } + }, + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "getnonce", + "command": { + "getnonce": 1 + } + }, + "expectError": { + "isClientError": true + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "getnonce", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "failureIsRedacted": false, + "data": { + "message": "Command failed", + "commandName": "getnonce", + "failure": { + "$$exists": true + } + } + } + ] + } + ] + }, + { + "description": "createUser command and resulting server-generated error are redacted", + "operations": [ + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "createUser", + "command": { + "createUser": "private", + "pwd": {}, + "roles": [] + } + }, + "expectError": { + "isClientError": false + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "createUser", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "failureIsRedacted": true, + "data": { + "message": "Command failed", + "commandName": "createUser", + "failure": { + "$$exists": true + } + } + } + ] + } + ] + }, + { + "description": "network error in response to createUser is not redacted", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "failPointClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "createUser" + ], + "closeConnection": true + } + } + } + }, + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "createUser", + "command": { + "createUser": "private", + "pwd": "pwd", + "roles": [] + } + }, + "expectError": { + "isClientError": true + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "createUser", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "failureIsRedacted": false, + "data": { + "message": "Command failed", + "commandName": "createUser", + "failure": { + "$$exists": true + } + } + } + ] + } + ] + }, + { + "description": "updateUser command and resulting server-generated error are redacted", + "operations": [ + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "updateUser", + "command": { + "updateUser": "private", + "pwd": {}, + "roles": [] + } + }, + "expectError": { + "isClientError": false + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "updateUser", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "failureIsRedacted": true, + "data": { + "message": "Command failed", + "commandName": "updateUser", + "failure": { + "$$exists": true + } + } + } + ] + } + ] + }, + { + "description": "network error in response to updateUser is not redacted", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "failPointClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "updateUser" + ], + "closeConnection": true + } + } + } + }, + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "updateUser", + "command": { + "updateUser": "private", + "pwd": "pwd", + "roles": [] + } + }, + "expectError": { + "isClientError": true + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "updateUser", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "failureIsRedacted": false, + "data": { + "message": "Command failed", + "commandName": "updateUser", + "failure": { + "$$exists": true + } + } + } + ] + } + ] + }, + { + "description": "copydbgetnonce command and resulting server-generated error are redacted", + "runOnRequirements": [ + { + "maxServerVersion": "3.6.99" + } + ], + "operations": [ + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "copydbgetnonce", + "command": { + "copydbgetnonce": "private" + } + }, + "expectError": { + "isClientError": false + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "copydbgetnonce", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "failureIsRedacted": true, + "data": { + "message": "Command failed", + "commandName": "copydbgetnonce", + "failure": { + "$$exists": true + } + } + } + ] + } + ] + }, + { + "description": "network error in response to copydbgetnonce is not redacted", + "runOnRequirements": [ + { + "maxServerVersion": "3.6.99" + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "failPointClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "copydbgetnonce" + ], + "closeConnection": true + } + } + } + }, + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "copydbgetnonce", + "command": { + "copydbgetnonce": "private" + } + }, + "expectError": { + "isClientError": true + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "copydbgetnonce", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "failureIsRedacted": false, + "data": { + "message": "Command failed", + "commandName": "copydbgetnonce", + "failure": { + "$$exists": true + } + } + } + ] + } + ] + }, + { + "description": "copydbsaslstart command and resulting server-generated error are redacted", + "runOnRequirements": [ + { + "maxServerVersion": "4.0.99" + } + ], + "operations": [ + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "copydbsaslstart", + "command": { + "copydbsaslstart": "private" + } + }, + "expectError": { + "isClientError": false + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "copydbsaslstart", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "failureIsRedacted": true, + "data": { + "message": "Command failed", + "commandName": "copydbsaslstart", + "failure": { + "$$exists": true + } + } + } + ] + } + ] + }, + { + "description": "network error in response to copydbsaslstart is not redacted", + "runOnRequirements": [ + { + "maxServerVersion": "4.0.99" + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "failPointClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "copydbsaslstart" + ], + "closeConnection": true + } + } + } + }, + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "copydbsaslstart", + "command": { + "copydbsaslstart": "private" + } + }, + "expectError": { + "isClientError": true + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "copydbgetnonce", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "failureIsRedacted": false, + "data": { + "message": "Command failed", + "commandName": "copydbgetnonce", + "failure": { + "$$exists": true + } + } + } + ] + } + ] + }, + { + "description": "copydb command and resulting server-generated error are redacted", + "runOnRequirements": [ + { + "maxServerVersion": "4.0.99" + } + ], + "operations": [ + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "copydb", + "command": { + "copydb": "private" + } + }, + "expectError": { + "isClientError": false + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "copydb", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "failureIsRedacted": true, + "data": { + "message": "Command failed", + "commandName": "copydb", + "failure": { + "$$exists": true + } + } + } + ] + } + ] + }, + { + "description": "network error in response to copydb is not redacted", + "runOnRequirements": [ + { + "maxServerVersion": "4.0.99" + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "failPointClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "copydb" + ], + "closeConnection": true + } + } + } + }, + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "copydb", + "command": { + "copydb": "private" + } + }, + "expectError": { + "isClientError": true + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "copydb", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "failureIsRedacted": false, + "data": { + "message": "Command failed", + "commandName": "copydb", + "failure": { + "$$exists": true + } + } + } + ] + } + ] + }, + { + "description": "hello with speculative authenticate command and server reply are redacted", + "runOnRequirements": [ + { + "minServerVersion": "4.9" + } + ], + "operations": [ + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "hello", + "command": { + "hello": 1, + "speculativeAuthenticate": { + "saslStart": 1 + } + } + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "hello", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command succeeded", + "commandName": "hello", + "reply": { + "$$matchAsDocument": {} + } + } + } + ] + } + ] + }, + { + "description": "legacy hello with speculative authenticate command and server reply are redacted", + "operations": [ + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "ismaster", + "command": { + "ismaster": 1, + "speculativeAuthenticate": { + "saslStart": 1 + } + } + } + }, + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "isMaster", + "command": { + "isMaster": 1, + "speculativeAuthenticate": { + "saslStart": 1 + } + } + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "ismaster", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command succeeded", + "commandName": "ismaster", + "reply": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "isMaster", + "command": { + "$$matchAsDocument": {} + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command succeeded", + "commandName": "isMaster", + "reply": { + "$$matchAsDocument": {} + } + } + } + ] + } + ] + }, + { + "description": "hello without speculative authenticate command and server reply are not redacted", + "runOnRequirements": [ + { + "minServerVersion": "4.9" + } + ], + "operations": [ + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "hello", + "command": { + "hello": 1 + } + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "hello", + "command": { + "$$matchAsDocument": { + "$$matchAsRoot": { + "hello": 1 + } + } + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command succeeded", + "commandName": "hello", + "reply": { + "$$matchAsDocument": { + "$$matchAsRoot": { + "ok": 1, + "isWritablePrimary": true + } + } + } + } + } + ] + } + ] + }, + { + "description": "legacy hello without speculative authenticate command and server reply are not redacted", + "operations": [ + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "ismaster", + "command": { + "ismaster": 1 + } + } + }, + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "isMaster", + "command": { + "isMaster": 1 + } + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "ismaster", + "command": { + "$$matchAsDocument": { + "$$matchAsRoot": { + "ismaster": 1 + } + } + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command succeeded", + "commandName": "ismaster", + "reply": { + "$$matchAsDocument": { + "$$matchAsRoot": { + "ok": 1, + "ismaster": true + } + } + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "databaseName": "logging-redaction-tests", + "commandName": "isMaster", + "command": { + "$$matchAsDocument": { + "$$matchAsRoot": { + "isMaster": 1 + } + } + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command succeeded", + "commandName": "isMaster", + "reply": { + "$$matchAsDocument": { + "$$matchAsRoot": { + "ok": 1, + "ismaster": true + } + } + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/command-logging-and-monitoring/logging/redacted-commands.yml b/test/spec/command-logging-and-monitoring/logging/redacted-commands.yml new file mode 100644 index 0000000000..05d61465e5 --- /dev/null +++ b/test/spec/command-logging-and-monitoring/logging/redacted-commands.yml @@ -0,0 +1,850 @@ +description: "redacted-commands" + +schemaVersion: "1.13" + +runOnRequirements: + - minServerVersion: "5.0" + auth: false + +createEntities: + - client: + id: &client client + useMultipleMongoses: false + observeLogMessages: + command: debug + - client: + id: &failPointClient failPointClient + useMultipleMongoses: false + - database: + id: &database database + client: *client + databaseName: &databaseName logging-redaction-tests + +tests: + - description: "authenticate command and resulting server-generated error are redacted" + operations: + - name: runCommand + object: *database + arguments: + commandName: authenticate + command: + authenticate: 1 + mechanism: "MONGODB-X509" + user: "CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry" + db: "$external" + # An authentication error is expected, but we want to check that the + # CommandStartedEvent is redacted + expectError: + isClientError: false + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: authenticate + command: + $$matchAsDocument: {} + - level: debug + component: command + failureIsRedacted: true + data: + message: "Command failed" + commandName: authenticate + failure: { $$exists: true } + + - description: "network error in response to authenticate is not redacted" + operations: + - name: failPoint + object: testRunner + arguments: + client: *failPointClient + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: ["authenticate"] + closeConnection: true + - name: runCommand + object: *database + arguments: + commandName: authenticate + command: + authenticate: 1 + mechanism: "MONGODB-X509" + user: "CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry" + expectError: + isClientError: true + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: authenticate + command: + $$matchAsDocument: {} + - level: debug + component: command + failureIsRedacted: false + data: + message: "Command failed" + commandName: authenticate + failure: { $$exists: true } + + - description: "saslStart command and resulting server-generated error are redacted" + operations: + - name: runCommand + object: *database + arguments: + commandName: saslStart + command: + saslStart: 1 + payload: "definitely-invalid-payload" + db: "admin" + expectError: + isClientError: false + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: saslStart + command: + $$matchAsDocument: {} + - level: debug + component: command + failureIsRedacted: true + data: + message: "Command failed" + commandName: saslStart + failure: { $$exists: true } + + - description: "network error in response to saslStart is not redacted" + operations: + - name: failPoint + object: testRunner + arguments: + client: *failPointClient + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: ["saslStart"] + closeConnection: true + - name: runCommand + object: *database + arguments: + commandName: saslStart + command: + saslStart: 1 + payload: ZmFrZXNhc2xwYXlsb2Fk + mechanism: MONGODB-X509 + expectError: + isClientError: true + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: saslStart + command: + $$matchAsDocument: {} + - level: debug + component: command + failureIsRedacted: false + data: + message: "Command failed" + commandName: saslStart + failure: { $$exists: true } + + - description: "saslContinue command and resulting server-generated error are redacted" + operations: + - name: runCommand + object: *database + arguments: + commandName: saslContinue + command: + saslContinue: 1 + conversationId: 0 + payload: "definitely-invalid-payload" + expectError: + isClientError: false + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: saslContinue + command: + $$matchAsDocument: {} + - level: debug + component: command + failureIsRedacted: true + data: + message: "Command failed" + commandName: saslContinue + failure: { $$exists: true } + + - description: "network error in response to saslContinue is not redacted" + operations: + - name: failPoint + object: testRunner + arguments: + client: *failPointClient + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: ["saslContinue"] + closeConnection: true + - name: runCommand + object: *database + arguments: + commandName: saslContinue + command: + saslContinue: 1 + conversationId: 0 + payload: ZmFrZXNhc2xwYXlsb2Fk + expectError: + isClientError: true + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: saslContinue + command: + $$matchAsDocument: {} + - level: debug + component: command + failureIsRedacted: false + data: + message: "Command failed" + commandName: saslContinue + failure: { $$exists: true } + + - description: "getnonce command and server reply are redacted" + runOnRequirements: + - maxServerVersion: 6.1.99 # getnonce removed as of 6.2 via SERVER-71007 + operations: + - name: runCommand + object: *database + arguments: + commandName: getnonce + command: + getnonce: 1 + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: getnonce + command: + $$matchAsDocument: {} + - level: debug + component: command + data: + message: "Command succeeded" + commandName: getnonce + reply: + $$matchAsDocument: {} + + - description: "network error in response to getnonce is not redacted" + runOnRequirements: + - maxServerVersion: 6.1.99 # getnonce removed as of 6.2 via SERVER-71007 + operations: + - name: failPoint + object: testRunner + arguments: + client: *failPointClient + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: ["getnonce"] + closeConnection: true + - name: runCommand + object: *database + arguments: + commandName: getnonce + command: + getnonce: 1 + expectError: + isClientError: true + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: getnonce + command: + $$matchAsDocument: {} + - level: debug + component: command + failureIsRedacted: false + data: + message: "Command failed" + commandName: getnonce + failure: { $$exists: true } + + - description: "createUser command and resulting server-generated error are redacted" + operations: + - name: runCommand + object: *database + arguments: + commandName: createUser + command: + createUser: "private" + # Passing an object is prohibited and we want to trigger a command + # failure + pwd: {} + roles: [] + expectError: + isClientError: false + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: createUser + command: + $$matchAsDocument: {} + - level: debug + component: command + failureIsRedacted: true + data: + message: "Command failed" + commandName: createUser + failure: { $$exists: true } + + - description: "network error in response to createUser is not redacted" + operations: + - name: failPoint + object: testRunner + arguments: + client: *failPointClient + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: ["createUser"] + closeConnection: true + - name: runCommand + object: *database + arguments: + commandName: createUser + command: + createUser: "private" + pwd: "pwd" + roles: [] + expectError: + isClientError: true + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: createUser + command: + $$matchAsDocument: {} + - level: debug + component: command + failureIsRedacted: false + data: + message: "Command failed" + commandName: createUser + failure: { $$exists: true } + + - description: "updateUser command and resulting server-generated error are redacted" + operations: + - name: runCommand + object: *database + arguments: + commandName: updateUser + command: + updateUser: "private" + pwd: {} + roles: [] + expectError: + isClientError: false + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: updateUser + command: + $$matchAsDocument: {} + - level: debug + component: command + failureIsRedacted: true + data: + message: "Command failed" + commandName: updateUser + failure: { $$exists: true } + + - description: "network error in response to updateUser is not redacted" + operations: + - name: failPoint + object: testRunner + arguments: + client: *failPointClient + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: ["updateUser"] + closeConnection: true + - name: runCommand + object: *database + arguments: + commandName: updateUser + command: + updateUser: "private" + pwd: "pwd" + roles: [] + expectError: + isClientError: true + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: updateUser + command: + $$matchAsDocument: {} + - level: debug + component: command + failureIsRedacted: false + data: + message: "Command failed" + commandName: updateUser + failure: { $$exists: true } + + - description: "copydbgetnonce command and resulting server-generated error are redacted" + runOnRequirements: + - maxServerVersion: 3.6.99 # copydbgetnonce was removed as of 4.0 via SERVER-32276 + operations: + - name: runCommand + object: *database + arguments: + commandName: copydbgetnonce + command: + copydbgetnonce: "private" + expectError: + isClientError: false + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: copydbgetnonce + command: + $$matchAsDocument: {} + - level: debug + component: command + failureIsRedacted: true + data: + message: "Command failed" + commandName: copydbgetnonce + failure: { $$exists: true } + + - description: "network error in response to copydbgetnonce is not redacted" + runOnRequirements: + - maxServerVersion: 3.6.99 # copydbgetnonce was removed as of 4.0 via SERVER-32276 + operations: + - name: failPoint + object: testRunner + arguments: + client: *failPointClient + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: ["copydbgetnonce"] + closeConnection: true + - name: runCommand + object: *database + arguments: + commandName: copydbgetnonce + command: + copydbgetnonce: "private" + expectError: + isClientError: true + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: copydbgetnonce + command: + $$matchAsDocument: {} + - level: debug + component: command + failureIsRedacted: false + data: + message: "Command failed" + commandName: copydbgetnonce + failure: { $$exists: true } + + - description: "copydbsaslstart command and resulting server-generated error are redacted" + runOnRequirements: + - maxServerVersion: 4.0.99 # copydbsaslstart was removed as of 4.2 via SERVER-36211 + operations: + - name: runCommand + object: *database + arguments: + commandName: copydbsaslstart + command: + copydbsaslstart: "private" + expectError: + isClientError: false + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: copydbsaslstart + command: + $$matchAsDocument: {} + - level: debug + component: command + failureIsRedacted: true + data: + message: "Command failed" + commandName: copydbsaslstart + failure: { $$exists: true } + + - description: "network error in response to copydbsaslstart is not redacted" + runOnRequirements: + - maxServerVersion: 4.0.99 # copydbsaslstart was removed as of 4.2 via SERVER-36211 + operations: + - name: failPoint + object: testRunner + arguments: + client: *failPointClient + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: ["copydbsaslstart"] + closeConnection: true + - name: runCommand + object: *database + arguments: + commandName: copydbsaslstart + command: + copydbsaslstart: "private" + expectError: + isClientError: true + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: copydbgetnonce + command: + $$matchAsDocument: {} + - level: debug + component: command + failureIsRedacted: false + data: + message: "Command failed" + commandName: copydbgetnonce + failure: { $$exists: true } + + - description: "copydb command and resulting server-generated error are redacted" + runOnRequirements: + - maxServerVersion: 4.0.99 # copydb was removed as of 4.2 via SERVER-36257 + operations: + - name: runCommand + object: *database + arguments: + commandName: copydb + command: + copydb: "private" + expectError: + isClientError: false + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: copydb + command: + $$matchAsDocument: {} + - level: debug + component: command + failureIsRedacted: true + data: + message: "Command failed" + commandName: copydb + failure: { $$exists: true } + + - description: "network error in response to copydb is not redacted" + runOnRequirements: + - maxServerVersion: 4.0.99 # copydb was removed as of 4.2 via SERVER-36257 + operations: + - name: failPoint + object: testRunner + arguments: + client: *failPointClient + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: ["copydb"] + closeConnection: true + - name: runCommand + object: *database + arguments: + commandName: copydb + command: + copydb: "private" + expectError: + isClientError: true + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: copydb + command: + $$matchAsDocument: {} + - level: debug + component: command + failureIsRedacted: false + data: + message: "Command failed" + commandName: copydb + failure: { $$exists: true } + + - description: "hello with speculative authenticate command and server reply are redacted" + runOnRequirements: + - minServerVersion: "4.9" + operations: + - name: runCommand + object: *database + arguments: + commandName: hello + command: + hello: 1 + speculativeAuthenticate: + saslStart: 1 + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: hello + command: + $$matchAsDocument: {} + - level: debug + component: command + data: + message: "Command succeeded" + commandName: hello + reply: + $$matchAsDocument: {} + + + - description: "legacy hello with speculative authenticate command and server reply are redacted" + operations: + - name: runCommand + object: *database + arguments: + commandName: ismaster + command: + ismaster: 1 + speculativeAuthenticate: + saslStart: 1 + - name: runCommand + object: *database + arguments: + commandName: isMaster + command: + isMaster: 1 + speculativeAuthenticate: + saslStart: 1 + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: ismaster + command: + $$matchAsDocument: {} + - level: debug + component: command + data: + message: "Command succeeded" + commandName: ismaster + reply: + $$matchAsDocument: {} + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: isMaster + command: + $$matchAsDocument: {} + - level: debug + component: command + data: + message: "Command succeeded" + commandName: isMaster + reply: + $$matchAsDocument: {} + + - description: "hello without speculative authenticate command and server reply are not redacted" + runOnRequirements: + - minServerVersion: "4.9" + operations: + - name: runCommand + object: *database + arguments: + commandName: hello + command: + hello: 1 + + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: hello + command: + $$matchAsDocument: + $$matchAsRoot: + hello: 1 + - level: debug + component: command + data: + message: "Command succeeded" + commandName: hello + reply: + $$matchAsDocument: + $$matchAsRoot: + ok: 1 + isWritablePrimary: true + + - description: "legacy hello without speculative authenticate command and server reply are not redacted" + operations: + - name: runCommand + object: *database + arguments: + commandName: ismaster + command: + ismaster: 1 + - name: runCommand + object: *database + arguments: + commandName: isMaster + command: + isMaster: 1 + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: ismaster + command: + $$matchAsDocument: + $$matchAsRoot: + ismaster: 1 + - level: debug + component: command + data: + message: "Command succeeded" + commandName: ismaster + reply: + $$matchAsDocument: + $$matchAsRoot: + ok: 1 + ismaster: true + - level: debug + component: command + data: + message: "Command started" + databaseName: *databaseName + commandName: isMaster + command: + $$matchAsDocument: + $$matchAsRoot: + isMaster: 1 + - level: debug + component: command + data: + message: "Command succeeded" + commandName: isMaster + reply: + $$matchAsDocument: + $$matchAsRoot: + ok: 1 + ismaster: true diff --git a/test/spec/command-logging-and-monitoring/logging/server-connection-id.json b/test/spec/command-logging-and-monitoring/logging/server-connection-id.json new file mode 100644 index 0000000000..abbbbc7442 --- /dev/null +++ b/test/spec/command-logging-and-monitoring/logging/server-connection-id.json @@ -0,0 +1,131 @@ +{ + "description": "server-connection-id", + "schemaVersion": "1.13", + "runOnRequirements": [ + { + "minServerVersion": "4.2" + } + ], + "createEntities": [ + { + "client": { + "id": "client", + "observeLogMessages": { + "command": "debug" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "logging-server-connection-id-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "logging-tests-collection" + } + } + ], + "initialData": [ + { + "databaseName": "logging-server-connection-id-tests", + "collectionName": "logging-tests-collection", + "documents": [] + } + ], + "tests": [ + { + "description": "command log messages include server connection id", + "operations": [ + { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "x": 1 + } + } + }, + { + "name": "find", + "object": "collection", + "arguments": { + "filter": { + "$or": true + } + }, + "expectError": { + "isError": true + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "commandName": "insert", + "serverConnectionId": { + "$$type": [ + "int", + "long" + ] + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command succeeded", + "commandName": "insert", + "serverConnectionId": { + "$$type": [ + "int", + "long" + ] + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "commandName": "find", + "serverConnectionId": { + "$$type": [ + "int", + "long" + ] + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command failed", + "commandName": "find", + "serverConnectionId": { + "$$type": [ + "int", + "long" + ] + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/command-logging-and-monitoring/logging/server-connection-id.yml b/test/spec/command-logging-and-monitoring/logging/server-connection-id.yml new file mode 100644 index 0000000000..4f54d1207e --- /dev/null +++ b/test/spec/command-logging-and-monitoring/logging/server-connection-id.yml @@ -0,0 +1,66 @@ +description: "server-connection-id" + +schemaVersion: "1.13" + +runOnRequirements: + - minServerVersion: "4.2" + +createEntities: + - client: + id: &client client + observeLogMessages: + command: debug + - database: + id: &database database + client: *client + databaseName: &databaseName logging-server-connection-id-tests + - collection: + id: &collection collection + database: *database + collectionName: &collectionName logging-tests-collection + +initialData: + - databaseName: *databaseName + collectionName: *collectionName + documents: [] + +tests: + - description: "command log messages include server connection id" + operations: + - name: insertOne + object: *collection + arguments: + document: { x: 1 } + - name: find + object: *collection + arguments: + filter: { $or: true } + expectError: + isError: true + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + commandName: insert + serverConnectionId: { $$type: [int, long] } + - level: debug + component: command + data: + message: "Command succeeded" + commandName: insert + serverConnectionId: { $$type: [int, long] } + - level: debug + component: command + data: + message: "Command started" + commandName: find + serverConnectionId: { $$type: [int, long] } + - level: debug + component: command + data: + message: "Command failed" + commandName: find + serverConnectionId: { $$type: [int, long] } diff --git a/test/spec/command-logging-and-monitoring/logging/service-id.json b/test/spec/command-logging-and-monitoring/logging/service-id.json new file mode 100644 index 0000000000..ea39d61231 --- /dev/null +++ b/test/spec/command-logging-and-monitoring/logging/service-id.json @@ -0,0 +1,207 @@ +{ + "description": "service-id", + "schemaVersion": "1.13", + "createEntities": [ + { + "client": { + "id": "client", + "observeLogMessages": { + "command": "debug" + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "logging-server-connection-id-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "logging-tests-collection" + } + } + ], + "initialData": [ + { + "databaseName": "logging-server-connection-id-tests", + "collectionName": "logging-tests-collection", + "documents": [] + } + ], + "tests": [ + { + "description": "command log messages include serviceId when in LB mode", + "runOnRequirements": [ + { + "topologies": [ + "load-balanced" + ] + } + ], + "operations": [ + { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "x": 1 + } + } + }, + { + "name": "find", + "object": "collection", + "arguments": { + "filter": { + "$or": true + } + }, + "expectError": { + "isError": true + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "commandName": "insert", + "serviceId": { + "$$type": "string" + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command succeeded", + "commandName": "insert", + "serviceId": { + "$$type": "string" + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "commandName": "find", + "serviceId": { + "$$type": "string" + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command failed", + "commandName": "find", + "serviceId": { + "$$type": "string" + } + } + } + ] + } + ] + }, + { + "description": "command log messages omit serviceId when not in LB mode", + "runOnRequirements": [ + { + "topologies": [ + "single", + "replicaset", + "sharded" + ] + } + ], + "operations": [ + { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "x": 1 + } + } + }, + { + "name": "find", + "object": "collection", + "arguments": { + "filter": { + "$or": true + } + }, + "expectError": { + "isError": true + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "commandName": "insert", + "serviceId": { + "$$exists": false + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command succeeded", + "commandName": "insert", + "serviceId": { + "$$exists": false + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command started", + "commandName": "find", + "serviceId": { + "$$exists": false + } + } + }, + { + "level": "debug", + "component": "command", + "data": { + "message": "Command failed", + "commandName": "find", + "serviceId": { + "$$exists": false + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/command-logging-and-monitoring/logging/service-id.yml b/test/spec/command-logging-and-monitoring/logging/service-id.yml new file mode 100644 index 0000000000..0c0f444e23 --- /dev/null +++ b/test/spec/command-logging-and-monitoring/logging/service-id.yml @@ -0,0 +1,111 @@ +description: "service-id" + +schemaVersion: "1.13" + +createEntities: + - client: + id: &client client + observeLogMessages: + command: debug + - database: + id: &database database + client: *client + databaseName: &databaseName logging-server-connection-id-tests + - collection: + id: &collection collection + database: *database + collectionName: &collectionName logging-tests-collection + +initialData: + - databaseName: *databaseName + collectionName: *collectionName + documents: [] + +tests: + - description: "command log messages include serviceId when in LB mode" + runOnRequirements: + - topologies: + - load-balanced + operations: + - name: insertOne + object: *collection + arguments: + document: { x: 1 } + - name: find + object: *collection + arguments: + filter: { $or: true } + expectError: + isError: true + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + commandName: insert + serviceId: { $$type: string } + - level: debug + component: command + data: + message: "Command succeeded" + commandName: insert + serviceId: { $$type: string } + - level: debug + component: command + data: + message: "Command started" + commandName: find + serviceId: { $$type: string } + - level: debug + component: command + data: + message: "Command failed" + commandName: find + serviceId: { $$type: string } + + - description: "command log messages omit serviceId when not in LB mode" + runOnRequirements: + - topologies: + - single + - replicaset + - sharded + operations: + - name: insertOne + object: *collection + arguments: + document: { x: 1 } + - name: find + object: *collection + arguments: + filter: { $or: true } + expectError: + isError: true + expectLogMessages: + - client: *client + messages: + - level: debug + component: command + data: + message: "Command started" + commandName: insert + serviceId: { $$exists: false } + - level: debug + component: command + data: + message: "Command succeeded" + commandName: insert + serviceId: { $$exists: false } + - level: debug + component: command + data: + message: "Command started" + commandName: find + serviceId: { $$exists: false } + - level: debug + component: command + data: + message: "Command failed" + commandName: find + serviceId: { $$exists: false } diff --git a/test/spec/command-monitoring/unified/bulkWrite.json b/test/spec/command-logging-and-monitoring/monitoring/bulkWrite.json similarity index 100% rename from test/spec/command-monitoring/unified/bulkWrite.json rename to test/spec/command-logging-and-monitoring/monitoring/bulkWrite.json diff --git a/test/spec/command-monitoring/unified/bulkWrite.yml b/test/spec/command-logging-and-monitoring/monitoring/bulkWrite.yml similarity index 100% rename from test/spec/command-monitoring/unified/bulkWrite.yml rename to test/spec/command-logging-and-monitoring/monitoring/bulkWrite.yml diff --git a/test/spec/command-monitoring/unified/command.json b/test/spec/command-logging-and-monitoring/monitoring/command.json similarity index 100% rename from test/spec/command-monitoring/unified/command.json rename to test/spec/command-logging-and-monitoring/monitoring/command.json diff --git a/test/spec/command-monitoring/unified/command.yml b/test/spec/command-logging-and-monitoring/monitoring/command.yml similarity index 100% rename from test/spec/command-monitoring/unified/command.yml rename to test/spec/command-logging-and-monitoring/monitoring/command.yml diff --git a/test/spec/command-monitoring/unified/deleteMany.json b/test/spec/command-logging-and-monitoring/monitoring/deleteMany.json similarity index 100% rename from test/spec/command-monitoring/unified/deleteMany.json rename to test/spec/command-logging-and-monitoring/monitoring/deleteMany.json diff --git a/test/spec/command-monitoring/unified/deleteMany.yml b/test/spec/command-logging-and-monitoring/monitoring/deleteMany.yml similarity index 100% rename from test/spec/command-monitoring/unified/deleteMany.yml rename to test/spec/command-logging-and-monitoring/monitoring/deleteMany.yml diff --git a/test/spec/command-monitoring/unified/deleteOne.json b/test/spec/command-logging-and-monitoring/monitoring/deleteOne.json similarity index 100% rename from test/spec/command-monitoring/unified/deleteOne.json rename to test/spec/command-logging-and-monitoring/monitoring/deleteOne.json diff --git a/test/spec/command-monitoring/unified/deleteOne.yml b/test/spec/command-logging-and-monitoring/monitoring/deleteOne.yml similarity index 100% rename from test/spec/command-monitoring/unified/deleteOne.yml rename to test/spec/command-logging-and-monitoring/monitoring/deleteOne.yml diff --git a/test/spec/command-monitoring/unified/find.json b/test/spec/command-logging-and-monitoring/monitoring/find.json similarity index 100% rename from test/spec/command-monitoring/unified/find.json rename to test/spec/command-logging-and-monitoring/monitoring/find.json diff --git a/test/spec/command-monitoring/unified/find.yml b/test/spec/command-logging-and-monitoring/monitoring/find.yml similarity index 100% rename from test/spec/command-monitoring/unified/find.yml rename to test/spec/command-logging-and-monitoring/monitoring/find.yml diff --git a/test/spec/command-monitoring/unified/insertMany.json b/test/spec/command-logging-and-monitoring/monitoring/insertMany.json similarity index 100% rename from test/spec/command-monitoring/unified/insertMany.json rename to test/spec/command-logging-and-monitoring/monitoring/insertMany.json diff --git a/test/spec/command-monitoring/unified/insertMany.yml b/test/spec/command-logging-and-monitoring/monitoring/insertMany.yml similarity index 100% rename from test/spec/command-monitoring/unified/insertMany.yml rename to test/spec/command-logging-and-monitoring/monitoring/insertMany.yml diff --git a/test/spec/command-monitoring/unified/insertOne.json b/test/spec/command-logging-and-monitoring/monitoring/insertOne.json similarity index 100% rename from test/spec/command-monitoring/unified/insertOne.json rename to test/spec/command-logging-and-monitoring/monitoring/insertOne.json diff --git a/test/spec/command-monitoring/unified/insertOne.yml b/test/spec/command-logging-and-monitoring/monitoring/insertOne.yml similarity index 100% rename from test/spec/command-monitoring/unified/insertOne.yml rename to test/spec/command-logging-and-monitoring/monitoring/insertOne.yml diff --git a/test/spec/command-logging-and-monitoring/monitoring/pre-42-server-connection-id.json b/test/spec/command-logging-and-monitoring/monitoring/pre-42-server-connection-id.json new file mode 100644 index 0000000000..141fbe584f --- /dev/null +++ b/test/spec/command-logging-and-monitoring/monitoring/pre-42-server-connection-id.json @@ -0,0 +1,101 @@ +{ + "description": "pre-42-server-connection-id", + "schemaVersion": "1.6", + "runOnRequirements": [ + { + "maxServerVersion": "4.0.99" + } + ], + "createEntities": [ + { + "client": { + "id": "client", + "observeEvents": [ + "commandStartedEvent", + "commandSucceededEvent", + "commandFailedEvent" + ] + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "server-connection-id-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "databaseName": "server-connection-id-tests", + "collectionName": "coll", + "documents": [] + } + ], + "tests": [ + { + "description": "command events do not include server connection id", + "operations": [ + { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "x": 1 + } + } + }, + { + "name": "find", + "object": "collection", + "arguments": { + "filter": { + "$or": true + } + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client", + "events": [ + { + "commandStartedEvent": { + "commandName": "insert", + "hasServerConnectionId": false + } + }, + { + "commandSucceededEvent": { + "commandName": "insert", + "hasServerConnectionId": false + } + }, + { + "commandStartedEvent": { + "commandName": "find", + "hasServerConnectionId": false + } + }, + { + "commandFailedEvent": { + "commandName": "find", + "hasServerConnectionId": false + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/command-logging-and-monitoring/monitoring/pre-42-server-connection-id.yml b/test/spec/command-logging-and-monitoring/monitoring/pre-42-server-connection-id.yml new file mode 100644 index 0000000000..483a8a3c19 --- /dev/null +++ b/test/spec/command-logging-and-monitoring/monitoring/pre-42-server-connection-id.yml @@ -0,0 +1,56 @@ +description: "pre-42-server-connection-id" + +schemaVersion: "1.6" + +runOnRequirements: + - maxServerVersion: "4.0.99" + +createEntities: + - client: + id: &client client + observeEvents: + - commandStartedEvent + - commandSucceededEvent + - commandFailedEvent + - database: + id: &database database + client: *client + databaseName: &databaseName server-connection-id-tests + - collection: + id: &collection collection + database: *database + collectionName: &collectionName coll + +initialData: + - databaseName: *databaseName + collectionName: *collectionName + documents: [] + +tests: + - description: "command events do not include server connection id" + operations: + - name: insertOne + object: *collection + arguments: + document: { x: 1 } + - name: find + object: *collection + arguments: + filter: { $or: true } + expectError: + isError: true + expectEvents: + - client: *client + events: + - commandStartedEvent: + commandName: insert + hasServerConnectionId: false + - commandSucceededEvent: + commandName: insert + hasServerConnectionId: false + - commandStartedEvent: + commandName: find + hasServerConnectionId: false + - commandFailedEvent: + commandName: find + hasServerConnectionId: false diff --git a/test/spec/command-monitoring/unified/redacted-commands.json b/test/spec/command-logging-and-monitoring/monitoring/redacted-commands.json similarity index 97% rename from test/spec/command-monitoring/unified/redacted-commands.json rename to test/spec/command-logging-and-monitoring/monitoring/redacted-commands.json index 0f85dc3e94..4302ba8900 100644 --- a/test/spec/command-monitoring/unified/redacted-commands.json +++ b/test/spec/command-logging-and-monitoring/monitoring/redacted-commands.json @@ -162,6 +162,11 @@ }, { "description": "getnonce", + "runOnRequirements": [ + { + "maxServerVersion": "6.1.99" + } + ], "operations": [ { "name": "runCommand", @@ -293,6 +298,11 @@ }, { "description": "copydbgetnonce", + "runOnRequirements": [ + { + "maxServerVersion": "3.6.99" + } + ], "operations": [ { "name": "runCommand", @@ -328,6 +338,11 @@ }, { "description": "copydbsaslstart", + "runOnRequirements": [ + { + "maxServerVersion": "4.0.99" + } + ], "operations": [ { "name": "runCommand", @@ -363,6 +378,11 @@ }, { "description": "copydb", + "runOnRequirements": [ + { + "maxServerVersion": "4.0.99" + } + ], "operations": [ { "name": "runCommand", diff --git a/test/spec/command-monitoring/unified/redacted-commands.yml b/test/spec/command-logging-and-monitoring/monitoring/redacted-commands.yml similarity index 95% rename from test/spec/command-monitoring/unified/redacted-commands.yml rename to test/spec/command-logging-and-monitoring/monitoring/redacted-commands.yml index 570fb5a547..adeab99b18 100644 --- a/test/spec/command-monitoring/unified/redacted-commands.yml +++ b/test/spec/command-logging-and-monitoring/monitoring/redacted-commands.yml @@ -93,6 +93,8 @@ tests: payload: { $$exists: false } - description: "getnonce" + runOnRequirements: + - maxServerVersion: 6.1.99 # getnonce removed as of 6.2 via SERVER-71007 operations: - name: runCommand object: *database @@ -159,6 +161,8 @@ tests: roles: { $$exists: false } - description: "copydbgetnonce" + runOnRequirements: + - maxServerVersion: 3.6.99 # copydbgetnonce was removed as of 4.0 via SERVER-32276 operations: - name: runCommand object: *database @@ -176,6 +180,8 @@ tests: command: { copydbgetnonce: { $$exists: false } } - description: "copydbsaslstart" + runOnRequirements: + - maxServerVersion: 4.0.99 # copydbsaslstart was removed as of 4.2 via SERVER-36211 operations: - name: runCommand object: *database @@ -193,6 +199,8 @@ tests: command: { copydbsaslstart: { $$exists: false } } - description: "copydb" + runOnRequirements: + - maxServerVersion: 4.0.99 # copydb was removed as of 4.2 via SERVER-36257 operations: - name: runCommand object: *database diff --git a/test/spec/command-logging-and-monitoring/monitoring/server-connection-id.json b/test/spec/command-logging-and-monitoring/monitoring/server-connection-id.json new file mode 100644 index 0000000000..a8f27637fc --- /dev/null +++ b/test/spec/command-logging-and-monitoring/monitoring/server-connection-id.json @@ -0,0 +1,101 @@ +{ + "description": "server-connection-id", + "schemaVersion": "1.6", + "runOnRequirements": [ + { + "minServerVersion": "4.2" + } + ], + "createEntities": [ + { + "client": { + "id": "client", + "observeEvents": [ + "commandStartedEvent", + "commandSucceededEvent", + "commandFailedEvent" + ] + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "server-connection-id-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "databaseName": "server-connection-id-tests", + "collectionName": "coll", + "documents": [] + } + ], + "tests": [ + { + "description": "command events include server connection id", + "operations": [ + { + "name": "insertOne", + "object": "collection", + "arguments": { + "document": { + "x": 1 + } + } + }, + { + "name": "find", + "object": "collection", + "arguments": { + "filter": { + "$or": true + } + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client", + "events": [ + { + "commandStartedEvent": { + "commandName": "insert", + "hasServerConnectionId": true + } + }, + { + "commandSucceededEvent": { + "commandName": "insert", + "hasServerConnectionId": true + } + }, + { + "commandStartedEvent": { + "commandName": "find", + "hasServerConnectionId": true + } + }, + { + "commandFailedEvent": { + "commandName": "find", + "hasServerConnectionId": true + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/command-logging-and-monitoring/monitoring/server-connection-id.yml b/test/spec/command-logging-and-monitoring/monitoring/server-connection-id.yml new file mode 100644 index 0000000000..abd34dad6e --- /dev/null +++ b/test/spec/command-logging-and-monitoring/monitoring/server-connection-id.yml @@ -0,0 +1,56 @@ +description: "server-connection-id" + +schemaVersion: "1.6" + +runOnRequirements: + - minServerVersion: "4.2" + +createEntities: + - client: + id: &client client + observeEvents: + - commandStartedEvent + - commandSucceededEvent + - commandFailedEvent + - database: + id: &database database + client: *client + databaseName: &databaseName server-connection-id-tests + - collection: + id: &collection collection + database: *database + collectionName: &collectionName coll + +initialData: + - databaseName: *databaseName + collectionName: *collectionName + documents: [] + +tests: + - description: "command events include server connection id" + operations: + - name: insertOne + object: *collection + arguments: + document: { x: 1 } + - name: find + object: *collection + arguments: + filter: { $or: true } + expectError: + isError: true + expectEvents: + - client: *client + events: + - commandStartedEvent: + commandName: insert + hasServerConnectionId: true + - commandSucceededEvent: + commandName: insert + hasServerConnectionId: true + - commandStartedEvent: + commandName: find + hasServerConnectionId: true + - commandFailedEvent: + commandName: find + hasServerConnectionId: true diff --git a/test/spec/command-monitoring/unified/unacknowledgedBulkWrite.json b/test/spec/command-logging-and-monitoring/monitoring/unacknowledgedBulkWrite.json similarity index 100% rename from test/spec/command-monitoring/unified/unacknowledgedBulkWrite.json rename to test/spec/command-logging-and-monitoring/monitoring/unacknowledgedBulkWrite.json diff --git a/test/spec/command-monitoring/unified/unacknowledgedBulkWrite.yml b/test/spec/command-logging-and-monitoring/monitoring/unacknowledgedBulkWrite.yml similarity index 100% rename from test/spec/command-monitoring/unified/unacknowledgedBulkWrite.yml rename to test/spec/command-logging-and-monitoring/monitoring/unacknowledgedBulkWrite.yml diff --git a/test/spec/command-monitoring/unified/updateMany.json b/test/spec/command-logging-and-monitoring/monitoring/updateMany.json similarity index 100% rename from test/spec/command-monitoring/unified/updateMany.json rename to test/spec/command-logging-and-monitoring/monitoring/updateMany.json diff --git a/test/spec/command-monitoring/unified/updateMany.yml b/test/spec/command-logging-and-monitoring/monitoring/updateMany.yml similarity index 100% rename from test/spec/command-monitoring/unified/updateMany.yml rename to test/spec/command-logging-and-monitoring/monitoring/updateMany.yml diff --git a/test/spec/command-monitoring/unified/updateOne.json b/test/spec/command-logging-and-monitoring/monitoring/updateOne.json similarity index 100% rename from test/spec/command-monitoring/unified/updateOne.json rename to test/spec/command-logging-and-monitoring/monitoring/updateOne.json diff --git a/test/spec/command-monitoring/unified/updateOne.yml b/test/spec/command-logging-and-monitoring/monitoring/updateOne.yml similarity index 100% rename from test/spec/command-monitoring/unified/updateOne.yml rename to test/spec/command-logging-and-monitoring/monitoring/updateOne.yml diff --git a/test/spec/command-monitoring/README.rst b/test/spec/command-monitoring/README.rst deleted file mode 100644 index 5700409cf3..0000000000 --- a/test/spec/command-monitoring/README.rst +++ /dev/null @@ -1,131 +0,0 @@ -.. role:: javascript(code) - :language: javascript - -================== -Command Monitoring -================== - -.. contents:: - --------- - -Testing -======= - -Tests in ``unified`` are implemented in the `Unified Test Format <../../unified-test-format/unified-test-format.rst>`__ and require -schema version 1.0. Tests in ``legacy`` should be run as described below. - -Tests are provided in YML and JSON format to assert proper upconversion of commands. - -Database and Collection Names ------------------------------ - -The collection under test is specified in each test file with the fields -``database_name`` and ``collection_name``. - -Data ----- - -The ``data`` at the beginning of each test file is the data that should exist in the -collection under test before each test run. - -Expectations ------------- - -Fake Placeholder Values -``````````````````````` - -When an attribute in an expectation contains the value ``"42"``, ``42`` or ``""``, this is a fake -placeholder value indicating that a special case MUST be tested that could not be -expressed in a YAML or JSON test. These cases are as follows: - -Cursor Matching -^^^^^^^^^^^^^^^ - -When encountering a ``cursor`` or ``getMore`` value of ``"42"`` in a test, the driver MUST assert -that the values are equal to each other and greater than zero. - -Errors -^^^^^^ - -For write errors, ``code`` values of ``42`` MUST assert that the value is present and -greater than zero. ``errmsg`` values of ``""`` MUST assert that the value is not empty -(a string of length greater than 1). - -OK Values -^^^^^^^^^ - -The server is inconsistent on whether the ok values returned are integers or doubles so -for simplicity the tests specify all expected values as doubles. Server 'ok' values of -integers MUST be converted to doubles for comparison with the expected values. - -Additional Values -````````````````` - -The expected events provide the minimum data that is required and can be tested. It is -possible for more values to be present in the events, such as extra data provided when -using sharded clusters or ``nModified`` field in updates. The driver MUST assert the -expected data is present and also MUST allow for additional data to be present as well -at the top level of the command document or reply document. - -For example, say the client sends a causally-consistent "distinct" command with -readConcern level "majority", like:: - - { - "distinct": "collection", - "key": "key", - "readConcern":{ - "afterClusterTime": {"$timestamp":{"t":1522336030,"i":1}}, - "level":"majority" - }, - "$clusterTime": { - "clusterTime": { "$timestamp": { "i": 1, "t": 1522335530 } }, - "signature": { - "hash": { "$binary": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", "$type": "00" }, - "keyId": { "$numberLong": "0" } - } - }, - "lsid": { - "id": { "$binary": "RaigP3oASqu+galPvRAfcg==", "$type": "04" } - } - } - -Then it would pass a command-started event like the following YAML, because the -fields not mentioned in the YAML are ignored:: - - command: - distinct: collection - key: key - -However, if there are fields in command subdocuments that are not mentioned in -the YAML, then the command does *not* pass the test:: - - command: - distinct: collection - key: key - # Fails because the expected readConcern has no "afterClusterTime". - readConcern: - level: majority - -Ignoring Tests Based On Server Version or Topology Type -``````````````````````````````````````````````````````` - -Due to variations in server behavior, some tests may not be valid and MUST NOT be run on -certain server versions or topology types. These tests are indicated with any of the -following fields, which will be optionally provided at the ``description`` level of each -test: - -- ``ignore_if_server_version_greater_than`` (optional): If specified, the test MUST be - skipped if the minor version of the server is greater than this minor version. The - server's patch version MUST NOT be considered. For example, a value of ``3.0`` implies - that the test can run on server version ``3.0.15`` but not ``3.1.0``. - -- ``ignore_if_server_version_less_than`` (optional): If specified, the test MUST be - skipped if the minor version of the server is less than this minor version. The - server's patch version MUST NOT be considered. For example, a value of ``3.2`` implies - that the test can run on server version ``3.2.0`` but not ``3.0.15``. - -- ``ignore_if_topology_type`` (optional): An array of server topologies for which the test - MUST be skipped. Valid topologies are "single", "replicaset", and "sharded". - -Tests that have none of these fields MUST be run on all supported server versions.