diff --git a/.evergreen/run-typescript.sh b/.evergreen/run-typescript.sh old mode 100644 new mode 100755 diff --git a/README.md b/README.md index 7c09eb597b..30daa919d3 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,11 @@ Change history can be found in [`HISTORY.md`](https://github.com/mongodb/node-mo ### Compatibility -For server and runtime version compatibility matrices, please refer to the following links: +The driver currently supports 3.6+ servers. + +** 3.6 support is deprecated and support will be removed in a future version ** + +For exhaustive server and runtime version compatibility matrices, please refer to the following links: - [MongoDB](https://www.mongodb.com/docs/drivers/node/current/compatibility/#mongodb-compatibility) - [NodeJS](https://www.mongodb.com/docs/drivers/node/current/compatibility/#language-compatibility) diff --git a/src/bulk/common.ts b/src/bulk/common.ts index ad0451e9ac..1a79dd6b1e 100644 --- a/src/bulk/common.ts +++ b/src/bulk/common.ts @@ -616,8 +616,8 @@ function handleMongoWriteConcernError( callback( new MongoBulkWriteError( { - message: err.result?.writeConcernError.errmsg, - code: err.result?.writeConcernError.result + message: err.result.writeConcernError.errmsg, + code: err.result.writeConcernError.code }, new BulkWriteResult(bulkResult, isOrdered) ) diff --git a/src/client-side-encryption/auto_encrypter.ts b/src/client-side-encryption/auto_encrypter.ts index 3066b8d1f0..5ac3945f5e 100644 --- a/src/client-side-encryption/auto_encrypter.ts +++ b/src/client-side-encryption/auto_encrypter.ts @@ -3,6 +3,7 @@ import { type MongoCryptConstructor, type MongoCryptOptions } from 'mongodb-client-encryption'; +import * as net from 'net'; import { deserialize, type Document, serialize } from '../bson'; import { type CommandOptions, type ProxyOptions } from '../cmap/connection'; @@ -11,6 +12,7 @@ import { getMongoDBClientEncryption } from '../deps'; import { MongoRuntimeError } from '../error'; import { MongoClient, type MongoClientOptions } from '../mongo_client'; import { MongoDBCollectionNamespace } from '../utils'; +import { autoSelectSocketOptions } from './client_encryption'; import * as cryptoCallbacks from './crypto_callbacks'; import { MongoCryptInvalidArgumentError } from './errors'; import { MongocryptdManager } from './mongocryptd_manager'; @@ -297,10 +299,20 @@ export class AutoEncrypter { serverSelectionTimeoutMS: 10000 }; - if (options.extraOptions == null || typeof options.extraOptions.mongocryptdURI !== 'string') { + if ( + (options.extraOptions == null || typeof options.extraOptions.mongocryptdURI !== 'string') && + !net.getDefaultAutoSelectFamily + ) { + // Only set family if autoSelectFamily options are not supported. clientOptions.family = 4; } + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore: TS complains as this always returns true on versions where it is present. + if (net.getDefaultAutoSelectFamily) { + Object.assign(clientOptions, autoSelectSocketOptions(this._client.options)); + } + this._mongocryptdClient = new MongoClient(this._mongocryptdManager.uri, clientOptions); } } @@ -379,7 +391,8 @@ export class AutoEncrypter { promoteValues: false, promoteLongs: false, proxyOptions: this._proxyOptions, - tlsOptions: this._tlsOptions + tlsOptions: this._tlsOptions, + socketOptions: autoSelectSocketOptions(this._client.options) }); return deserialize(await stateMachine.execute(this, context), { @@ -399,7 +412,8 @@ export class AutoEncrypter { const stateMachine = new StateMachine({ ...options, proxyOptions: this._proxyOptions, - tlsOptions: this._tlsOptions + tlsOptions: this._tlsOptions, + socketOptions: autoSelectSocketOptions(this._client.options) }); return await stateMachine.execute(this, context); diff --git a/src/client-side-encryption/client_encryption.ts b/src/client-side-encryption/client_encryption.ts index b78b354996..03d2ff2de2 100644 --- a/src/client-side-encryption/client_encryption.ts +++ b/src/client-side-encryption/client_encryption.ts @@ -12,7 +12,7 @@ import { type Collection } from '../collection'; import { type FindCursor } from '../cursor/find_cursor'; import { type Db } from '../db'; import { getMongoDBClientEncryption } from '../deps'; -import { type MongoClient } from '../mongo_client'; +import { type MongoClient, type MongoClientOptions } from '../mongo_client'; import { type Filter, type WithId } from '../mongo_types'; import { type CreateCollectionOptions } from '../operations/create_collection'; import { type DeleteResult } from '../operations/delete'; @@ -28,7 +28,11 @@ import { type KMSProviders, refreshKMSCredentials } from './providers/index'; -import { type CSFLEKMSTlsOptions, StateMachine } from './state_machine'; +import { + type ClientEncryptionSocketOptions, + type CSFLEKMSTlsOptions, + StateMachine +} from './state_machine'; /** * @public @@ -199,7 +203,8 @@ export class ClientEncryption { const stateMachine = new StateMachine({ proxyOptions: this._proxyOptions, - tlsOptions: this._tlsOptions + tlsOptions: this._tlsOptions, + socketOptions: autoSelectSocketOptions(this._client.options) }); const dataKey = deserialize(await stateMachine.execute(this, context)) as DataKey; @@ -256,7 +261,8 @@ export class ClientEncryption { const context = this._mongoCrypt.makeRewrapManyDataKeyContext(filterBson, keyEncryptionKeyBson); const stateMachine = new StateMachine({ proxyOptions: this._proxyOptions, - tlsOptions: this._tlsOptions + tlsOptions: this._tlsOptions, + socketOptions: autoSelectSocketOptions(this._client.options) }); const { v: dataKeys } = deserialize(await stateMachine.execute(this, context)); @@ -637,7 +643,8 @@ export class ClientEncryption { const stateMachine = new StateMachine({ proxyOptions: this._proxyOptions, - tlsOptions: this._tlsOptions + tlsOptions: this._tlsOptions, + socketOptions: autoSelectSocketOptions(this._client.options) }); const { v } = deserialize(await stateMachine.execute(this, context)); @@ -715,7 +722,8 @@ export class ClientEncryption { const valueBuffer = serialize({ v: value }); const stateMachine = new StateMachine({ proxyOptions: this._proxyOptions, - tlsOptions: this._tlsOptions + tlsOptions: this._tlsOptions, + socketOptions: autoSelectSocketOptions(this._client.options) }); const context = this._mongoCrypt.makeExplicitEncryptionContext(valueBuffer, contextOptions); @@ -957,3 +965,21 @@ export interface RangeOptions { sparsity: Long; precision?: number; } + +/** + * Get the socket options from the client. + * @param baseOptions - The mongo client options. + * @returns ClientEncryptionSocketOptions + */ +export function autoSelectSocketOptions( + baseOptions: MongoClientOptions +): ClientEncryptionSocketOptions { + const options: ClientEncryptionSocketOptions = { autoSelectFamily: true }; + if ('autoSelectFamily' in baseOptions) { + options.autoSelectFamily = baseOptions.autoSelectFamily; + } + if ('autoSelectFamilyAttemptTimeout' in baseOptions) { + options.autoSelectFamilyAttemptTimeout = baseOptions.autoSelectFamilyAttemptTimeout; + } + return options; +} diff --git a/src/client-side-encryption/state_machine.ts b/src/client-side-encryption/state_machine.ts index f0ae19546a..af3ea4c215 100644 --- a/src/client-side-encryption/state_machine.ts +++ b/src/client-side-encryption/state_machine.ts @@ -14,7 +14,7 @@ import { type ProxyOptions } from '../cmap/connection'; import { getSocks, type SocksLib } from '../deps'; import { type MongoClient, type MongoClientOptions } from '../mongo_client'; import { BufferPool, MongoDBCollectionNamespace, promiseWithResolvers } from '../utils'; -import { type DataKey } from './client_encryption'; +import { autoSelectSocketOptions, type DataKey } from './client_encryption'; import { MongoCryptError } from './errors'; import { type MongocryptdManager } from './mongocryptd_manager'; import { type KMSProviders } from './providers'; @@ -114,6 +114,16 @@ export type CSFLEKMSTlsOptions = { [key: string]: ClientEncryptionTlsOptions | undefined; }; +/** + * @public + * + * Socket options to use for KMS requests. + */ +export type ClientEncryptionSocketOptions = Pick< + MongoClientOptions, + 'autoSelectFamily' | 'autoSelectFamilyAttemptTimeout' +>; + /** * This is kind of a hack. For `rewrapManyDataKey`, we have tests that * guarantee that when there are no matching keys, `rewrapManyDataKey` returns @@ -153,6 +163,9 @@ export type StateMachineOptions = { /** TLS options for KMS requests, if set. */ tlsOptions: CSFLEKMSTlsOptions; + + /** Socket specific options we support. */ + socketOptions: ClientEncryptionSocketOptions; } & Pick; /** @@ -289,10 +302,17 @@ export class StateMachine { async kmsRequest(request: MongoCryptKMSRequest): Promise { const parsedUrl = request.endpoint.split(':'); const port = parsedUrl[1] != null ? Number.parseInt(parsedUrl[1], 10) : HTTPS_PORT; - const options: tls.ConnectionOptions & { host: string; port: number } = { + const socketOptions = autoSelectSocketOptions(this.options.socketOptions || {}); + const options: tls.ConnectionOptions & { + host: string; + port: number; + autoSelectFamily?: boolean; + autoSelectFamilyAttemptTimeout?: number; + } = { host: parsedUrl[0], servername: parsedUrl[0], - port + port, + ...socketOptions }; const message = request.message; const buffer = new BufferPool(); @@ -351,10 +371,12 @@ export class StateMachine { try { if (this.options.proxyOptions && this.options.proxyOptions.proxyHost) { - netSocket.connect({ + const netSocketOptions = { host: this.options.proxyOptions.proxyHost, - port: this.options.proxyOptions.proxyPort || 1080 - }); + port: this.options.proxyOptions.proxyPort || 1080, + ...socketOptions + }; + netSocket.connect(netSocketOptions); await willConnect; try { diff --git a/src/cmap/connect.ts b/src/cmap/connect.ts index e319dbbed9..b2ec3caabf 100644 --- a/src/cmap/connect.ts +++ b/src/cmap/connect.ts @@ -164,7 +164,7 @@ export async function performInitialHandshake( } catch (error) { if (error instanceof MongoError) { error.addErrorLabel(MongoErrorLabel.HandshakeError); - if (needsRetryableWriteLabel(error, response.maxWireVersion)) { + if (needsRetryableWriteLabel(error, response.maxWireVersion, conn.description.type)) { error.addErrorLabel(MongoErrorLabel.RetryableWriteError); } } @@ -269,6 +269,8 @@ export const LEGAL_TLS_SOCKET_OPTIONS = [ /** @public */ export const LEGAL_TCP_SOCKET_OPTIONS = [ + 'autoSelectFamily', + 'autoSelectFamilyAttemptTimeout', 'family', 'hints', 'localAddress', diff --git a/src/connection_string.ts b/src/connection_string.ts index b0becafac0..bf9acf556c 100644 --- a/src/connection_string.ts +++ b/src/connection_string.ts @@ -740,6 +740,13 @@ export const OPTIONS = { autoEncryption: { type: 'record' }, + autoSelectFamily: { + type: 'boolean', + default: true + }, + autoSelectFamilyAttemptTimeout: { + type: 'uint' + }, bsonRegExp: { type: 'boolean' }, diff --git a/src/error.ts b/src/error.ts index 938ce715ff..5ce02c82ab 100644 --- a/src/error.ts +++ b/src/error.ts @@ -1,4 +1,5 @@ import type { Document } from './bson'; +import type { ServerType } from './sdam/common'; import type { TopologyVersion } from './sdam/server_description'; import type { TopologyDescription } from './sdam/topology_description'; @@ -1158,6 +1159,23 @@ export class MongoServerSelectionError extends MongoSystemError { } } +/** + * The type of the result property of MongoWriteConcernError + * @public + */ +export interface WriteConcernErrorResult { + writeConcernError: { + code: number; + errmsg: string; + codeName?: string; + errInfo?: Document; + }; + ok: number; + code?: number; + errorLabels?: string[]; + [x: string | number]: unknown; +} + /** * An error thrown when the server reports a writeConcernError * @public @@ -1178,16 +1196,8 @@ export class MongoWriteConcernError extends MongoServerError { * * @public **/ - constructor(result: { - writeConcernError: { - code: number; - errmsg: string; - codeName?: string; - errInfo?: Document; - }; - errorLabels?: string[]; - }) { - super({ ...result, ...result.writeConcernError }); + constructor(result: WriteConcernErrorResult) { + super({ ...result.writeConcernError, ...result }); this.errInfo = result.writeConcernError.errInfo; this.result = result; } @@ -1217,7 +1227,11 @@ const RETRYABLE_READ_ERROR_CODES = new Set([ // see: https://github.com/mongodb/specifications/blob/master/source/retryable-writes/retryable-writes.rst#terms const RETRYABLE_WRITE_ERROR_CODES = RETRYABLE_READ_ERROR_CODES; -export function needsRetryableWriteLabel(error: Error, maxWireVersion: number): boolean { +export function needsRetryableWriteLabel( + error: Error, + maxWireVersion: number, + serverType: ServerType +): boolean { // pre-4.4 server, then the driver adds an error label for every valid case // execute operation will only inspect the label, code/message logic is handled here if (error instanceof MongoNetworkError) { @@ -1237,11 +1251,17 @@ export function needsRetryableWriteLabel(error: Error, maxWireVersion: number): } if (error instanceof MongoWriteConcernError) { - return RETRYABLE_WRITE_ERROR_CODES.has(error.result?.code ?? error.code ?? 0); + if (serverType === 'Mongos' && maxWireVersion < 9) { + // use original top-level code from server response + return RETRYABLE_WRITE_ERROR_CODES.has(error.result.code ?? 0); + } + return RETRYABLE_WRITE_ERROR_CODES.has( + error.result.writeConcernError.code ?? Number(error.code) ?? 0 + ); } - if (error instanceof MongoError && typeof error.code === 'number') { - return RETRYABLE_WRITE_ERROR_CODES.has(error.code); + if (error instanceof MongoError) { + return RETRYABLE_WRITE_ERROR_CODES.has(Number(error.code)); } const isNotWritablePrimaryError = LEGACY_NOT_WRITABLE_PRIMARY_ERROR_MESSAGE.test(error.message); diff --git a/src/gridfs/download.ts b/src/gridfs/download.ts index 6b0fc57fc6..7d2a7b2ee3 100644 --- a/src/gridfs/download.ts +++ b/src/gridfs/download.ts @@ -56,15 +56,41 @@ export interface GridFSFile { /** @internal */ export interface GridFSBucketReadStreamPrivate { + /** + * The running total number of bytes read from the chunks collection. + */ bytesRead: number; + /** + * The number of bytes to remove from the last chunk read in the file. This is non-zero + * if `end` is not equal to the length of the document and `end` is not a multiple + * of the chunkSize. + */ bytesToTrim: number; + + /** + * The number of bytes to remove from the first chunk read in the file. This is non-zero + * if `start` is not equal to the 0 and `start` is not a multiple + * of the chunkSize. + */ bytesToSkip: number; + + files: Collection; chunks: Collection; cursor?: FindCursor; + + /** The running total number of chunks read from the chunks collection. */ expected: number; - files: Collection; + + /** + * The filter used to search in the _files_ collection (i.e., `{ _id: <> }`) + * This is not the same filter used when reading chunks from the chunks collection. + */ filter: Document; + + /** Indicates whether or not download has started. */ init: boolean; + + /** The expected number of chunks to read, calculated from start, end, chunkSize and file length. */ expectedEnd: number; file?: GridFSFile; options: { diff --git a/src/index.ts b/src/index.ts index 08869f04c5..19b2359379 100644 --- a/src/index.ts +++ b/src/index.ts @@ -73,7 +73,8 @@ export { MongoTopologyClosedError, MongoTransactionError, MongoUnexpectedServerResponseError, - MongoWriteConcernError + MongoWriteConcernError, + WriteConcernErrorResult } from './error'; export { configureExplicitResourceManagement } from './resource_management'; export { @@ -248,6 +249,7 @@ export type { LocalKMSProviderConfiguration } from './client-side-encryption/providers/index'; export type { + ClientEncryptionSocketOptions, ClientEncryptionTlsOptions, CSFLEKMSTlsOptions, StateMachineExecutable diff --git a/src/mongo_client.ts b/src/mongo_client.ts index 853df569d1..db16e556c1 100644 --- a/src/mongo_client.ts +++ b/src/mongo_client.ts @@ -105,7 +105,7 @@ export type SupportedTLSSocketOptions = Pick< /** @public */ export type SupportedSocketOptions = Pick< - TcpNetConnectOpts, + TcpNetConnectOpts & { autoSelectFamily?: boolean; autoSelectFamilyAttemptTimeout?: number }, (typeof LEGAL_TCP_SOCKET_OPTIONS)[number] >; diff --git a/src/operations/find_and_modify.ts b/src/operations/find_and_modify.ts index c295fcb0a8..2df4fefe3e 100644 --- a/src/operations/find_and_modify.ts +++ b/src/operations/find_and_modify.ts @@ -192,12 +192,7 @@ export class FindAndModifyOperation extends CommandOperation { ...this.cmdBase }; - // Have we specified collation - try { - decorateWithCollation(cmd, coll, options); - } catch (err) { - return err; - } + decorateWithCollation(cmd, coll, options); if (options.hint) { // TODO: once this method becomes a CommandOperation we will have the server diff --git a/src/sdam/server.ts b/src/sdam/server.ts index 59a7231b4f..b4450f0072 100644 --- a/src/sdam/server.ts +++ b/src/sdam/server.ts @@ -453,7 +453,7 @@ export class Server extends TypedEventEmitter { } else { if ( (isRetryableWritesEnabled(this.topology) || isTransactionCommand(cmd)) && - needsRetryableWriteLabel(error, maxWireVersion(this)) && + needsRetryableWriteLabel(error, maxWireVersion(this), this.description.type) && !inActiveTransaction(session, cmd) ) { error.addErrorLabel(MongoErrorLabel.RetryableWriteError); diff --git a/test/integration/crud/crud.spec.test.ts b/test/integration/crud/crud.spec.test.ts index 4b43d49a5d..0d9ac6c09e 100644 --- a/test/integration/crud/crud.spec.test.ts +++ b/test/integration/crud/crud.spec.test.ts @@ -1,425 +1,71 @@ -import { expect } from 'chai'; -import * as fs from 'fs'; import * as path from 'path'; import { loadSpecTests } from '../../spec/index'; import { runUnifiedSuite } from '../../tools/unified-spec-runner/runner'; -function enforceServerVersionLimits(requires, scenario) { - const versionLimits: string[] = []; - if (scenario.minServerVersion) { - versionLimits.push(`>=${scenario.minServerVersion}`); - } - if (scenario.maxServerVersion) { - versionLimits.push(`<=${scenario.maxServerVersion}`); - } - if (versionLimits.length) { - requires.mongodb = versionLimits.join(' '); - } - if (scenario.serverless) { - requires.serverless = scenario.serverless; - } -} - -function findScenarios(...args: string[]) { - const route = [__dirname, '..', '..', 'spec', 'crud'].concat(Array.from(args)); - return fs - .readdirSync(path.resolve(...route)) - .filter(x => x.indexOf('json') !== -1) - .map(x => [x, fs.readFileSync(path.resolve(...route.concat([x])), 'utf8')]) - .map(x => [path.basename(x[0], '.json'), JSON.parse(x[1])]); -} - -const readScenarios = findScenarios('v1', 'read'); -const writeScenarios = findScenarios('v1', 'write'); - -const testContext = {}; -describe('CRUD spec v1', function () { - beforeEach(function () { - const configuration = this.configuration; - const client = configuration.newClient(); - return client.connect().then(client => { - testContext.client = client; - testContext.db = client.db(configuration.db); - }); - }); - - afterEach(() => { - if (testContext.client) { - return testContext.client.close(); - } - }); - - describe('read', function () { - readScenarios.forEach(scenarioData => { - const scenarioName = scenarioData[0]; - const scenario = scenarioData[1]; - scenario.name = scenarioName; - - const metadata = { - requires: { - topology: ['single', 'replicaset', 'sharded'] - } - }; - - enforceServerVersionLimits(metadata.requires, scenario); - - describe(scenarioName, function () { - scenario.tests.forEach(scenarioTest => { - beforeEach(() => testContext.db.dropDatabase()); - it(scenarioTest.description, { - metadata, - test: function () { - return executeScenario(scenario, scenarioTest, this.configuration, testContext); - } - }); - }); - }); - }); - }); - - describe('write', function () { - writeScenarios.forEach(scenarioData => { - const scenarioName = scenarioData[0]; - const scenario = scenarioData[1]; - scenario.name = scenarioName; - - const metadata = { - requires: { - topology: ['single', 'replicaset', 'sharded'] - } - }; - - enforceServerVersionLimits(metadata.requires, scenario); - - describe(scenarioName, function () { - beforeEach(() => testContext.db.dropDatabase()); - - scenario.tests.forEach(scenarioTest => { - it(scenarioTest.description, { - metadata, - test: function () { - return executeScenario(scenario, scenarioTest, this.configuration, testContext); - } - }); - }); - }); - }); - }); - - function invert(promise) { - return promise.then( - () => { - throw new Error('Expected operation to throw an error'); - }, - e => e - ); - } - - function assertWriteExpectations(collection, outcome) { - return function (result) { - Object.keys(outcome.result).forEach(resultName => { - expect(result).to.have.property(resultName); - expect(result[resultName]).to.containSubset(outcome.result[resultName]); - }); - - if (collection && outcome.collection && outcome.collection.data) { - return collection - .find({}) - .toArray() - .then(results => { - expect(results).to.containSubset(outcome.collection.data); - }); - } - }; - } - - function assertReadExpectations(db, collection, outcome) { - return function (result) { - if (outcome.result && !outcome.collection) { - expect(result).to.containSubset(outcome.result); - } - - if (collection && outcome.collection) { - if (outcome.collection.name) { - return db - .collection(outcome.collection.name) - .find({}) - .toArray() - .then(collectionResults => { - expect(collectionResults).to.containSubset(outcome.collection.data); - }); - } - - return collection - .find({}) - .toArray() - .then(results => { - expect(results).to.containSubset(outcome.collection.data); - }); - } - }; - } - - function executeAggregateTest(scenarioTest, db, collection) { - const options = {}; - if (scenarioTest.operation.arguments.collation) { - options.collation = scenarioTest.operation.arguments.collation; - } - - const pipeline = scenarioTest.operation.arguments.pipeline; - return collection - .aggregate(pipeline, options) - .toArray() - .then(assertReadExpectations(db, collection, scenarioTest.outcome)); - } - - function executeCountTest(scenarioTest, db, collection) { - const args = scenarioTest.operation.arguments; - const filter = args.filter; - const options = Object.assign({}, args); - delete options.filter; - - return collection - .count(filter, options) - .then(assertReadExpectations(db, collection, scenarioTest.outcome)); - } - - function executeCountDocumentsTest(scenarioTest, db, collection) { - const args = scenarioTest.operation.arguments; - const filter = args.filter; - const options = Object.assign({}, args); - delete options.filter; - - return collection - .countDocuments(filter, options) - .then(assertReadExpectations(db, collection, scenarioTest.outcome)); - } - - function executeEstimatedDocumentCountTest(scenarioTest, db, collection) { - const args = scenarioTest.operation.arguments; - const options = Object.assign({}, args); - delete options.filter; - - return collection - .estimatedDocumentCount(options) - .then(assertReadExpectations(db, collection, scenarioTest.outcome)); - } - - function executeDistinctTest(scenarioTest, db, collection) { - const args = scenarioTest.operation.arguments; - const fieldName = args.fieldName; - const options = Object.assign({}, args); - const filter = args.filter || {}; - delete options.fieldName; - delete options.filter; - - return collection - .distinct(fieldName, filter, options) - .then(assertReadExpectations(db, collection, scenarioTest.outcome)); - } - - function executeFindTest(scenarioTest, db, collection) { - const args = scenarioTest.operation.arguments; - const filter = args.filter; - const options = Object.assign({}, args); - delete options.filter; - - return collection - .find(filter, options) - .toArray() - .then(assertReadExpectations(db, collection, scenarioTest.outcome)); - } - - function executeDeleteTest(scenarioTest, db, collection) { - // Unpack the scenario test - const args = scenarioTest.operation.arguments; - const filter = args.filter; - const options = Object.assign({}, args); - delete options.filter; - - return collection[scenarioTest.operation.name](filter, options).then( - assertWriteExpectations(collection, scenarioTest.outcome) - ); - } - - function executeInsertTest(scenarioTest, db, collection) { - const args = scenarioTest.operation.arguments; - const documents = args.document || args.documents; - const options = Object.assign({}, args.options); - delete options.document; - delete options.documents; - - let promise = collection[scenarioTest.operation.name](documents, options); - - const outcome = scenarioTest.outcome; - if (outcome.error) { - promise = invert(promise); - } - - return promise.then(assertWriteExpectations(collection, scenarioTest.outcome)); - } - - function executeBulkTest(scenarioTest, db, collection) { - const args = scenarioTest.operation.arguments; - const operations = args.requests.map(operation => { - const op = {}; - op[operation.name] = operation['arguments']; - if (operation['arguments'].collation) { - op.collation = operation['arguments'].collation; - } - return op; - }); - const options = Object.assign({}, args.options); - - let promise = collection.bulkWrite(operations, options); - - const outcome = scenarioTest.outcome; - if (outcome.error) { - promise = invert(promise); - } - - return promise.then(assertWriteExpectations(collection, scenarioTest.outcome)); - } - - function executeReplaceTest(scenarioTest, db, collection) { - const args = scenarioTest.operation.arguments; - const filter = args.filter; - const replacement = args.replacement; - const options = Object.assign({}, args); - delete options.filter; - delete options.replacement; - const opName = scenarioTest.operation.name; - - // Get the results - return collection[opName](filter, replacement, options).then( - assertWriteExpectations(collection, scenarioTest.outcome) - ); - } - - function executeUpdateTest(scenarioTest, db, collection) { - const args = scenarioTest.operation.arguments; - const filter = args.filter; - const update = args.update; - const options = Object.assign({}, args); - delete options.filter; - delete options.update; - - return collection[scenarioTest.operation.name](filter, update, options).then( - assertWriteExpectations(collection, scenarioTest.outcome) - ); - } - - function executeFindOneTest(scenarioTest, db, collection) { - const args = scenarioTest.operation.arguments; - const filter = args.filter; - const second = args.update || args.replacement; - const options = Object.assign({}, args); - if (options.returnDocument) { - options.returnDocument = options.returnDocument.toLowerCase(); - } - - delete options.filter; - delete options.update; - delete options.replacement; - - const opName = scenarioTest.operation.name; - const findPromise = - opName === 'findOneAndDelete' - ? collection[opName](filter, options) - : collection[opName](filter, second, options); - - return findPromise.then(assertReadExpectations(db, collection, scenarioTest.outcome)); - } - - function executeScenario(scenario, scenarioTest, configuration, context) { - const collection = context.db.collection( - 'crud_spec_tests_' + scenario.name + '_' + scenarioTest.operation.name - ); - - const errorHandler = err => { - if (!err.message.match(/ns not found/)) throw err; - }; - - const dropPromises = []; - dropPromises.push(collection.drop().catch(errorHandler)); - if (scenarioTest.outcome.collection && scenarioTest.outcome.collection.name) { - dropPromises.push( - context.db.collection(scenarioTest.outcome.collection.name).drop().catch(errorHandler) - ); - } - - function promiseTry(callback) { - return new Promise((resolve, reject) => { - try { - resolve(callback()); - } catch (e) { - reject(e); - } - }); - } - - const outcome = scenarioTest.outcome; - return Promise.all(dropPromises) - .then(() => - scenario.data && scenario.data.length - ? collection.insertMany(scenario.data) - : Promise.resolve() - ) - .then(() => - promiseTry(() => { - switch (scenarioTest.operation.name) { - case 'aggregate': - return executeAggregateTest(scenarioTest, context.db, collection); - case 'count': - return executeCountTest(scenarioTest, context.db, collection); - case 'countDocuments': - return executeCountDocumentsTest(scenarioTest, context.db, collection); - case 'estimatedDocumentCount': - return executeEstimatedDocumentCountTest(scenarioTest, context.db, collection); - case 'distinct': - return executeDistinctTest(scenarioTest, context.db, collection); - case 'find': - return executeFindTest(scenarioTest, context.db, collection); - case 'deleteOne': - case 'deleteMany': - return executeDeleteTest(scenarioTest, context.db, collection); - case 'replaceOne': - return executeReplaceTest(scenarioTest, context.db, collection); - case 'updateOne': - case 'updateMany': - return executeUpdateTest(scenarioTest, context.db, collection); - case 'findOneAndReplace': - case 'findOneAndUpdate': - case 'findOneAndDelete': - return executeFindOneTest(scenarioTest, context.db, collection); - case 'insertOne': - case 'insertMany': - return executeInsertTest(scenarioTest, context.db, collection); - case 'bulkWrite': - return executeBulkTest(scenarioTest, context.db, collection); - } - }) - ) - .then( - () => { - if ( - outcome.error === true && - scenarioTest.operation.name !== 'bulkWrite' && - scenarioTest.operation.name !== 'insertMany' - ) { - throw new Error('Error expected!'); - } - }, - err => { - if (outcome && (outcome.error == null || outcome.error === false)) { - throw err; - } - } - ); - } -}); +const clientBulkWriteTests = new RegExp( + [ + 'client bulk write delete with collation', + 'client bulk write delete with hint', + 'client bulkWrite operations support errorResponse assertions', + 'an individual operation fails during an ordered bulkWrite', + 'an individual operation fails during an unordered bulkWrite', + 'detailed results are omitted from error when verboseResults is false', + 'a top-level failure occurs during a bulkWrite', + 'a bulk write with only errors does not report a partial result', + 'an empty list of write models is a client-side error', + 'a write concern error occurs during a bulkWrite', + 'client bulkWrite' + ].join('|') +); + +const unacknowledgedHintTests = [ + 'Unacknowledged updateOne with hint document on 4.2+ server', + 'Unacknowledged updateOne with hint string on 4.2+ server', + 'Unacknowledged updateMany with hint document on 4.2+ server', + 'Unacknowledged updateMany with hint string on 4.2+ server', + 'Unacknowledged replaceOne with hint document on 4.2+ server', + 'Unacknowledged replaceOne with hint string on 4.2+ server', + 'Unacknowledged updateOne with hint document on 4.2+ server', + 'Unacknowledged updateOne with hint string on 4.2+ server', + 'Unacknowledged updateMany with hint document on 4.2+ server', + 'Unacknowledged updateMany with hint string on 4.2+ server', + 'Unacknowledged replaceOne with hint document on 4.2+ server', + 'Unacknowledged replaceOne with hint string on 4.2+ server', + 'Unacknowledged findOneAndUpdate with hint document on 4.4+ server', + 'Unacknowledged findOneAndUpdate with hint string on 4.4+ server', + 'Unacknowledged findOneAndReplace with hint document on 4.4+ server', + 'Unacknowledged findOneAndReplace with hint string on 4.4+ server', + 'Unacknowledged findOneAndDelete with hint document on 4.4+ server', + 'Unacknowledged findOneAndDelete with hint string on 4.4+ server', + 'Unacknowledged deleteOne with hint document on 4.4+ server', + 'Unacknowledged deleteOne with hint string on 4.4+ server', + 'Unacknowledged deleteMany with hint document on 4.4+ server', + 'Unacknowledged deleteMany with hint string on 4.4+ server', + 'Unacknowledged deleteOne with hint document on 4.4+ server', + 'Unacknowledged deleteOne with hint string on 4.4+ server', + 'Unacknowledged deleteMany with hint document on 4.4+ server', + 'Unacknowledged deleteMany with hint string on 4.4+ server' +]; + +const loadBalancedCollationTests = [ + 'FindOneAndUpdate when many documents match with collation returning the document before modification', + 'FindOneAndReplace when one document matches with collation returning the document after modification', + 'FindOneAndDelete when one document matches with collation', + 'Distinct with a collation' +]; describe('CRUD unified', function () { - runUnifiedSuite(loadSpecTests(path.join('crud', 'unified'))); + runUnifiedSuite( + loadSpecTests(path.join('crud', 'unified')), + ({ description }, { isLoadBalanced }) => { + return description.match(clientBulkWriteTests) + ? 'TODO(NODE-6257): implement client level bulk write' + : unacknowledgedHintTests.includes(description) + ? `TODO(NODE-3541)` + : isLoadBalanced && loadBalancedCollationTests.includes(description) + ? `TODO(NODE-6280): fix collation for find and modify commands on load balanced mode` + : false; + } + ); }); diff --git a/test/integration/gridfs/gridfs.spec.test.js b/test/integration/gridfs/gridfs.spec.test.js deleted file mode 100644 index 6bde9ff6e5..0000000000 --- a/test/integration/gridfs/gridfs.spec.test.js +++ /dev/null @@ -1,235 +0,0 @@ -'use strict'; - -const { EJSON } = require('bson'); -const { expect } = require('chai'); -const { once } = require('node:events'); -const { GridFSBucket } = require('../../mongodb'); - -describe('GridFS spec', function () { - let client; - let db; - - beforeEach(async function () { - client = this.configuration.newClient(); - db = client.db('gridfs_spec_tests'); - }); - - afterEach(async function () { - await db.dropDatabase().catch(() => null); - await client.close(); - }); - - const UPLOAD_SPEC = require('../../spec/gridfs/gridfs-upload.json'); - - for (const testSpec of UPLOAD_SPEC.tests) { - it(testSpec.description, async function () { - const bucket = new GridFSBucket(db, { bucketName: 'expected' }); - - const uploadStream = bucket.openUploadStream( - testSpec.act.arguments.filename, - testSpec.act.arguments.options - ); - - const buf = Buffer.from(testSpec.act.arguments.source.$hex, 'hex'); - - const finished = once(uploadStream, 'finish'); - - uploadStream.write(buf); - uploadStream.end(); - - await finished; - - for (const data of testSpec.assert.data) { - const docs = await db.collection(data.insert).find({}).toArray(); - - expect(data.documents.length).to.equal(docs.length); - for (let i = 0; i < docs.length; ++i) { - testResultDoc(data.documents[i], docs[i], uploadStream.id); - } - } - }); - } - - const DOWNLOAD_SPEC = require('../../spec/gridfs/gridfs-download.json'); - DOWNLOAD_SPEC.tests.forEach(function (specTest) { - (function (testSpec) { - it(testSpec.description, { - metadata: { requires: { topology: ['single'] } }, - - test(done) { - const configuration = this.configuration; - const client = configuration.newClient(configuration.writeConcernMax(), { - maxPoolSize: 1 - }); - client.connect(function (err, client) { - const db = client.db(configuration.db); - db.dropDatabase(function (err) { - expect(err).to.not.exist; - const BUCKET_NAME = 'fs'; - - const _runTest = function () { - const bucket = new GridFSBucket(db, { bucketName: BUCKET_NAME }); - let res = Buffer.alloc(0); - - const download = bucket.openDownloadStream( - EJSON.parse(JSON.stringify(testSpec.act.arguments.id), { relaxed: true }) - ); - - download.on('data', function (chunk) { - res = Buffer.concat([res, chunk]); - }); - - let errorReported = false; - download.on('error', function (error) { - errorReported = true; - if (!testSpec.assert.error) { - expect.fail('Should be unreached'); - - // We need to abort in order to close the underlying cursor, - // and by extension the implicit session used for the cursor. - // This is only necessary if the cursor is not exhausted - download.abort(); - client.close(done); - } - expect(error.toString().indexOf(testSpec.assert.error) !== -1).to.equal(true); - - // We need to abort in order to close the underlying cursor, - // and by extension the implicit session used for the cursor. - // This is only necessary if the cursor is not exhausted - download.abort(); - client.close(done); - }); - - download.on('end', function () { - const result = testSpec.assert.result; - if (!result) { - if (errorReported) { - return; - } - - // We need to abort in order to close the underlying cursor, - // and by extension the implicit session used for the cursor. - // This is only necessary if the cursor is not exhausted - download.abort(); - client.close(done); - expect.fail('errorReported should be set'); - } - - expect(res.toString('hex')).to.equal(result.$hex); - - // We need to abort in order to close the underlying cursor, - // and by extension the implicit session used for the cursor. - // This is only necessary if the cursor is not exhausted - download.abort(); - client.close(done); - }); - }; - - const keys = Object.keys(DOWNLOAD_SPEC.data); - let numCollections = Object.keys(DOWNLOAD_SPEC.data).length; - keys.forEach(function (collection) { - const data = DOWNLOAD_SPEC.data[collection].map(function (v) { - return deflateTestDoc(v); - }); - - db.collection(BUCKET_NAME + '.' + collection).insertMany(data, function (error) { - expect(error).to.not.exist; - - if (--numCollections === 0) { - if (testSpec.arrange) { - // only support 1 arrange op for now - expect(testSpec.arrange.data.length).to.equal(1); - applyArrange(db, deflateTestDoc(testSpec.arrange.data[0]), function (error) { - expect(error).to.not.exist; - _runTest(); - }); - } else { - _runTest(); - } - } - }); - }); - }); - }); - } - }); - })(specTest); - }); - - function testResultDoc(specDoc, resDoc, result) { - const specKeys = Object.keys(specDoc) - .filter(key => key !== 'md5') - .sort(); - const resKeys = Object.keys(resDoc).sort(); - - expect(specKeys.length === resKeys.length).to.equal(true); - - for (let i = 0; i < specKeys.length; ++i) { - const key = specKeys[i]; - expect(specKeys[i]).to.equal(resKeys[i]); - if (specDoc[key] === '*actual') { - expect(resDoc[key]).to.exist; - } else if (specDoc[key] === '*result') { - expect(resDoc[key].toString()).to.equal(result.toString()); - } else if (specDoc[key].$hex) { - expect(resDoc[key]._bsontype === 'Binary').to.equal(true); - expect(resDoc[key].toString('hex')).to.equal(specDoc[key].$hex); - } else { - if (typeof specDoc[key] === 'object') { - expect(specDoc[key]).to.deep.equal(resDoc[key]); - } else { - expect(specDoc[key]).to.equal(resDoc[key]); - } - } - } - } - - function deflateTestDoc(doc) { - const ret = EJSON.parse(JSON.stringify(doc), { relaxed: true }); - convert$hexToBuffer(ret); - return ret; - } - - function convert$hexToBuffer(doc) { - const keys = Object.keys(doc); - keys.forEach(function (key) { - if (doc[key] && typeof doc[key] === 'object') { - if (doc[key].$hex != null) { - doc[key] = Buffer.from(doc[key].$hex, 'hex'); - } else { - convert$hexToBuffer(doc[key]); - } - } - }); - } - - function applyArrange(db, command, callback) { - // Don't count on commands being there since we need to test on 2.2 and 2.4 - if (command.delete) { - if (command.deletes.length !== 1) { - return callback(new Error('can only arrange with 1 delete')); - } - if (command.deletes[0].limit !== 1) { - return callback(new Error('can only arrange with delete limit 1')); - } - db.collection(command.delete).deleteOne(command.deletes[0].q, callback); - } else if (command.insert) { - db.collection(command.insert).insertMany(command.documents, callback); - } else if (command.update) { - const bulk = []; - for (let i = 0; i < command.updates.length; ++i) { - bulk.push({ - updateOne: { - filter: command.updates[i].q, - update: command.updates[i].u - } - }); - } - - db.collection(command.update).bulkWrite(bulk, callback); - } else { - const msg = 'Command not recognized: ' + require('util').inspect(command); - callback(new Error(msg)); - } - } -}); diff --git a/test/integration/gridfs/gridfs.spec.test.ts b/test/integration/gridfs/gridfs.spec.test.ts new file mode 100644 index 0000000000..7e73283cb6 --- /dev/null +++ b/test/integration/gridfs/gridfs.spec.test.ts @@ -0,0 +1,8 @@ +import { loadSpecTests } from '../../spec'; +import { runUnifiedSuite } from '../../tools/unified-spec-runner/runner'; + +describe('GridFS Unified Tests', function () { + runUnifiedSuite(loadSpecTests('gridfs'), ({ description }) => { + return description === 'download when final chunk is missing' ? `TODO(NODE-xxxx)` : false; + }); +}); diff --git a/test/integration/node-specific/mongo_client.test.ts b/test/integration/node-specific/mongo_client.test.ts index b0653a702a..634516f8f7 100644 --- a/test/integration/node-specific/mongo_client.test.ts +++ b/test/integration/node-specific/mongo_client.test.ts @@ -1,5 +1,6 @@ import { expect } from 'chai'; import { once } from 'events'; +import * as net from 'net'; import * as sinon from 'sinon'; import { @@ -721,4 +722,56 @@ describe('class MongoClient', function () { }); }); }); + + context('when connecting', function () { + let netSpy; + + beforeEach(function () { + netSpy = sinon.spy(net, 'createConnection'); + }); + + afterEach(function () { + sinon.restore(); + }); + + context('when auto select options are provided', function () { + beforeEach(function () { + client = this.configuration.newClient({ + autoSelectFamily: false, + autoSelectFamilyAttemptTimeout: 100 + }); + }); + + it('sets the provided options', { + metadata: { requires: { topology: ['single'] } }, + test: async function () { + await client.connect(); + expect(netSpy).to.have.been.calledWith({ + autoSelectFamily: false, + autoSelectFamilyAttemptTimeout: 100, + host: 'localhost', + port: 27017 + }); + } + }); + }); + + context('when auto select options are not provided', function () { + beforeEach(function () { + client = this.configuration.newClient(); + }); + + it('sets the default options', { + metadata: { requires: { topology: ['single'] } }, + test: async function () { + await client.connect(); + expect(netSpy).to.have.been.calledWith({ + autoSelectFamily: true, + host: 'localhost', + port: 27017 + }); + } + }); + }); + }); }); diff --git a/test/integration/read-write-concern/read_write_concern.spec.test.js b/test/integration/read-write-concern/read_write_concern.spec.test.js deleted file mode 100644 index 1374a8e8b4..0000000000 --- a/test/integration/read-write-concern/read_write_concern.spec.test.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -const { TestRunnerContext, generateTopologyTests } = require('../../tools/spec-runner'); -const { loadSpecTests } = require('../../spec'); - -describe('Read Write Concern spec tests', function () { - describe('operation spec tests', function () { - const testContext = new TestRunnerContext(); - const testSuites = loadSpecTests('read-write-concern/operation'); - - after(() => testContext.teardown()); - - before(function () { - return testContext.setup(this.configuration); - }); - - generateTopologyTests(testSuites, testContext, ({ description }) => { - if (description === 'MapReduce omits default write concern') { - return 'The node driver does not have a mapReduce collection helper'; - } - return true; - }); - }); -}); diff --git a/test/integration/read-write-concern/read_write_concern.spec.test.ts b/test/integration/read-write-concern/read_write_concern.spec.test.ts new file mode 100644 index 0000000000..f87c2d4631 --- /dev/null +++ b/test/integration/read-write-concern/read_write_concern.spec.test.ts @@ -0,0 +1,14 @@ +import path = require('path'); +import { loadSpecTests } from '../../spec'; +import { runUnifiedSuite } from '../../tools/unified-spec-runner/runner'; + +describe('Read/Write Concern Unified Tests', function () { + runUnifiedSuite( + loadSpecTests(path.join('read-write-concern', 'operation')), + ({ description }) => { + return description.toLowerCase().includes('mapreduce') + ? 'The node driver does not implement mapReduce.' + : false; + } + ); +}); diff --git a/test/integration/retryable-reads/retryable_reads.spec.test.ts b/test/integration/retryable-reads/retryable_reads.spec.test.ts index 15eb7b97b8..57b325f420 100644 --- a/test/integration/retryable-reads/retryable_reads.spec.test.ts +++ b/test/integration/retryable-reads/retryable_reads.spec.test.ts @@ -1,51 +1,21 @@ import * as path from 'path'; import { loadSpecTests } from '../../spec'; -import { generateTopologyTests, TestRunnerContext } from '../../tools/spec-runner'; import { runUnifiedSuite } from '../../tools/unified-spec-runner/runner'; -describe('Retryable Reads (legacy)', function () { - const testContext = new TestRunnerContext(); - const testSuites = loadSpecTests(path.join('retryable-reads', 'legacy')); - - after(() => testContext.teardown()); - - before(function () { - return testContext.setup(this.configuration); - }); - - generateTopologyTests(testSuites, testContext, spec => { - const shouldRun = - spec.description.match(/distinct/i) || - spec.description.match(/aggregate/i) || - spec.description.match(/countDocuments/i) || - spec.description.match(/listIndexes/i) || - spec.description.match(/listDatabases/i) || - spec.description.match(/listDatabaseNames/i) || - spec.description.match(/listCollections/i) || - spec.description.match(/listCollectionNames/i) || - spec.description.match(/estimatedDocumentCount/i) || - spec.description.match(/count/i) || - spec.description.match(/find/i); - - if (!shouldRun) { - return 'Test skipped by generic filter.'; - } - - return true; - }); -}); - const UNIMPLEMENTED_APIS = [ - 'collection.listIndexNames', - 'database.listCollectionNames', - 'client.listDatabaseNames' + 'listIndexNames', + 'listCollectionNames', + 'listDatabaseNames', + 'mapReduce', + 'listCollectionObjects', + 'listDatabaseObjects' ]; describe('Retryable Reads (unified)', function () { runUnifiedSuite(loadSpecTests(path.join('retryable-reads', 'unified')), ({ description }) => { for (const apiName of UNIMPLEMENTED_APIS) { - if (description.startsWith(apiName)) { + if (description.toLowerCase().includes(apiName.toLowerCase())) { return `The Node.js Driver does not support ${apiName}`; } } diff --git a/test/integration/retryable-writes/retryable_writes.spec.test.ts b/test/integration/retryable-writes/retryable_writes.spec.test.ts index 0ba83bcdb9..1c9e510e4f 100644 --- a/test/integration/retryable-writes/retryable_writes.spec.test.ts +++ b/test/integration/retryable-writes/retryable_writes.spec.test.ts @@ -1,207 +1,24 @@ -import { expect } from 'chai'; import * as path from 'path'; -import type { Collection, Db, MongoClient } from '../../mongodb'; import { loadSpecTests } from '../../spec'; -import { legacyRunOnToRunOnRequirement } from '../../tools/spec-runner'; import { runUnifiedSuite } from '../../tools/unified-spec-runner/runner'; -import { isAnyRequirementSatisfied } from '../../tools/unified-spec-runner/unified-utils'; -interface RetryableWriteTestContext { - client?: MongoClient; - db?: Db; - collection?: Collection; - failPointName?: any; -} - -describe('Legacy Retryable Writes Specs', function () { - let ctx: RetryableWriteTestContext = {}; - - const retryableWrites = loadSpecTests('retryable-writes', 'legacy'); - - for (const suite of retryableWrites) { - describe(suite.name, function () { - beforeEach(async function () { - let utilClient: MongoClient; - if (this.configuration.isLoadBalanced) { - // The util client can always point at the single mongos LB frontend. - utilClient = this.configuration.newClient(this.configuration.singleMongosLoadBalancerUri); - } else { - utilClient = this.configuration.newClient(); - } - - await utilClient.connect(); - - const allRequirements = suite.runOn.map(legacyRunOnToRunOnRequirement); - - const someRequirementMet = - !allRequirements.length || - (await isAnyRequirementSatisfied(this.currentTest.ctx, allRequirements, utilClient)); - - await utilClient.close(); - - if (!someRequirementMet) this.skip(); - }); - - beforeEach(async function () { - // Step 1: Test Setup. Includes a lot of boilerplate stuff - // like creating a client, dropping and refilling data collections, - // and enabling failpoints - const { spec } = this.currentTest; - await executeScenarioSetup(suite, spec, this.configuration, ctx); - }); - - afterEach(async function () { - // Step 3: Test Teardown. Turn off failpoints, and close client - if (!ctx.db || !ctx.client) { - return; - } - - if (ctx.failPointName) { - await turnOffFailPoint(ctx.client, ctx.failPointName); - } - await ctx.client.close(); - ctx = {}; // reset context - }); - for (const spec of suite.tests) { - // Step 2: Run the test - const mochaTest = it(spec.description, async () => await executeScenarioTest(spec, ctx)); - - // A pattern we don't need to repeat for unified tests - // In order to give the beforeEach hook access to the - // spec test so it can be responsible for skipping it - // and executeScenarioSetup - mochaTest.spec = spec; - } - }); - } -}); - -async function executeScenarioSetup(scenario, test, config, ctx) { - const url = config.url(); - const options = { - ...test.clientOptions, - heartbeatFrequencyMS: 100, - monitorCommands: true, - minPoolSize: 10 - }; - - ctx.failPointName = test.failPoint && test.failPoint.configureFailPoint; - - const client = config.newClient(url, options); - await client.connect(); - - ctx.client = client; - ctx.db = client.db(config.db); - ctx.collection = ctx.db.collection(`retryable_writes_test_${config.name}_${test.operation.name}`); - - try { - await ctx.collection.drop(); - } catch (error) { - if (!error.message.match(/ns not found/)) { - throw error; - } - } - - if (Array.isArray(scenario.data) && scenario.data.length) { - await ctx.collection.insertMany(scenario.data); - } - - if (test.failPoint) { - await ctx.client.db('admin').command(test.failPoint); - } -} - -async function executeScenarioTest(test, ctx: RetryableWriteTestContext) { - const args = generateArguments(test); - - // In case the spec files or our API changes - expect(ctx.collection).to.have.property(test.operation.name).that.is.a('function'); - - // TODO(NODE-4033): Collect command started events and assert txn number existence or omission - // have to add logic to handle bulkWrites which emit multiple command started events - const resultOrError = await ctx.collection[test.operation.name](...args).catch(error => error); - - const outcome = test.outcome && test.outcome.result; - const errorLabelsContain = outcome && outcome.errorLabelsContain; - const errorLabelsOmit = outcome && outcome.errorLabelsOmit; - const hasResult = outcome && !errorLabelsContain && !errorLabelsOmit; - if (test.outcome.error) { - const thrownError = resultOrError; - expect(thrownError, `${test.operation.name} was supposed to fail but did not!`).to.exist; - expect(thrownError).to.have.property('message'); - - if (hasResult) { - expect(thrownError.result).to.matchMongoSpec(test.outcome.result); - } - - if (errorLabelsContain) { - expect(thrownError.errorLabels).to.include.members(errorLabelsContain); - } - - if (errorLabelsOmit) { - for (const label of errorLabelsOmit) { - expect(thrownError.errorLabels).to.not.contain(label); - } - } - } else if (test.outcome.result) { - expect(resultOrError, resultOrError.stack).to.not.be.instanceOf(Error); - const result = resultOrError; - const expected = test.outcome.result; - - const actual = result.value ?? result; - // Some of our result classes contain the optional 'acknowledged' property which is - // not part of the test expectations. - for (const property in expected) { - expect(actual).to.have.deep.property(property, expected[property]); - } - } - - if (test.outcome.collection) { - const collectionResults = await ctx.collection.find({}).toArray(); - expect(collectionResults).to.deep.equal(test.outcome.collection.data); - } -} - -// Helper Functions - -/** Transforms the arguments from a test into actual arguments for our function calls */ -function generateArguments(test) { - const args = []; - - if (test.operation.arguments) { - const options: Record = {}; - for (const arg of Object.keys(test.operation.arguments)) { - if (arg === 'requests') { - /** Transforms a request arg into a bulk write operation */ - args.push( - test.operation.arguments[arg].map(({ name, arguments: args }) => ({ [name]: args })) - ); - } else if (arg === 'upsert') { - options.upsert = test.operation.arguments[arg]; - } else if (arg === 'returnDocument') { - options.returnDocument = test.operation.arguments[arg].toLowerCase(); - } else { - args.push(test.operation.arguments[arg]); - } - } - - if (Object.keys(options).length > 0) { - args.push(options); - } - } - - return args; -} - -/** Runs a command that turns off a fail point */ -async function turnOffFailPoint(client, name) { - return await client.db('admin').command({ - configureFailPoint: name, - mode: 'off' - }); -} +const clientBulkWriteTests = [ + 'client bulkWrite with one network error succeeds after retry', + 'client bulkWrite with two network errors fails after retry', + 'client bulkWrite with no multi: true operations succeeds after retryable top-level error', + 'client bulkWrite with multi: true operations fails after retryable top-level error', + 'client bulkWrite with no multi: true operations succeeds after retryable writeConcernError', + 'client bulkWrite with multi: true operations fails after retryable writeConcernError', + 'client bulkWrite with retryWrites: false does not retry', + 'client.clientBulkWrite succeeds after retryable handshake network error', + 'client.clientBulkWrite succeeds after retryable handshake server error (ShutdownInProgress)' +]; describe('Retryable Writes (unified)', function () { - runUnifiedSuite(loadSpecTests(path.join('retryable-writes', 'unified'))); + runUnifiedSuite(loadSpecTests(path.join('retryable-writes', 'unified')), ({ description }) => { + return clientBulkWriteTests.includes(description) + ? `TODO(NODE-6257): implement client-level bulk write.` + : false; + }); }); diff --git a/test/integration/unified-test-format/unified_test_format.spec.test.ts b/test/integration/unified-test-format/unified_test_format.spec.test.ts index 4dd6ff80c0..2080fce98e 100644 --- a/test/integration/unified-test-format/unified_test_format.spec.test.ts +++ b/test/integration/unified-test-format/unified_test_format.spec.test.ts @@ -41,7 +41,11 @@ const filter: TestFilter = ({ description }) => { return false; }; -describe('Unified test format runner', function unifiedTestRunner() { +describe('Unified test format runner (valid-pass)', function unifiedTestRunner() { // Valid tests that should pass runUnifiedSuite(loadSpecTests('unified-test-format/valid-pass'), filter); }); + +describe('Unified test format runner (valid-fail)', function unifiedTestRunner() { + runUnifiedSuite(loadSpecTests('unified-test-format/valid-fail'), () => false, true); +}); diff --git a/test/lambda/mongodb/package-lock.json b/test/lambda/mongodb/package-lock.json index 58b65b9baa..9fb90773a8 100644 --- a/test/lambda/mongodb/package-lock.json +++ b/test/lambda/mongodb/package-lock.json @@ -1,72 +1,58 @@ { - "name": "mongodb", + "name": "mongodb-test-lambda", "version": "1.0.0", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "mongodb", + "name": "mongodb-test-lambda", "version": "1.0.0", - "license": "MIT", + "license": "Apache-2.0", "dependencies": { "mongodb": "mongodb/node-mongodb-native" } }, "node_modules/@mongodb-js/saslprep": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz", - "integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.8.tgz", + "integrity": "sha512-qKwC/M/nNNaKUBMQ0nuzm47b7ZYWQHN3pcXq4IIcoSBc2hOIrflAxJduIvvqmhoz3gR2TacTAs8vlsCVPkiEdQ==", "dependencies": { "sparse-bitfield": "^3.0.3" } }, - "node_modules/@types/node": { - "version": "18.11.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", - "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==" - }, "node_modules/@types/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" }, "node_modules/@types/whatwg-url": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", - "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", + "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", "dependencies": { - "@types/node": "*", "@types/webidl-conversions": "*" } }, "node_modules/bson": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-6.2.0.tgz", - "integrity": "sha512-ID1cI+7bazPDyL9wYy9GaQ8gEEohWvcUl/Yf0dIdutJxnmInEEyCsb4awy/OiBfall7zBA179Pahi3vCdFze3Q==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.8.0.tgz", + "integrity": "sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ==", "engines": { "node": ">=16.20.1" } }, - "node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", - "optional": true, - "peer": true - }, "node_modules/memory-pager": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" }, "node_modules/mongodb": { - "version": "6.1.0", - "resolved": "git+ssh://git@github.com/mongodb/node-mongodb-native.git#0f0b652dde1ecd56b25095c95b7958435c1bdf72", - "license": "Apache-2.0", + "version": "6.8.0", + "resolved": "git+ssh://git@github.com/mongodb/node-mongodb-native.git#74916f297b6f8cc6a7056520cc3520ce2e9ca250", "dependencies": { - "@mongodb-js/saslprep": "^1.1.0", - "bson": "^6.2.0", - "mongodb-connection-string-url": "^2.6.0" + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.7.0", + "mongodb-connection-string-url": "^3.0.0" }, "engines": { "node": ">=16.20.1" @@ -105,48 +91,22 @@ } }, "node_modules/mongodb-connection-string-url": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", - "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz", + "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==", "dependencies": { - "@types/whatwg-url": "^8.2.1", - "whatwg-url": "^11.0.0" + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "engines": { "node": ">=6" } }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "optional": true, - "peer": true, - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "optional": true, - "peer": true, - "dependencies": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" - } - }, "node_modules/sparse-bitfield": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", @@ -156,14 +116,14 @@ } }, "node_modules/tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", "dependencies": { - "punycode": "^2.1.1" + "punycode": "^2.3.0" }, "engines": { - "node": ">=12" + "node": ">=14" } }, "node_modules/webidl-conversions": { @@ -175,132 +135,15 @@ } }, "node_modules/whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", "dependencies": { - "tr46": "^3.0.0", + "tr46": "^4.1.1", "webidl-conversions": "^7.0.0" }, "engines": { - "node": ">=12" - } - } - }, - "dependencies": { - "@mongodb-js/saslprep": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz", - "integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==", - "requires": { - "sparse-bitfield": "^3.0.3" - } - }, - "@types/node": { - "version": "18.11.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", - "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==" - }, - "@types/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" - }, - "@types/whatwg-url": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", - "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", - "requires": { - "@types/node": "*", - "@types/webidl-conversions": "*" - } - }, - "bson": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-6.2.0.tgz", - "integrity": "sha512-ID1cI+7bazPDyL9wYy9GaQ8gEEohWvcUl/Yf0dIdutJxnmInEEyCsb4awy/OiBfall7zBA179Pahi3vCdFze3Q==" - }, - "ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", - "optional": true, - "peer": true - }, - "memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" - }, - "mongodb": { - "version": "git+ssh://git@github.com/mongodb/node-mongodb-native.git#0f0b652dde1ecd56b25095c95b7958435c1bdf72", - "from": "mongodb@mongodb/node-mongodb-native", - "requires": { - "@mongodb-js/saslprep": "^1.1.0", - "bson": "^6.2.0", - "mongodb-connection-string-url": "^2.6.0" - } - }, - "mongodb-connection-string-url": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", - "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", - "requires": { - "@types/whatwg-url": "^8.2.1", - "whatwg-url": "^11.0.0" - } - }, - "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" - }, - "smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "optional": true, - "peer": true - }, - "socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "optional": true, - "peer": true, - "requires": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - } - }, - "sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", - "requires": { - "memory-pager": "^1.0.2" - } - }, - "tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "requires": { - "punycode": "^2.1.1" - } - }, - "webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" - }, - "whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "requires": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" + "node": ">=16" } } } diff --git a/test/manual/atlas-data-lake-testing/atlas_data_lake_testing.spec.js b/test/manual/atlas-data-lake-testing/atlas_data_lake_testing.spec.js deleted file mode 100644 index ecf96cc60d..0000000000 --- a/test/manual/atlas-data-lake-testing/atlas_data_lake_testing.spec.js +++ /dev/null @@ -1,39 +0,0 @@ -'use strict'; -const path = require('path'); -const { installNodeDNSWorkaroundHooks } = require('../../tools/runner/hooks/configuration'); -const { - TestRunnerContext, - gatherTestSuites, - generateTopologyTests -} = require('../../tools/spec-runner'); - -describe('Atlas Data Lake - spec', function () { - const testContext = new TestRunnerContext({ - skipPrepareDatabase: true, - useSessions: false, - user: 'mhuser', - password: 'pencil', - authSource: 'admin' - }); - - const testSuites = gatherTestSuites( - path.resolve(__dirname, '../../spec/atlas-data-lake-testing') - ); - - // These tests timeout connecting to on localhost mongohoused in CI on Node18+. - // Manually setting the ip address resolution is safe for testing purposes - // because in production, mongohoused will never be running on localhost. - installNodeDNSWorkaroundHooks(); - - before(function () { - return testContext.setup(this.configuration); - }); - - after(() => { - testContext.teardown(); - }); - - for (const suite of testSuites) suite.runOn = []; // patched in for the spec runner - - generateTopologyTests(testSuites, testContext); -}); diff --git a/test/manual/atlas-data-lake-testing/atlas_data_lake_testing.spec.ts b/test/manual/atlas-data-lake-testing/atlas_data_lake_testing.spec.ts new file mode 100644 index 0000000000..4b4532e520 --- /dev/null +++ b/test/manual/atlas-data-lake-testing/atlas_data_lake_testing.spec.ts @@ -0,0 +1,8 @@ +import path = require('path'); + +import { loadSpecTests } from '../../spec'; +import { runUnifiedSuite } from '../../tools/unified-spec-runner/runner'; + +describe('Atlas Data Lake Unified Tests', function () { + runUnifiedSuite(loadSpecTests(path.join('atlas-data-lake-testing', 'unified'))); +}); diff --git a/test/manual/mocharc.json b/test/manual/mocharc.json index b52cf660c2..08a1a88d8e 100644 --- a/test/manual/mocharc.json +++ b/test/manual/mocharc.json @@ -1,5 +1,8 @@ { - "require": "ts-node/register", + "require": [ + "ts-node/register", + "test/tools/runner/chai_addons.ts" + ], "reporter": "test/tools/reporter/mongodb_reporter.js", "failZero": true, "color": true, diff --git a/test/manual/tls_support.test.ts b/test/manual/tls_support.test.ts index da89c71046..5359708626 100644 --- a/test/manual/tls_support.test.ts +++ b/test/manual/tls_support.test.ts @@ -1,7 +1,9 @@ import * as process from 'node:process'; +import * as tls from 'node:tls'; import { expect } from 'chai'; import { promises as fs } from 'fs'; +import * as sinon from 'sinon'; import { LEGACY_HELLO_COMMAND, @@ -61,6 +63,63 @@ describe('TLS Support', function () { }); context('when tls filepaths have length > 0', () => { + context('when auto family options are not set', function () { + let tlsSpy; + + afterEach(function () { + sinon.restore(); + }); + + beforeEach(function () { + client = new MongoClient(CONNECTION_STRING, tlsSettings); + tlsSpy = sinon.spy(tls, 'connect'); + }); + + it('sets the default options', async function () { + await client.connect(); + expect(tlsSpy).to.have.been.calledWith({ + autoSelectFamily: true, + host: 'localhost', + port: 27017, + servername: 'localhost', + ca: sinon.match.defined, + cert: sinon.match.defined, + key: sinon.match.defined + }); + }); + }); + + context('when auto family options are set', function () { + let tlsSpy; + + afterEach(function () { + sinon.restore(); + }); + + beforeEach(function () { + client = new MongoClient(CONNECTION_STRING, { + ...tlsSettings, + autoSelectFamily: false, + autoSelectFamilyAttemptTimeout: 100 + }); + tlsSpy = sinon.spy(tls, 'connect'); + }); + + it('sets the provided options', async function () { + await client.connect(); + expect(tlsSpy).to.have.been.calledWith({ + autoSelectFamily: false, + autoSelectFamilyAttemptTimeout: 100, + host: 'localhost', + port: 27017, + servername: 'localhost', + ca: sinon.match.defined, + cert: sinon.match.defined, + key: sinon.match.defined + }); + }); + }); + context('when connection will succeed', () => { beforeEach(async () => { client = new MongoClient(CONNECTION_STRING, tlsSettings); diff --git a/test/spec/atlas-data-lake-testing/README.md b/test/spec/atlas-data-lake-testing/README.md new file mode 100644 index 0000000000..f6ade52de1 --- /dev/null +++ b/test/spec/atlas-data-lake-testing/README.md @@ -0,0 +1,70 @@ +# Atlas Data Lake Tests + +## Introduction + +The YAML and JSON files in this directory are platform-independent tests that drivers can use to assert compatibility +with [Atlas Data Lake](https://www.mongodb.com/docs/datalake/). These tests utilize the +[Unified Test Format](../../unified-test-format/unified-test-format.md). + +Several prose tests, which are not easily expressed in YAML, are also presented in this file. Those tests will need to +be manually implemented by each driver. + +## Test Considerations + +Running these integration tests will require a running `mongohoused` with data available in its `test.driverdata` +collection. See the +[ADL directory in drivers-evergreen-tools](https://github.com/mongodb-labs/drivers-evergreen-tools/tree/master/.evergreen/atlas_data_lake) +and [10gen/mongohouse README](https://github.com/10gen/mongohouse/blob/master/README.md) for more information. + +The test runner for Atlas Data Lake testing MUST NOT drop the collection and/or database under test. In contrast to most +other tests, which insert their own data fixtures into an empty collection, the data for these tests is specified in the +`mongohoused` configuration file. + +Additionally, the test runner MUST NOT execute `killAllSessions` (see: +[Terminating Open Transactions](../../unified-test-format/unified-test-format.md#terminating-open-transactions)) when +connected to Atlas Data Lake. + +## Prose Tests + +The following tests MUST be implemented to fully test compatibility with Atlas Data Lake. + +### 1. Support for `killCursors` command + +Test that the driver properly constructs and issues a +[killCursors](https://www.mongodb.com/docs/manual/reference/command/killCursors/) command to Atlas Data Lake. For this +test, configure an APM listener on a client and execute a query on the `test.driverdata` collection that will leave a +cursor open on the server (e.g. specify `batchSize=2` for a query that would match 3+ documents). Drivers MAY iterate +the cursor if necessary to execute the initial `find` command but MUST NOT iterate further to avoid executing a +`getMore`. + +Observe the CommandSucceededEvent event for the `find` command and extract the cursor's ID and namespace from the +response document's `cursor.id` and `cursor.ns` fields, respectively. Destroy the cursor object and observe a +CommandStartedEvent and CommandSucceededEvent for the `killCursors` command. Assert that the cursor ID and target +namespace in the outgoing command match the values from the `find` command's CommandSucceededEvent. When matching the +namespace, note that the `killCursors` field will contain the collection name and the database may be inferred from +either the `$db` field or accessed via the CommandStartedEvent directly. Finally, assert that the `killCursors` +CommandSucceededEvent indicates that the expected cursor was killed in the `cursorsKilled` field. + +Note: this test assumes that drivers only issue a `killCursors` command internally when destroying a cursor that may +still exist on the server. If a driver constructs and issues `killCursors` commands in other ways (e.g. public API), +this test MUST be adapted to test all such code paths. + +### 2. Connect without authentication + +Test that the driver can establish a connection with Atlas Data Lake without authentication. For these tests, create a +MongoClient using a valid connection string without auth credentials and execute a ping command. + +### 3. Connect with authentication + +Test that the driver can establish a connection with Atlas Data Lake with authentication. For these tests, create a +MongoClient using a valid connection string with SCRAM-SHA-1 and credentials from the drivers-evergreen-tools ADL +configuration and execute a ping command. Repeat this test using SCRAM-SHA-256. + +## Changelog + +- 2024-03-08: Convert legacy ADL tests to unified format. Convert test README from reStructuredText to Markdown. + +- 2022-10-05: Add spec front matter + +- 2020-07-15: Link to CRUD test runner implementation and note that the collection under test must not be dropped before + each test. diff --git a/test/spec/atlas-data-lake-testing/aggregate.json b/test/spec/atlas-data-lake-testing/aggregate.json deleted file mode 100644 index 99995bca41..0000000000 --- a/test/spec/atlas-data-lake-testing/aggregate.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "collection_name": "driverdata", - "database_name": "test", - "tests": [ - { - "description": "Aggregate with pipeline (project, sort, limit)", - "operations": [ - { - "object": "collection", - "name": "aggregate", - "arguments": { - "pipeline": [ - { - "$project": { - "_id": 0 - } - }, - { - "$sort": { - "a": 1 - } - }, - { - "$limit": 2 - } - ] - }, - "result": [ - { - "a": 1, - "b": 2, - "c": 3 - }, - { - "a": 2, - "b": 3, - "c": 4 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "driverdata" - } - } - } - ] - } - ] -} diff --git a/test/spec/atlas-data-lake-testing/aggregate.yml b/test/spec/atlas-data-lake-testing/aggregate.yml deleted file mode 100644 index bbe813987d..0000000000 --- a/test/spec/atlas-data-lake-testing/aggregate.yml +++ /dev/null @@ -1,23 +0,0 @@ -collection_name: &collection_name "driverdata" -database_name: &database_name "test" - -tests: - - - description: "Aggregate with pipeline (project, sort, limit)" - operations: - - - object: collection - name: aggregate - arguments: - pipeline: - - $project: { _id: 0 } - - $sort: { a: 1 } - - $limit: 2 - result: - - { a: 1, b: 2, c: 3 } - - { a: 2, b: 3, c: 4 } - expectations: - - - command_started_event: - command: - aggregate: *collection_name diff --git a/test/spec/atlas-data-lake-testing/estimatedDocumentCount.json b/test/spec/atlas-data-lake-testing/estimatedDocumentCount.json deleted file mode 100644 index 997a3ab3fc..0000000000 --- a/test/spec/atlas-data-lake-testing/estimatedDocumentCount.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "collection_name": "driverdata", - "database_name": "test", - "tests": [ - { - "description": "estimatedDocumentCount succeeds", - "operations": [ - { - "object": "collection", - "name": "estimatedDocumentCount", - "result": 15 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "driverdata" - }, - "command_name": "count", - "database_name": "test" - } - } - ] - } - ] -} diff --git a/test/spec/atlas-data-lake-testing/estimatedDocumentCount.yml b/test/spec/atlas-data-lake-testing/estimatedDocumentCount.yml deleted file mode 100644 index 64c6bbd04f..0000000000 --- a/test/spec/atlas-data-lake-testing/estimatedDocumentCount.yml +++ /dev/null @@ -1,18 +0,0 @@ -collection_name: &collection_name "driverdata" -database_name: &database_name "test" - -tests: - - - description: "estimatedDocumentCount succeeds" - operations: - - - object: collection - name: estimatedDocumentCount - result: 15 - expectations: - - - command_started_event: - command: - count: *collection_name - command_name: count - database_name: *database_name diff --git a/test/spec/atlas-data-lake-testing/find.yml b/test/spec/atlas-data-lake-testing/find.yml deleted file mode 100644 index ed0f9fd530..0000000000 --- a/test/spec/atlas-data-lake-testing/find.yml +++ /dev/null @@ -1,27 +0,0 @@ -collection_name: &collection_name "driverdata" -database_name: &database_name "test" - -tests: - - - description: "Find with projection and sort" - operations: - - - object: collection - name: find - arguments: - filter: { b: { $gt: 5 } } - projection: { _id: 0 } - sort: { a: 1 } - limit: 5 - result: - - {"a": 5, "b": 6, "c": 7} - - {"a": 6, "b": 7, "c": 8} - - {"a": 7, "b": 8, "c": 9} - - {"a": 8, "b": 9, "c": 10} - - {"a": 9, "b": 10, "c": 11} - expectations: - - - command_started_event: - command: - find: *collection_name - diff --git a/test/spec/atlas-data-lake-testing/getMore.json b/test/spec/atlas-data-lake-testing/getMore.json deleted file mode 100644 index fa1deab4f3..0000000000 --- a/test/spec/atlas-data-lake-testing/getMore.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "collection_name": "driverdata", - "database_name": "test", - "tests": [ - { - "description": "A successful find event with getMore", - "operations": [ - { - "object": "collection", - "name": "find", - "arguments": { - "filter": { - "a": { - "$gte": 2 - } - }, - "sort": { - "a": 1 - }, - "batchSize": 3, - "limit": 4 - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "driverdata", - "filter": { - "a": { - "$gte": 2 - } - }, - "sort": { - "a": 1 - }, - "batchSize": 3, - "limit": 4 - }, - "command_name": "find", - "database_name": "test" - } - }, - { - "command_started_event": { - "command": { - "batchSize": 1 - }, - "command_name": "getMore", - "database_name": "cursors" - } - } - ] - } - ] -} \ No newline at end of file diff --git a/test/spec/atlas-data-lake-testing/getMore.yml b/test/spec/atlas-data-lake-testing/getMore.yml deleted file mode 100644 index c16c1224c5..0000000000 --- a/test/spec/atlas-data-lake-testing/getMore.yml +++ /dev/null @@ -1,35 +0,0 @@ -collection_name: &collection_name "driverdata" -database_name: &database_name "test" - -tests: - - - description: "A successful find event with getMore" - operations: - - - object: collection - name: find - arguments: - filter: { a: { $gte: 2 }} - sort: { a: 1 } - batchSize: 3 - limit: 4 - expectations: - - - command_started_event: - command: - find: *collection_name - filter: { a: { $gte : 2 }} - sort: { a: 1 } - batchSize: 3 - limit: 4 - command_name: "find" - database_name: *database_name - - - command_started_event: - command: - # Assertions for "getMore" and "collection" fields are omitted, as they will have arbitrary values - # TODO: Those assertions can be added after wildcard matchers are available via SPEC-1215 - batchSize: 1 - command_name: "getMore" - # mongohoused always expects getMores on the "cursors" database - database_name: "cursors" diff --git a/test/spec/atlas-data-lake-testing/listCollections.json b/test/spec/atlas-data-lake-testing/listCollections.json deleted file mode 100644 index 8d8a8f6c1b..0000000000 --- a/test/spec/atlas-data-lake-testing/listCollections.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "database_name": "test", - "tests": [ - { - "description": "ListCollections succeeds", - "operations": [ - { - "name": "listCollections", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command_name": "listCollections", - "database_name": "test", - "command": { - "listCollections": 1 - } - } - } - ] - } - ] -} \ No newline at end of file diff --git a/test/spec/atlas-data-lake-testing/listCollections.yml b/test/spec/atlas-data-lake-testing/listCollections.yml deleted file mode 100644 index 2b1fedcddb..0000000000 --- a/test/spec/atlas-data-lake-testing/listCollections.yml +++ /dev/null @@ -1,17 +0,0 @@ -database_name: &database_name "test" - -tests: - - - description: "ListCollections succeeds" - operations: - - - name: listCollections - object: database - expectations: - - - command_started_event: - command_name: "listCollections" - database_name: *database_name - command: - listCollections: 1 - diff --git a/test/spec/atlas-data-lake-testing/listDatabases.json b/test/spec/atlas-data-lake-testing/listDatabases.json deleted file mode 100644 index f8ec9a0bf4..0000000000 --- a/test/spec/atlas-data-lake-testing/listDatabases.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "tests": [ - { - "description": "ListDatabases succeeds", - "operations": [ - { - "name": "listDatabases", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command_name": "listDatabases", - "database_name": "admin", - "command": { - "listDatabases": 1 - } - } - } - ] - } - ] -} \ No newline at end of file diff --git a/test/spec/atlas-data-lake-testing/listDatabases.yml b/test/spec/atlas-data-lake-testing/listDatabases.yml deleted file mode 100644 index b6e565b90f..0000000000 --- a/test/spec/atlas-data-lake-testing/listDatabases.yml +++ /dev/null @@ -1,15 +0,0 @@ -tests: - - - description: "ListDatabases succeeds" - operations: - - - name: listDatabases - object: client - expectations: - - - command_started_event: - command_name: "listDatabases" - database_name: "admin" - command: - listDatabases: 1 - diff --git a/test/spec/atlas-data-lake-testing/runCommand.json b/test/spec/atlas-data-lake-testing/runCommand.json deleted file mode 100644 index f72e863ba5..0000000000 --- a/test/spec/atlas-data-lake-testing/runCommand.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "database_name": "test", - "tests": [ - { - "description": "ping succeeds using runCommand", - "operations": [ - { - "name": "runCommand", - "object": "database", - "command_name": "ping", - "arguments": { - "command": { - "ping": 1 - } - } - } - ], - "expectations": [ - { - "command_started_event": { - "command_name": "ping", - "database_name": "test", - "command": { - "ping": 1 - } - } - } - ] - } - ] -} \ No newline at end of file diff --git a/test/spec/atlas-data-lake-testing/runCommand.yml b/test/spec/atlas-data-lake-testing/runCommand.yml deleted file mode 100644 index 14435c28d5..0000000000 --- a/test/spec/atlas-data-lake-testing/runCommand.yml +++ /dev/null @@ -1,20 +0,0 @@ -database_name: &database_name "test" - -tests: - - - description: "ping succeeds using runCommand" - operations: - - - name: runCommand - object: database - command_name: ping - arguments: - command: - ping: 1 - expectations: - - - command_started_event: - command_name: ping - database_name: *database_name - command: - ping: 1 diff --git a/test/spec/atlas-data-lake-testing/unified/aggregate.json b/test/spec/atlas-data-lake-testing/unified/aggregate.json new file mode 100644 index 0000000000..68a3467c71 --- /dev/null +++ b/test/spec/atlas-data-lake-testing/unified/aggregate.json @@ -0,0 +1,84 @@ +{ + "description": "aggregate", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "test" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "driverdata" + } + } + ], + "tests": [ + { + "description": "Aggregate with pipeline (project, sort, limit)", + "operations": [ + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$project": { + "_id": 0 + } + }, + { + "$sort": { + "a": 1 + } + }, + { + "$limit": 2 + } + ] + }, + "expectResult": [ + { + "a": 1, + "b": 2, + "c": 3 + }, + { + "a": 2, + "b": 3, + "c": 4 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "driverdata" + }, + "commandName": "aggregate", + "databaseName": "test" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/atlas-data-lake-testing/unified/aggregate.yml b/test/spec/atlas-data-lake-testing/unified/aggregate.yml new file mode 100644 index 0000000000..54bad5aeaa --- /dev/null +++ b/test/spec/atlas-data-lake-testing/unified/aggregate.yml @@ -0,0 +1,38 @@ +description: "aggregate" + +schemaVersion: "1.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name test + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name driverdata + +tests: + - description: "Aggregate with pipeline (project, sort, limit)" + operations: + - object: *collection0 + name: aggregate + arguments: + pipeline: + - $project: { _id: 0 } + - $sort: { a: 1 } + - $limit: 2 + expectResult: + - { a: 1, b: 2, c: 3 } + - { a: 2, b: 3, c: 4 } + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + aggregate: *collection0Name + commandName: aggregate + databaseName: *database0Name diff --git a/test/spec/atlas-data-lake-testing/unified/estimatedDocumentCount.json b/test/spec/atlas-data-lake-testing/unified/estimatedDocumentCount.json new file mode 100644 index 0000000000..b7515a4418 --- /dev/null +++ b/test/spec/atlas-data-lake-testing/unified/estimatedDocumentCount.json @@ -0,0 +1,56 @@ +{ + "description": "estimatedDocumentCount", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "test" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "driverdata" + } + } + ], + "tests": [ + { + "description": "estimatedDocumentCount succeeds", + "operations": [ + { + "object": "collection0", + "name": "estimatedDocumentCount", + "expectResult": 15 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "driverdata" + }, + "commandName": "count", + "databaseName": "test" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/atlas-data-lake-testing/unified/estimatedDocumentCount.yml b/test/spec/atlas-data-lake-testing/unified/estimatedDocumentCount.yml new file mode 100644 index 0000000000..fe3c353879 --- /dev/null +++ b/test/spec/atlas-data-lake-testing/unified/estimatedDocumentCount.yml @@ -0,0 +1,31 @@ +description: "estimatedDocumentCount" + +schemaVersion: "1.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name test + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name driverdata + +tests: + - description: "estimatedDocumentCount succeeds" + operations: + - object: *collection0 + name: estimatedDocumentCount + expectResult: 15 + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + count: *collection0Name + commandName: count + databaseName: *database0Name diff --git a/test/spec/atlas-data-lake-testing/find.json b/test/spec/atlas-data-lake-testing/unified/find.json similarity index 52% rename from test/spec/atlas-data-lake-testing/find.json rename to test/spec/atlas-data-lake-testing/unified/find.json index 8a3468a135..d0652dc720 100644 --- a/test/spec/atlas-data-lake-testing/find.json +++ b/test/spec/atlas-data-lake-testing/unified/find.json @@ -1,12 +1,36 @@ { - "collection_name": "driverdata", - "database_name": "test", + "description": "find", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "test" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "driverdata" + } + } + ], "tests": [ { "description": "Find with projection and sort", "operations": [ { - "object": "collection", + "object": "collection0", "name": "find", "arguments": { "filter": { @@ -22,7 +46,7 @@ }, "limit": 5 }, - "result": [ + "expectResult": [ { "a": 5, "b": 6, @@ -51,13 +75,20 @@ ] } ], - "expectations": [ + "expectEvents": [ { - "command_started_event": { - "command": { - "find": "driverdata" + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "driverdata" + }, + "commandName": "find", + "databaseName": "test" + } } - } + ] } ] } diff --git a/test/spec/atlas-data-lake-testing/unified/find.yml b/test/spec/atlas-data-lake-testing/unified/find.yml new file mode 100644 index 0000000000..10384f78f4 --- /dev/null +++ b/test/spec/atlas-data-lake-testing/unified/find.yml @@ -0,0 +1,41 @@ +description: "find" + +schemaVersion: "1.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name test + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name driverdata + +tests: + - description: "Find with projection and sort" + operations: + - object: *collection0 + name: find + arguments: + filter: { b: { $gt: 5 } } + projection: { _id: 0 } + sort: { a: 1 } + limit: 5 + expectResult: + - { a: 5, b: 6, c: 7 } + - { a: 6, b: 7, c: 8 } + - { a: 7, b: 8, c: 9 } + - { a: 8, b: 9, c: 10 } + - { a: 9, b: 10, c: 11 } + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + find: *collection0Name + commandName: find + databaseName: *database0Name diff --git a/test/spec/atlas-data-lake-testing/unified/getMore.json b/test/spec/atlas-data-lake-testing/unified/getMore.json new file mode 100644 index 0000000000..109b6d3d8e --- /dev/null +++ b/test/spec/atlas-data-lake-testing/unified/getMore.json @@ -0,0 +1,95 @@ +{ + "description": "getMore", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "test" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "driverdata" + } + } + ], + "tests": [ + { + "description": "A successful find event with getMore", + "operations": [ + { + "object": "collection0", + "name": "find", + "arguments": { + "filter": { + "a": { + "$gte": 2 + } + }, + "sort": { + "a": 1 + }, + "batchSize": 3, + "limit": 4 + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "driverdata", + "filter": { + "a": { + "$gte": 2 + } + }, + "sort": { + "a": 1 + }, + "batchSize": 3, + "limit": 4 + }, + "commandName": "find", + "databaseName": "test" + } + }, + { + "commandStartedEvent": { + "command": { + "getMore": { + "$$type": [ + "int", + "long" + ] + }, + "collection": { + "$$type": "string" + }, + "batchSize": 1 + }, + "commandName": "getMore", + "databaseName": "cursors" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/atlas-data-lake-testing/unified/getMore.yml b/test/spec/atlas-data-lake-testing/unified/getMore.yml new file mode 100644 index 0000000000..f02fbfe9a1 --- /dev/null +++ b/test/spec/atlas-data-lake-testing/unified/getMore.yml @@ -0,0 +1,48 @@ +description: "getMore" + +schemaVersion: "1.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name test + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name driverdata + +tests: + - description: "A successful find event with getMore" + operations: + - object: *collection0 + name: find + arguments: + filter: { a: { $gte: 2 } } + sort: { a: 1 } + batchSize: 3 + limit: 4 + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + find: *collection0Name + filter: { a: { $gte : 2 } } + sort: { a: 1 } + batchSize: 3 + limit: 4 + commandName: find + databaseName: *database0Name + - commandStartedEvent: + command: + getMore: { $$type: [ int, long ] } + # collection name will be an internal identifier + collection: { $$type: string } + batchSize: 1 + commandName: getMore + # mongohoused always expects getMores on the "cursors" database + databaseName: cursors diff --git a/test/spec/atlas-data-lake-testing/unified/listCollections.json b/test/spec/atlas-data-lake-testing/unified/listCollections.json new file mode 100644 index 0000000000..642e7ed328 --- /dev/null +++ b/test/spec/atlas-data-lake-testing/unified/listCollections.json @@ -0,0 +1,48 @@ +{ + "description": "listCollections", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "test" + } + } + ], + "tests": [ + { + "description": "ListCollections succeeds", + "operations": [ + { + "object": "database0", + "name": "listCollections" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + }, + "commandName": "listCollections", + "databaseName": "test" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/atlas-data-lake-testing/unified/listCollections.yml b/test/spec/atlas-data-lake-testing/unified/listCollections.yml new file mode 100644 index 0000000000..2b9cd1cc94 --- /dev/null +++ b/test/spec/atlas-data-lake-testing/unified/listCollections.yml @@ -0,0 +1,26 @@ +description: "listCollections" + +schemaVersion: "1.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name test + +tests: + - description: "ListCollections succeeds" + operations: + - object: *database0 + name: listCollections + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + listCollections: 1 + commandName: listCollections + databaseName: *database0Name diff --git a/test/spec/atlas-data-lake-testing/unified/listDatabases.json b/test/spec/atlas-data-lake-testing/unified/listDatabases.json new file mode 100644 index 0000000000..64506ee54e --- /dev/null +++ b/test/spec/atlas-data-lake-testing/unified/listDatabases.json @@ -0,0 +1,41 @@ +{ + "description": "listDatabases", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + } + ], + "tests": [ + { + "description": "ListCollections succeeds", + "operations": [ + { + "object": "client0", + "name": "listDatabases" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + }, + "commandName": "listDatabases", + "databaseName": "admin" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/atlas-data-lake-testing/unified/listDatabases.yml b/test/spec/atlas-data-lake-testing/unified/listDatabases.yml new file mode 100644 index 0000000000..cb70ee6c73 --- /dev/null +++ b/test/spec/atlas-data-lake-testing/unified/listDatabases.yml @@ -0,0 +1,22 @@ +description: "listDatabases" + +schemaVersion: "1.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + +tests: + - description: "ListCollections succeeds" + operations: + - object: *client0 + name: listDatabases + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + listDatabases: 1 + commandName: listDatabases + databaseName: admin diff --git a/test/spec/atlas-data-lake-testing/unified/runCommand.json b/test/spec/atlas-data-lake-testing/unified/runCommand.json new file mode 100644 index 0000000000..325b6b3f30 --- /dev/null +++ b/test/spec/atlas-data-lake-testing/unified/runCommand.json @@ -0,0 +1,54 @@ +{ + "description": "runCommand", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "test" + } + } + ], + "tests": [ + { + "description": "ping succeeds using runCommand", + "operations": [ + { + "object": "database0", + "name": "runCommand", + "arguments": { + "command": { + "ping": 1 + }, + "commandName": "ping" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "ping": 1 + }, + "commandName": "ping", + "databaseName": "test" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/atlas-data-lake-testing/unified/runCommand.yml b/test/spec/atlas-data-lake-testing/unified/runCommand.yml new file mode 100644 index 0000000000..8ab0d7b478 --- /dev/null +++ b/test/spec/atlas-data-lake-testing/unified/runCommand.yml @@ -0,0 +1,29 @@ +description: "runCommand" + +schemaVersion: "1.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name test + +tests: + - description: "ping succeeds using runCommand" + operations: + - object: *database0 + name: runCommand + arguments: + command: { ping: 1 } + commandName: ping + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + ping: 1 + commandName: ping + databaseName: *database0Name diff --git a/test/spec/crud/README.md b/test/spec/crud/README.md new file mode 100644 index 0000000000..8417ef1334 --- /dev/null +++ b/test/spec/crud/README.md @@ -0,0 +1,678 @@ +# CRUD Tests + +## Introduction + +The YAML and JSON files in this directory are platform-independent tests meant to exercise a driver's implementation of +the CRUD specification. These tests utilize the [Unified Test Format](../../unified-test-format/unified-test-format.md). + +Several prose tests, which are not easily expressed in YAML, are also presented in this file. Those tests will need to +be manually implemented by each driver. + +## Prose Tests + +### 1. WriteConcernError.details exposes writeConcernError.errInfo + +Test that `writeConcernError.errInfo` in a command response is propagated as `WriteConcernError.details` (or equivalent) +in the driver. + +Using a 4.0+ server, set the following failpoint: + +```javascript +{ + "configureFailPoint": "failCommand", + "data": { + "failCommands": ["insert"], + "writeConcernError": { + "code": 100, + "codeName": "UnsatisfiableWriteConcern", + "errmsg": "Not enough data-bearing nodes", + "errInfo": { + "writeConcern": { + "w": 2, + "wtimeout": 0, + "provenance": "clientSupplied" + } + } + } + }, + "mode": { "times": 1 } +} +``` + +Then, perform an insert operation and assert that a WriteConcernError occurs and that its `details` property is both +accessible and matches the `errInfo` object from the failpoint. + +### 2. WriteError.details exposes writeErrors\[\].errInfo + +Test that `writeErrors[].errInfo` in a command response is propagated as `WriteError.details` (or equivalent) in the +driver. + +Using a 5.0+ server, create a collection with +[document validation](https://www.mongodb.com/docs/manual/core/schema-validation/) like so: + +```javascript +{ + "create": "test", + "validator": { + "x": { $type: "string" } + } +} +``` + +Enable [command monitoring](../../command-logging-and-monitoring/command-logging-and-monitoring.rst) to observe +CommandSucceededEvents. Then, insert an invalid document (e.g. `{x: 1}`) and assert that a WriteError occurs, that its +code is `121` (i.e. DocumentValidationFailure), and that its `details` property is accessible. Additionally, assert that +a CommandSucceededEvent was observed and that the `writeErrors[0].errInfo` field in the response document matches the +WriteError's `details` property. + +### 3. `MongoClient.bulkWrite` batch splits a `writeModels` input with greater than `maxWriteBatchSize` operations + +Test that `MongoClient.bulkWrite` properly handles `writeModels` inputs containing a number of writes greater than +`maxWriteBatchSize`. + +This test must only be run on 8.0+ servers. + +Construct a `MongoClient` (referred to as `client`) with +[command monitoring](../../command-logging-and-monitoring/command-logging-and-monitoring.rst) enabled to observe +CommandStartedEvents. Perform a `hello` command using `client` and record the `maxWriteBatchSize` value contained in the +response. Then, construct the following write model (referred to as `model`): + +```javascript +InsertOne: { + "namespace": "db.coll", + "document": { "a": "b" } +} +``` + +Construct a list of write models (referred to as `models`) with `model` repeated `maxWriteBatchSize + 1` times. Execute +`bulkWrite` on `client` with `models`. Assert that the bulk write succeeds and returns a `BulkWriteResult` with an +`insertedCount` value of `maxWriteBatchSize + 1`. + +Assert that two CommandStartedEvents (referred to as `firstEvent` and `secondEvent`) were observed for the `bulkWrite` +command. Assert that the length of `firstEvent.command.ops` is `maxWriteBatchSize`. Assert that the length of +`secondEvent.command.ops` is 1. If the driver exposes `operationId`s in its CommandStartedEvents, assert that +`firstEvent.operationId` is equal to `secondEvent.operationId`. + +### 4. `MongoClient.bulkWrite` batch splits when an `ops` payload exceeds `maxMessageSizeBytes` + +Test that `MongoClient.bulkWrite` properly handles a `writeModels` input which constructs an `ops` array larger than +`maxMessageSizeBytes`. + +This test must only be run on 8.0+ servers. + +Construct a `MongoClient` (referred to as `client`) with +[command monitoring](../../command-logging-and-monitoring/command-logging-and-monitoring.rst) enabled to observe +CommandStartedEvents. Perform a `hello` command using `client` and record the following values from the response: +`maxBsonObjectSize` and `maxMessageSizeBytes`. Then, construct the following document (referred to as `document`): + +```javascript +{ + "a": "b".repeat(maxBsonObjectSize - 500) +} +``` + +Construct the following write model (referred to as `model`): + +```javascript +InsertOne: { + "namespace": "db.coll", + "document": document +} +``` + +Use the following calculation to determine the number of inserts that should be provided to `MongoClient.bulkWrite`: +`maxMessageSizeBytes / maxBsonObjectSize + 1` (referred to as `numModels`). This number ensures that the inserts +provided to `MongoClient.bulkWrite` will require multiple `bulkWrite` commands to be sent to the server. + +Construct as list of write models (referred to as `models`) with `model` repeated `numModels` times. Then execute +`bulkWrite` on `client` with `models`. Assert that the bulk write succeeds and returns a `BulkWriteResult` with an +`insertedCount` value of `numModels`. + +Assert that two CommandStartedEvents (referred to as `firstEvent` and `secondEvent`) were observed. Assert that the +length of `firstEvent.command.ops` is `numModels - 1`. Assert that the length of `secondEvent.command.ops` is 1. If the +driver exposes `operationId`s in its CommandStartedEvents, assert that `firstEvent.operationId` is equal to +`secondEvent.operationId`. + +### 5. `MongoClient.bulkWrite` collects `WriteConcernError`s across batches + +Test that `MongoClient.bulkWrite` properly collects and reports `writeConcernError`s returned in separate batches. + +This test must only be run on 8.0+ servers. + +Construct a `MongoClient` (referred to as `client`) with `retryWrites: false` configured and +[command monitoring](../../command-logging-and-monitoring/command-logging-and-monitoring.rst) enabled to observe +CommandStartedEvents. Perform a `hello` command using `client` and record the `maxWriteBatchSize` value contained in the +response. Then, configure the following fail point with `client`: + +```javascript +{ + "configureFailPoint": "failCommand", + "mode": { "times": 2 }, + "data": { + "failCommands": ["bulkWrite"], + "writeConcernError": { + "code": 91, + "errmsg": "Replication is being shut down" + } + } +} +``` + +Construct the following write model (referred to as `model`): + +```javascript +InsertOne: { + "namespace": "db.coll", + "document": { "a": "b" } +} +``` + +Construct a list of write models (referred to as `models`) with `model` repeated `maxWriteBatchSize + 1` times. Execute +`bulkWrite` on `client` with `models`. Assert that the bulk write fails and returns a `BulkWriteError` (referred to as +`error`). + +Assert that `error.writeConcernErrors` has a length of 2. + +Assert that `error.partialResult` is populated. Assert that `error.partialResult.insertedCount` is equal to +`maxWriteBatchSize + 1`. + +Assert that two CommandStartedEvents were observed for the `bulkWrite` command. + +### 6. `MongoClient.bulkWrite` handles individual `WriteError`s across batches + +Test that `MongoClient.bulkWrite` handles individual write errors across batches for ordered and unordered bulk writes. + +This test must only be run on 8.0+ servers. + +Construct a `MongoClient` (referred to as `client`) with +[command monitoring](../../command-logging-and-monitoring/command-logging-and-monitoring.rst) enabled to observe +CommandStartedEvents. Perform a `hello` command using `client` and record the `maxWriteBatchSize` value contained in the +response. + +Construct a `MongoCollection` (referred to as `collection`) with the namespace "db.coll" (referred to as `namespace`). +Drop `collection`. Then, construct the following document (referred to as `document`): + +```javascript +{ + "_id": 1 +} +``` + +Insert `document` into `collection`. + +Create the following write model (referred to as `model`): + +```javascript +InsertOne { + "namespace": namespace, + "document": document +} +``` + +Construct a list of write models (referred to as `models`) with `model` repeated `maxWriteBatchSize + 1` times. + +#### Unordered + +Test that an unordered bulk write collects `WriteError`s across batches. + +Execute `bulkWrite` on `client` with `models` and `ordered` set to false. Assert that the bulk write fails and returns a +`BulkWriteError` (referred to as `unorderedError`). + +Assert that `unorderedError.writeErrors` has a length of `maxWriteBatchSize + 1`. + +Assert that two CommandStartedEvents were observed for the `bulkWrite` command. + +#### Ordered + +Test that an ordered bulk write does not execute further batches when a `WriteError` occurs. + +Execute `bulkWrite` on `client` with `models` and `ordered` set to true. Assert that the bulk write fails and returns a +`BulkWriteError` (referred to as `orderedError`). + +Assert that `orderedError.writeErrors` has a length of 1. + +Assert that one CommandStartedEvent was observed for the `bulkWrite` command. + +### 7. `MongoClient.bulkWrite` handles a cursor requiring a `getMore` + +Test that `MongoClient.bulkWrite` properly iterates the results cursor when `getMore` is required. + +This test must only be run on 8.0+ servers. + +Construct a `MongoClient` (referred to as `client`) with +[command monitoring](../../command-logging-and-monitoring/command-logging-and-monitoring.rst) enabled to observe +CommandStartedEvents. Perform a `hello` command using `client` and record the `maxBsonObjectSize` value from the +response. + +Construct a `MongoCollection` (referred to as `collection`) with the namespace "db.coll" (referred to as `namespace`). +Drop `collection`. Then create the following list of write models (referred to as `models`): + +```javascript +UpdateOne { + "namespace": namespace, + "filter": { "_id": "a".repeat(maxBsonObjectSize / 2) }, + "update": { "$set": { "x": 1 } }, + "upsert": true +}, +UpdateOne { + "namespace": namespace, + "filter": { "_id": "b".repeat(maxBsonObjectSize / 2) }, + "update": { "$set": { "x": 1 } }, + "upsert": true +}, +``` + +Execute `bulkWrite` on `client` with `models` and `verboseResults` set to true. Assert that the bulk write succeeds and +returns a `BulkWriteResult` (referred to as `result`). + +Assert that `result.upsertedCount` is equal to 2. + +Assert that the length of `result.updateResults` is equal to 2. + +Assert that a CommandStartedEvent was observed for the `getMore` command. + +### 8. `MongoClient.bulkWrite` handles a cursor requiring `getMore` within a transaction + +Test that `MongoClient.bulkWrite` executed within a transaction properly iterates the results cursor when `getMore` is +required. + +This test must only be run on 8.0+ servers. This test must not be run against standalone servers. + +Construct a `MongoClient` (referred to as `client`) with +[command monitoring](../../command-logging-and-monitoring/command-logging-and-monitoring.rst) enabled to observe +CommandStartedEvents. Perform a `hello` command using `client` and record the `maxBsonObjectSize` value from the +response. + +Construct a `MongoCollection` (referred to as `collection`) with the namespace "db.coll" (referred to as `namespace`). +Drop `collection`. + +Start a session on `client` (referred to as `session`). Start a transaction on `session`. + +Create the following list of write models (referred to as `models`): + +```javascript +UpdateOne { + "namespace": namespace, + "filter": { "_id": "a".repeat(maxBsonObjectSize / 2) }, + "update": { "$set": { "x": 1 } }, + "upsert": true +}, +UpdateOne { + "namespace": namespace, + "filter": { "_id": "b".repeat(maxBsonObjectSize / 2) }, + "update": { "$set": { "x": 1 } }, + "upsert": true +}, +``` + +Execute `bulkWrite` on `client` with `models`, `session`, and `verboseResults` set to true. Assert that the bulk write +succeeds and returns a `BulkWriteResult` (referred to as `result`). + +Assert that `result.upsertedCount` is equal to 2. + +Assert that the length of `result.updateResults` is equal to 2. + +Assert that a CommandStartedEvent was observed for the `getMore` command. + +### 9. `MongoClient.bulkWrite` handles a `getMore` error + +Test that `MongoClient.bulkWrite` properly handles a failure that occurs when attempting a `getMore`. + +This test must only be run on 8.0+ servers. + +Construct a `MongoClient` (referred to as `client`) with +[command monitoring](../../command-logging-and-monitoring/command-logging-and-monitoring.rst) enabled to observe +CommandStartedEvents. Perform a `hello` command using `client` and record the `maxBsonObjectSize` value from the +response. Then, configure the following fail point with `client`: + +```javascript +{ + "configureFailPoint": "failCommand", + "mode": { "times": 1 }, + "data": { + "failCommands": ["getMore"], + "errorCode": 8 + } +} +``` + +Construct a `MongoCollection` (referred to as `collection`) with the namespace "db.coll" (referred to as `namespace`). +Drop `collection`. Then create the following list of write models (referred to as `models`): + +```javascript +UpdateOne { + "namespace": namespace, + "filter": { "_id": "a".repeat(maxBsonObjectSize / 2) }, + "update": { "$set": { "x": 1 } }, + "upsert": true +}, +UpdateOne { + "namespace": namespace, + "filter": { "_id": "b".repeat(maxBsonObjectSize / 2) }, + "update": { "$set": { "x": 1 } }, + "upsert": true +}, +``` + +Execute `bulkWrite` on `client` with `models` and `verboseResults` set to true. Assert that the bulk write fails and +returns a `BulkWriteError` (referred to as `bulkWriteError`). + +Assert that `bulkWriteError.error` is populated with an error (referred to as `topLevelError`). Assert that +`topLevelError.errorCode` is equal to 8. + +Assert that `bulkWriteError.partialResult` is populated with a result (referred to as `partialResult`). Assert that +`partialResult.upsertedCount` is equal to 2. Assert that the length of `partialResult.updateResults` is equal to 1. + +Assert that a CommandStartedEvent was observed for the `getMore` command. + +Assert that a CommandStartedEvent was observed for the `killCursors` command. + +### 10. `MongoClient.bulkWrite` returns error for unacknowledged too-large insert + +This test must only be run on 8.0+ servers. + +Construct a `MongoClient` (referred to as `client`). + +Perform a `hello` command using `client` and record the following values from the response: `maxBsonObjectSize`. + +Then, construct the following document (referred to as `document`): + +```javascript +{ + "a": "b".repeat(maxBsonObjectSize) +} +``` + +#### With insert + +Construct the following write model (referred to as `model`): + +```javascript +InsertOne: { + "namespace": "db.coll", + "document": document +} +``` + +Construct as list of write models (referred to as `models`) with the one `model`. + +Call `MongoClient.bulkWrite` with `models` and `BulkWriteOptions.writeConcern` set to an unacknowledged write concern. + +Expect a client-side error due the size. + +#### With replace + +Construct the following write model (referred to as `model`): + +```javascript +ReplaceOne: { + "namespace": "db.coll", + "filter": {}, + "replacement": document +} +``` + +Construct as list of write models (referred to as `models`) with the one `model`. + +Call `MongoClient.bulkWrite` with `models` and `BulkWriteOptions.writeConcern` set to an unacknowledged write concern. + +Expect a client-side error due the size. + +### 11. `MongoClient.bulkWrite` batch splits when the addition of a new namespace exceeds the maximum message size + +Test that `MongoClient.bulkWrite` batch splits a bulk write when the addition of a new namespace to `nsInfo` causes the +size of the message to exceed `maxMessageSizeBytes - 1000`. + +This test must only be run on 8.0+ servers. + +Repeat the following setup for each test case: + +### Setup + +Construct a `MongoClient` (referred to as `client`) with +[command monitoring](../../command-logging-and-monitoring/command-logging-and-monitoring.rst) enabled to observe +CommandStartedEvents. Perform a `hello` command using `client` and record the following values from the response: +`maxBsonObjectSize` and `maxMessageSizeBytes`. + +Calculate the following values: + +``` +opsBytes = maxMessageSizeBytes - 1122 +numModels = opsBytes / maxBsonObjectSize +remainderBytes = opsBytes % maxBsonObjectSize +``` + +Construct the following write model (referred to as `firstModel`): + +```javascript +InsertOne { + "namespace": "db.coll", + "document": { "a": "b".repeat(maxBsonObjectSize - 57) } +} +``` + +Create a list of write models (referred to as `models`) with `firstModel` repeated `numModels` times. + +If `remainderBytes` is greater than or equal to 217, add 1 to `numModels` and append the following write model to +`models`: + +```javascript +InsertOne { + "namespace": "db.coll", + "document": { "a": "b".repeat(remainderBytes - 57) } +} +``` + +Then perform the following two tests: + +#### Case 1: No batch-splitting required + +Create the following write model (referred to as `sameNamespaceModel`): + +```javascript +InsertOne { + "namespace": "db.coll", + "document": { "a": "b" } +} +``` + +Append `sameNamespaceModel` to `models`. + +Execute `bulkWrite` on `client` with `models`. Assert that the bulk write succeeds and returns a `BulkWriteResult` +(referred to as `result`). + +Assert that `result.insertedCount` is equal to `numModels + 1`. + +Assert that one CommandStartedEvent was observed for the `bulkWrite` command (referred to as `event`). + +Assert that the length of `event.command.ops` is `numModels + 1`. Assert that the length of `event.command.nsInfo` is 1. +Assert that the namespace contained in `event.command.nsInfo` is "db.coll". + +#### Case 2: Batch-splitting required + +Construct the following namespace (referred to as `namespace`): + +``` +"db." + "c".repeat(200) +``` + +Create the following write model (referred to as `newNamespaceModel`): + +```javascript +InsertOne { + "namespace": namespace, + "document": { "a": "b" } +} +``` + +Append `newNamespaceModel` to `models`. + +Execute `bulkWrite` on `client` with `models`. Assert that the bulk write succeeds and returns a `BulkWriteResult` +(referred to as `result`). + +Assert that `result.insertedCount` is equal to `numModels + 1`. + +Assert that two CommandStartedEvents were observed for the `bulkWrite` command (referred to as `firstEvent` and +`secondEvent`). + +Assert that the length of `firstEvent.command.ops` is equal to `numModels`. Assert that the length of +`firstEvent.command.nsInfo` is equal to 1. Assert that the namespace contained in `firstEvent.command.nsInfo` is +"db.coll". + +Assert that the length of `secondEvent.command.ops` is equal to 1. Assert that the length of +`secondEvent.command.nsInfo` is equal to 1. Assert that the namespace contained in `secondEvent.command.nsInfo` is +`namespace`. + +#### Details on size calculations + +This information is not needed to implement this prose test, but is documented for future reference. This test is +designed to work if `maxBsonObjectSize` or `maxMessageSizeBytes` changes, but will need to be updated if a required +field is added to the `bulkWrite` command or the `insert` operation document, or if the overhead `OP_MSG` allowance is +changed in the bulk write specification. + +The command document for the `bulkWrite` has the following structure and size: + +```javascript +{ + "bulkWrite": 1, + "errorsOnly": true, + "ordered": true +} + +Size: 43 bytes +``` + +Each write model will create an `ops` document with the following structure and size: + +```javascript +{ + "insert": <0 | 1>, + "document": { + "_id": , + "a": + } +} + +Size: 57 bytes + +``` + +The `ops` document for both `newNamespaceModel` and `sameNamespaceModel` has a string with one character, so it is a +total of 58 bytes. + +The models using the "db.coll" namespace will create one `nsInfo` document with the following structure and size: + +```javascript +{ + "ns": "db.coll" +} + +Size: 21 bytes +``` + +`newNamespaceModel` will create an `nsInfo` document with the following structure and size: + +```javascript +{ + "ns": "db." +} + +Size: 217 bytes +``` + +We need to fill up the rest of the message with bytes such that another `ops` document will fit, but another `nsInfo` +entry will not. The following calculations are used: + +``` +# 1000 is the OP_MSG overhead required in the spec +maxBulkWriteBytes = maxMessageSizeBytes - 1000 + +# bulkWrite command + first namespace entry +existingMessageBytes = 43 + 21 + +# Space to fit the last model's ops entry +lastModelBytes = 58 + +remainingBulkWriteBytes = maxBulkWriteBytes - existingMessageBytes - lastModelBytes + +# With the actual numbers plugged in +remainingBulkWriteBytes = maxMessageSizeBytes - 1122 +``` + +### 12. `MongoClient.bulkWrite` returns an error if no operations can be added to `ops` + +Test that `MongoClient.bulkWrite` returns an error if an operation provided exceeds `maxMessageSizeBytes` such that an +empty `ops` payload would be sent. + +This test must only be run on 8.0+ servers. This test may be skipped by drivers that are not able to construct +arbitrarily large documents. + +Construct a `MongoClient` (referred to as `client`). Perform a `hello` command using `client` and record the +`maxMessageSizeBytes` value contained in the response. + +#### Case 1: `document` too large + +Construct the following write model (referred to as `largeDocumentModel`): + +```javascript +InsertOne { + "namespace": "db.coll", + "document": { "a": "b".repeat(maxMessageSizeBytes) } +} +``` + +Execute `bulkWrite` on `client` with `largeDocumentModel`. Assert that an error (referred to as `error`) is returned. +Assert that `error` is a client error. + +#### Case 2: `namespace` too large + +Construct the following namespace (referred to as `namespace`): + +``` +"db." + "c".repeat(maxMessageSizeBytes) +``` + +Construct the following write model (referred to as `largeNamespaceModel`): + +```javascript +InsertOne { + "namespace": namespace, + "document": { "a": "b" } +} +``` + +Execute `bulkWrite` on `client` with `largeNamespaceModel`. Assert that an error (referred to as `error`) is returned. +Assert that `error` is a client error. + +### 13. `MongoClient.bulkWrite` returns an error if auto-encryption is configured + +This test is expected to be removed when [DRIVERS-2888](https://jira.mongodb.org/browse/DRIVERS-2888) is resolved. + +Test that `MongoClient.bulkWrite` returns an error if the client has auto-encryption configured. + +This test must only be run on 8.0+ servers. + +Construct a `MongoClient` (referred to as `client`) configured with the following `AutoEncryptionOpts`: + +```javascript +AutoEncryptionOpts { + "keyVaultNamespace": "db.coll", + "kmsProviders": { + "aws": { + "accessKeyId": "foo", + "secretAccessKey": "bar" + } + } +} +``` + +Construct the following write model (referred to as `model`): + +```javascript +InsertOne { + "namespace": "db.coll", + "document": { "a": "b" } +} +``` + +Execute `bulkWrite` on `client` with `model`. Assert that an error (referred to as `error`) is returned. Assert that +`error` is a client error containing the message: "bulkWrite does not currently support automatic encryption". diff --git a/test/spec/crud/README.rst b/test/spec/crud/README.rst deleted file mode 100644 index 0bfea3cd15..0000000000 --- a/test/spec/crud/README.rst +++ /dev/null @@ -1,278 +0,0 @@ -========== -CRUD Tests -========== - -.. contents:: - ----- - -Introduction -============ - -The YAML and JSON files in this directory tree are platform-independent tests -that drivers can use to prove their conformance to the CRUD spec. - -Running these integration tests will require a running MongoDB server or -cluster with server versions 2.6.0 or later. Some tests have specific server -version requirements as noted by the ``runOn`` section, if provided. - -Subdirectories for Test Formats -------------------------------- - -This document describes a legacy format for CRUD tests: legacy-v1, which dates back -to the first version of the CRUD specification. New CRUD tests should be written -in the `unified test format <../../unified-test-format/unified-test-format.rst>`_ -and placed under ``unified/``. Until such time that all original tests have been ported -to the unified test format, tests in each format will be grouped in their own subdirectory: - -- ``v1/``: Legacy-v1 format tests -- ``unified/``: Tests using the `unified test format <../../unified-test-format/unified-test-format.rst>`_ - -Since some drivers may not have a unified test runner capable of executing tests -in all two formats, segregating tests in this manner will make it easier for -drivers to sync and feed test files to different test runners. - -Legacy-v1 Test Format for Single Operations -------------------------------------------- - -*Note: this section pertains to test files in the "v1" directory.* - -The test format above supports both multiple operations and APM expectations, -and is consistent with the formats used by other specifications. Previously, the -CRUD spec tests used a simplified format that only allowed for executing a -single operation. Notable differences from the legacy-v2 format are as follows: - -- Instead of a ``tests[i].operations`` array, a single operation was defined as - a document in ``tests[i].operation``. That document consisted of only the - ``name``, ``arguments``, and an optional ``object`` field. - -- Instead of ``error`` and ``result`` fields within each element in the - ``tests[i].operations`` array, the single operation's error and result were - defined under the ``tests[i].outcome.error`` and ``tests[i].outcome.result`` - fields. - -- Instead of a top-level ``runOn`` field, server requirements are denoted by - separate top-level ``minServerVersion``, ``maxServerVersion``, and - ``serverless`` fields. The minimum server version is an inclusive lower bound - for running the test. The maximum server version is an exclusive upper bound - for running the test. If a field is not present, it should be assumed that - there is no corresponding bound on the required server version. The - ``serverless`` requirement behaves the same as the ``serverless`` field of the - `unified test format's runOnRequirement <../../unified-test-format/unified-test-format.rst#runonrequirement>`_. - -The legacy-v1 format should not conflict with the newer, multi-operation format -used by other specs (e.g. Transactions). It is possible to create a unified test -runner capable of executing both legacy formats (as some drivers do). - -Error Assertions for Bulk Write Operations -========================================== - -When asserting errors (e.g. ``errorContains``, ``errorCodeName``) for bulk write -operations, the test harness should inspect the ``writeConcernError`` and/or -``writeErrors`` properties of the bulk write exception. This may not be needed for -``errorContains`` if a driver concatenates all write and write concern error -messages into the bulk write exception's top-level message. - -Test Runner Implementation -========================== - -This section provides guidance for implementing a test runner for legacy-v1 -tests. See the `unified test format spec <../../../../unified-test-format/unified-test-format.rst>`_ for how to run tests under -``unified/``. - -Before running the tests: - -- Create a global MongoClient (``globalMongoClient``) and connect to the server. - This client will be used for executing meta operations, such as checking - server versions and preparing data fixtures. - -For each test file: - -- Using ``globalMongoClient``, check that the current server version satisfies - one of the configurations provided in the top-level ``runOn`` field in the test - file (if applicable). If the - requirements are not satisifed, the test file should be skipped. - -- Determine the collection and database under test, utilizing the top-level - ``collection_name`` and/or ``database_name`` fields if present. - -- For each element in the ``tests`` array: - - - Using ``globalMongoClient``, ensure that the collection and/or database - under test is in a "clean" state, as needed. This may be accomplished by - dropping the database; however, drivers may also decide to drop individual - collections as needed (this may be more performant). - - - If the top-level ``data`` field is present in the test file, insert the - corresponding data into the collection under test using - ``globalMongoClient``. - - - If the the ``failPoint`` field is present, use ``globalMongoClient`` to - configure the fail point on the primary server. See - `Server Fail Point <../../transactions/tests#server-fail-point>`_ in the - Transactions spec test documentation for more information. - - - Create a local MongoClient (``localMongoClient``) and connect to the server. - This client will be used for executing the test case. - - - If ``clientOptions`` is present, those options should be used to create - the client. Drivers MAY merge these options atop existing defaults (e.g. - reduced ``serverSelectionTimeoutMS`` value for faster test failures) at - their own discretion. - - - Activate command monitoring for ``localMongoClient`` and begin capturing - events. Note that some events may need to be filtered out if the driver - uses global listeners or reports internal commands (e.g. ``hello``, legacy - hello, authentication). - - - For each element in the ``operations`` array: - - - Using ``localMongoClient``, select the appropriate ``object`` to execute - the operation. Default to the collection under test if this field is not - present. - - - If ``collectionOptions`` is present, those options should be used to - construct the collection object. - - - Given the ``name`` and ``arguments``, execute the operation on the object - under test. Capture the result of the operation, if any, and observe - whether an error occurred. If an error is encountered that includes a - result (e.g. BulkWriteException), extract the result object. - - - If ``error`` is present and true, assert that the operation encountered an - error. Otherwise, assert that no error was encountered. - - - if ``result`` is present, assert that it matches the operation's result. - - - Deactivate command monitoring for ``localMongoClient``. - - - If the ``expectations`` array is present, assert that the sequence of - emitted CommandStartedEvents from executing the operation(s) matches the - sequence of ``command_started_event`` objects in the ``expectations`` array. - - - If the ``outcome`` field is present, assert the contents of the specified - collection using ``globalMongoClient``. - Note the server does not guarantee that documents returned by a find - command will be in inserted order. This find MUST sort by ``{_id:1}``. - -Evaluating Matches ------------------- - -The expected values for results (e.g. ``result`` for an operation -operation, ``command_started_event.command``, elements in ``outcome.data``) are -written in `Extended JSON <../../extended-json.rst>`_. Drivers may adopt any of -the following approaches to comparisons, as long as they are consistent: - -- Convert ``actual`` to Extended JSON and compare to ``expected`` -- Convert ``expected`` and ``actual`` to BSON, and compare them -- Convert ``expected`` and ``actual`` to native representations, and compare - them - -Extra Fields in Actual Documents -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When comparing ``actual`` and ``expected`` *documents*, drivers should permit -``actual`` documents to contain additional fields not present in ``expected``. -For example, the following documents match: - -- ``expected`` is ``{ "x": 1 }`` -- ``actual`` is ``{ "_id": { "$oid" : "000000000000000000000001" }, "x": 1 }`` - -In this sense, ``expected`` may be a subset of ``actual``. It may also be -helpful to think of ``expected`` as a form of query criteria. The intention -behind this rule is that it is not always feasible for the test to express all -fields in the expected document(s) (e.g. session and cluster time information -in a ``command_started_event.command`` document). - -This rule for allowing extra fields in ``actual`` only applies for values that -correspond to a document. For instance, an actual result of ``[1, 2, 3, 4]`` for -a ``distinct`` operation would not match an expected result of ``[1, 2, 3]``. -Likewise with the ``find`` operation, this rule would only apply when matching -documents *within* the expected result array and actual cursor. - -Note that in the case of result objects for some CRUD operations, ``expected`` -may condition additional, optional fields (see: -`Optional Fields in Expected Result Objects`_). - -Fields that must NOT be present in Actual Documents -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Some command-started events in ``expectations`` include ``null`` values for -optional fields such as ``allowDiskUse``. -Tests MUST assert that the actual command **omits** any field that has a -``null`` value in the expected command. - -Optional Fields in Expected Result Objects -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Some ``expected`` results may include fields that are optional in the CRUD -specification, such as ``insertedId`` (for InsertOneResult), ``insertedIds`` -(for InsertManyResult), and ``upsertedCount`` (for UpdateResult). Drivers that -do not implement these fields should ignore them when comparing ``actual`` with -``expected``. - -Prose Tests -=========== - -The following tests have not yet been automated, but MUST still be tested. - -1. WriteConcernError.details exposes writeConcernError.errInfo --------------------------------------------------------------- - -Test that ``writeConcernError.errInfo`` in a command response is propagated as -``WriteConcernError.details`` (or equivalent) in the driver. - -Using a 4.0+ server, set the following failpoint: - -.. code:: javascript - - { - "configureFailPoint": "failCommand", - "data": { - "failCommands": ["insert"], - "writeConcernError": { - "code": 100, - "codeName": "UnsatisfiableWriteConcern", - "errmsg": "Not enough data-bearing nodes", - "errInfo": { - "writeConcern": { - "w": 2, - "wtimeout": 0, - "provenance": "clientSupplied" - } - } - } - }, - "mode": { "times": 1 } - } - -Then, perform an insert operation and assert that a WriteConcernError occurs and -that its ``details`` property is both accessible and matches the ``errInfo`` -object from the failpoint. - -2. WriteError.details exposes writeErrors[].errInfo ---------------------------------------------------- - -Test that ``writeErrors[].errInfo`` in a command response is propagated as -``WriteError.details`` (or equivalent) in the driver. - -Using a 5.0+ server, create a collection with -`document validation `_ -like so: - -.. code:: javascript - - { - "create": "test", - "validator": { - "x": { $type: "string" } - } - } - -Enable `command monitoring <../../command-monitoring/command-monitoring.rst>`_ -to observe CommandSucceededEvents. Then, insert an invalid document (e.g. -``{x: 1}``) and assert that a WriteError occurs, that its code is ``121`` -(i.e. DocumentValidationFailure), and that its ``details`` property is -accessible. Additionally, assert that a CommandSucceededEvent was observed and -that the ``writeErrors[0].errInfo`` field in the response document matches the -WriteError's ``details`` property. diff --git a/test/spec/crud/unified/aggregate-allowdiskuse.json b/test/spec/crud/unified/aggregate-allowdiskuse.json index 6d794d1e4d..2e54175b8a 100644 --- a/test/spec/crud/unified/aggregate-allowdiskuse.json +++ b/test/spec/crud/unified/aggregate-allowdiskuse.json @@ -1,155 +1,155 @@ { - "description": "aggregate-allowdiskuse", - "schemaVersion": "1.0", - "createEntities": [ - { - "client": { - "id": "client0", - "observeEvents": [ - "commandStartedEvent" - ] - } - }, - { - "database": { - "id": "database0", - "client": "client0", - "databaseName": "crud-tests" - } - }, - { - "collection": { - "id": "collection0", - "database": "database0", - "collectionName": "coll0" - } + "description": "aggregate-allowdiskuse", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] } - ], - "initialData": [ - { - "collectionName": "coll0", - "databaseName": "crud-tests", - "documents": [] + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" } - ], - "tests": [ - { - "description": "Aggregate does not send allowDiskUse when value is not specified", - "operations": [ - { - "object": "collection0", - "name": "aggregate", - "arguments": { - "pipeline": [ - { - "$match": {} - } - ] - } - } - ], - "expectEvents": [ - { - "client": "client0", - "events": [ + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "Aggregate does not send allowDiskUse when value is not specified", + "operations": [ + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ { - "commandStartedEvent": { - "command": { - "aggregate": "coll0", - "pipeline": [ - { - "$match": {} - } - ], - "allowDiskUse": { - "$$exists": false - } - }, - "commandName": "aggregate", - "databaseName": "crud-tests" - } + "$match": {} } ] } - ] - }, - { - "description": "Aggregate sends allowDiskUse false when false is specified", - "operations": [ - { - "object": "collection0", - "name": "aggregate", - "arguments": { - "pipeline": [ - { - "$match": {} - } - ], - "allowDiskUse": false + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll0", + "pipeline": [ + { + "$match": {} + } + ], + "allowDiskUse": { + "$$exists": false + } + }, + "commandName": "aggregate", + "databaseName": "crud-tests" + } } - } - ], - "expectEvents": [ - { - "client": "client0", - "events": [ + ] + } + ] + }, + { + "description": "Aggregate sends allowDiskUse false when false is specified", + "operations": [ + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ { - "commandStartedEvent": { - "command": { - "aggregate": "coll0", - "pipeline": [ - { - "$match": {} - } - ], - "allowDiskUse": false - }, - "commandName": "aggregate", - "databaseName": "crud-tests" - } + "$match": {} } - ] + ], + "allowDiskUse": false } - ] - }, - { - "description": "Aggregate sends allowDiskUse true when true is specified", - "operations": [ - { - "object": "collection0", - "name": "aggregate", - "arguments": { - "pipeline": [ - { - "$match": {} - } - ], - "allowDiskUse": true + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll0", + "pipeline": [ + { + "$match": {} + } + ], + "allowDiskUse": false + }, + "commandName": "aggregate", + "databaseName": "crud-tests" + } } - } - ], - "expectEvents": [ - { - "client": "client0", - "events": [ + ] + } + ] + }, + { + "description": "Aggregate sends allowDiskUse true when true is specified", + "operations": [ + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ { - "commandStartedEvent": { - "command": { - "aggregate": "coll0", - "pipeline": [ - { - "$match": {} - } - ], - "allowDiskUse": true - }, - "commandName": "aggregate", - "databaseName": "crud-tests" - } + "$match": {} } - ] + ], + "allowDiskUse": true } - ] - } - ] - } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll0", + "pipeline": [ + { + "$match": {} + } + ], + "allowDiskUse": true + }, + "commandName": "aggregate", + "databaseName": "crud-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/aggregate-collation.json b/test/spec/crud/unified/aggregate-collation.json new file mode 100644 index 0000000000..e7f0c3a7f1 --- /dev/null +++ b/test/spec/crud/unified/aggregate-collation.json @@ -0,0 +1,73 @@ +{ + "description": "aggregate-collation", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "3.4", + "serverless": "forbid" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": "ping" + } + ] + } + ], + "tests": [ + { + "description": "Aggregate with collation", + "operations": [ + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "x": "PING" + } + } + ], + "collation": { + "locale": "en_US", + "strength": 2 + } + }, + "expectResult": [ + { + "_id": 1, + "x": "ping" + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/aggregate-collation.yml b/test/spec/crud/unified/aggregate-collation.yml new file mode 100644 index 0000000000..088dc5705b --- /dev/null +++ b/test/spec/crud/unified/aggregate-collation.yml @@ -0,0 +1,48 @@ +description: aggregate-collation + +schemaVersion: '1.4' + +runOnRequirements: + - + minServerVersion: '3.4' + serverless: forbid + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: ping } + +tests: + - + description: 'Aggregate with collation' + operations: + - + object: *collection0 + name: aggregate + arguments: + pipeline: + - { $match: { x: PING } } + # https://www.mongodb.com/docs/manual/reference/collation/#collation-document + collation: + locale: en_US + strength: 2 + expectResult: + - { _id: 1, x: ping } diff --git a/test/spec/crud/unified/aggregate-merge.yml b/test/spec/crud/unified/aggregate-merge.yml index 821f03e1c6..48dd54d1bd 100644 --- a/test/spec/crud/unified/aggregate-merge.yml +++ b/test/spec/crud/unified/aggregate-merge.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: aggregate-merge schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/aggregate-out-readConcern.yml b/test/spec/crud/unified/aggregate-out-readConcern.yml index c210c46929..67bdee676a 100644 --- a/test/spec/crud/unified/aggregate-out-readConcern.yml +++ b/test/spec/crud/unified/aggregate-out-readConcern.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: aggregate-out-readConcern schemaVersion: '1.4' runOnRequirements: diff --git a/test/spec/crud/unified/aggregate-out.json b/test/spec/crud/unified/aggregate-out.json new file mode 100644 index 0000000000..db0d7918cf --- /dev/null +++ b/test/spec/crud/unified/aggregate-out.json @@ -0,0 +1,143 @@ +{ + "description": "aggregate-out", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "2.6", + "serverless": "forbid" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "Aggregate with $out", + "operations": [ + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$sort": { + "x": 1 + } + }, + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$out": "other_test_collection" + } + ], + "batchSize": 2 + } + } + ], + "outcome": [ + { + "collectionName": "other_test_collection", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "Aggregate with $out and batch size of 0", + "operations": [ + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$sort": { + "x": 1 + } + }, + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$out": "other_test_collection" + } + ], + "batchSize": 0 + } + } + ], + "outcome": [ + { + "collectionName": "other_test_collection", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/aggregate-out.yml b/test/spec/crud/unified/aggregate-out.yml new file mode 100644 index 0000000000..a85eed0322 --- /dev/null +++ b/test/spec/crud/unified/aggregate-out.yml @@ -0,0 +1,72 @@ +description: aggregate-out + +schemaVersion: '1.4' + +runOnRequirements: + - + minServerVersion: '2.6' + serverless: forbid + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - + description: 'Aggregate with $out' + operations: + - + object: *collection0 + name: aggregate + arguments: + pipeline: + - { $sort: { x: 1 } } + - { $match: { _id: { $gt: 1 } } } + - { $out: other_test_collection } + batchSize: 2 + outcome: + - + collectionName: other_test_collection + databaseName: *database_name + documents: + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'Aggregate with $out and batch size of 0' + operations: + - + object: *collection0 + name: aggregate + arguments: + pipeline: + - { $sort: { x: 1 } } + - { $match: { _id: { $gt: 1 } } } + - { $out: other_test_collection } + batchSize: 0 + outcome: + - + collectionName: other_test_collection + databaseName: *database_name + documents: + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } diff --git a/test/spec/crud/unified/aggregate.json b/test/spec/crud/unified/aggregate.json index 0cbfb4e6e9..55634f05f6 100644 --- a/test/spec/crud/unified/aggregate.json +++ b/test/spec/crud/unified/aggregate.json @@ -562,6 +562,54 @@ ] } ] + }, + { + "description": "Aggregate with multiple stages", + "operations": [ + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$sort": { + "x": 1 + } + }, + { + "$match": { + "_id": { + "$gt": 1 + } + } + } + ], + "batchSize": 2 + }, + "expectResult": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + }, + { + "_id": 5, + "x": 55 + }, + { + "_id": 6, + "x": 66 + } + ] + } + ] } ] } diff --git a/test/spec/crud/unified/aggregate.yml b/test/spec/crud/unified/aggregate.yml index 032aece0fa..6f99aaf0fe 100644 --- a/test/spec/crud/unified/aggregate.yml +++ b/test/spec/crud/unified/aggregate.yml @@ -213,3 +213,20 @@ tests: comment: { $$exists: false } commandName: getMore databaseName: *database0Name + - + description: 'Aggregate with multiple stages' + operations: + - + object: *collection0 + name: aggregate + arguments: + pipeline: + - { $sort: { x: 1 } } + - { $match: { _id: { $gt: 1 } } } + batchSize: 2 + expectResult: + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - { _id: 4, x: 44 } + - { _id: 5, x: 55 } + - { _id: 6, x: 66 } diff --git a/test/spec/crud/unified/bulkWrite-arrayFilters-clientError.yml b/test/spec/crud/unified/bulkWrite-arrayFilters-clientError.yml index 8b4c7a1c9e..12bc84c704 100644 --- a/test/spec/crud/unified/bulkWrite-arrayFilters-clientError.yml +++ b/test/spec/crud/unified/bulkWrite-arrayFilters-clientError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: bulkWrite-arrayFilters-clientError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/bulkWrite-arrayFilters.json b/test/spec/crud/unified/bulkWrite-arrayFilters.json index 70ee014f7a..bc4e7b9fcb 100644 --- a/test/spec/crud/unified/bulkWrite-arrayFilters.json +++ b/test/spec/crud/unified/bulkWrite-arrayFilters.json @@ -274,6 +274,91 @@ ] } ] + }, + { + "description": "BulkWrite with arrayFilters", + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "updateOne": { + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 3 + } + ] + } + }, + { + "updateMany": { + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 1 + } + ] + } + } + ], + "ordered": true + }, + "expectResult": { + "deletedCount": 0, + "insertedCount": 0, + "insertedIds": { + "$$unsetOrMatches": {} + }, + "matchedCount": 3, + "modifiedCount": 3, + "upsertedCount": 0, + "upsertedIds": {} + } + } + ], + "outcome": [ + { + "collectionName": "test", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "y": [ + { + "b": 2 + }, + { + "b": 2 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 2 + } + ] + } + ] + } + ] } ] } diff --git a/test/spec/crud/unified/bulkWrite-arrayFilters.yml b/test/spec/crud/unified/bulkWrite-arrayFilters.yml index a236acb12d..9db833581f 100644 --- a/test/spec/crud/unified/bulkWrite-arrayFilters.yml +++ b/test/spec/crud/unified/bulkWrite-arrayFilters.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: bulkWrite-arrayFilters schemaVersion: '1.0' runOnRequirements: @@ -172,3 +169,42 @@ tests: b: 0 - b: 2 + - + description: 'BulkWrite with arrayFilters' + operations: + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + # UpdateOne when one document matches arrayFilters + updateOne: + filter: { } + update: { $set: { 'y.$[i].b': 2 } } + arrayFilters: + - { i.b: 3 } + - + # UpdateMany when multiple documents match arrayFilters + updateMany: + filter: { } + update: { $set: { 'y.$[i].b': 2 } } + arrayFilters: + - { i.b: 1 } + ordered: true + expectResult: + deletedCount: 0 + insertedCount: 0 + insertedIds: + $$unsetOrMatches: { } + matchedCount: 3 + modifiedCount: 3 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, y: [ { b: 2 }, { b: 2 } ] } + - { _id: 2, y: [ { b: 0 }, { b: 2 } ] } diff --git a/test/spec/crud/unified/bulkWrite-collation.json b/test/spec/crud/unified/bulkWrite-collation.json new file mode 100644 index 0000000000..fe54b1a1e3 --- /dev/null +++ b/test/spec/crud/unified/bulkWrite-collation.json @@ -0,0 +1,254 @@ +{ + "description": "bulkWrite-collation", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "3.4", + "serverless": "forbid" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": "ping" + }, + { + "_id": 3, + "x": "pINg" + }, + { + "_id": 4, + "x": "pong" + }, + { + "_id": 5, + "x": "pONg" + } + ] + } + ], + "tests": [ + { + "description": "BulkWrite with delete operations and collation", + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "deleteOne": { + "filter": { + "x": "PING" + }, + "collation": { + "locale": "en_US", + "strength": 2 + } + } + }, + { + "deleteOne": { + "filter": { + "x": "PING" + }, + "collation": { + "locale": "en_US", + "strength": 2 + } + } + }, + { + "deleteMany": { + "filter": { + "x": "PONG" + }, + "collation": { + "locale": "en_US", + "strength": 2 + } + } + } + ], + "ordered": true + }, + "expectResult": { + "deletedCount": 4, + "insertedCount": 0, + "insertedIds": { + "$$unsetOrMatches": {} + }, + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 0, + "upsertedIds": {} + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "BulkWrite with update operations and collation", + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "updateMany": { + "filter": { + "x": "ping" + }, + "update": { + "$set": { + "x": "PONG" + } + }, + "collation": { + "locale": "en_US", + "strength": 3 + } + } + }, + { + "updateOne": { + "filter": { + "x": "ping" + }, + "update": { + "$set": { + "x": "PONG" + } + }, + "collation": { + "locale": "en_US", + "strength": 2 + } + } + }, + { + "replaceOne": { + "filter": { + "x": "ping" + }, + "replacement": { + "_id": 6, + "x": "ping" + }, + "upsert": true, + "collation": { + "locale": "en_US", + "strength": 3 + } + } + }, + { + "updateMany": { + "filter": { + "x": "pong" + }, + "update": { + "$set": { + "x": "PONG" + } + }, + "collation": { + "locale": "en_US", + "strength": 2 + } + } + } + ], + "ordered": true + }, + "expectResult": { + "deletedCount": 0, + "insertedCount": 0, + "insertedIds": { + "$$unsetOrMatches": {} + }, + "matchedCount": 6, + "modifiedCount": 4, + "upsertedCount": 1, + "upsertedIds": { + "2": 6 + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": "PONG" + }, + { + "_id": 3, + "x": "PONG" + }, + { + "_id": 4, + "x": "PONG" + }, + { + "_id": 5, + "x": "PONG" + }, + { + "_id": 6, + "x": "ping" + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/bulkWrite-collation.yml b/test/spec/crud/unified/bulkWrite-collation.yml new file mode 100644 index 0000000000..b9b3fc4fe9 --- /dev/null +++ b/test/spec/crud/unified/bulkWrite-collation.yml @@ -0,0 +1,130 @@ +description: bulkWrite-collation + +schemaVersion: '1.4' + +runOnRequirements: + - + minServerVersion: '3.4' + serverless: forbid + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: ping } + - { _id: 3, x: pINg } + - { _id: 4, x: pong } + - { _id: 5, x: pONg } + +# See: https://www.mongodb.com/docs/manual/reference/collation/#collation-document +tests: + - + description: 'BulkWrite with delete operations and collation' + operations: + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + # matches two documents but deletes one + deleteOne: + filter: { x: "PING" } + collation: { locale: "en_US", strength: 2 } + - + # matches the remaining document and deletes it + deleteOne: + filter: { x: "PING" } + collation: { locale: "en_US", strength: 2 } + - + # matches two documents and deletes them + deleteMany: + filter: { x: "PONG" } + collation: { locale: "en_US", strength: 2 } + ordered: true + expectResult: + deletedCount: 4 + insertedCount: 0 + insertedIds: + $$unsetOrMatches: { } + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'BulkWrite with update operations and collation' + operations: + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + # matches only one document due to strength and updates + updateMany: + filter: { x: "ping" } + update: { $set: { x: "PONG" } } + collation: { locale: "en_US", strength: 3 } + - + # matches one document and updates + updateOne: + filter: { x: "ping" } + update: { $set: { x: "PONG" } } + collation: { locale: "en_US", strength: 2 } + - + # matches no document due to strength and upserts + replaceOne: + filter: { x: "ping" } + replacement: { _id: 6, x: "ping" } + upsert: true + collation: { locale: "en_US", strength: 3 } + - + # matches two documents and updates + updateMany: + filter: { x: "pong" } + update: { $set: { x: "PONG" } } + collation: { locale: "en_US", strength: 2 } + ordered: true + expectResult: + deletedCount: 0 + insertedCount: 0 + insertedIds: + $$unsetOrMatches: { } + matchedCount: 6 + modifiedCount: 4 + upsertedCount: 1 + upsertedIds: { '2': 6 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - {_id: 1, x: 11 } + - {_id: 2, x: "PONG" } + - {_id: 3, x: "PONG" } + - {_id: 4, x: "PONG" } + - {_id: 5, x: "PONG" } + - {_id: 6, x: "ping" } diff --git a/test/spec/crud/unified/bulkWrite-comment.json b/test/spec/crud/unified/bulkWrite-comment.json index de044fca91..0b2addc850 100644 --- a/test/spec/crud/unified/bulkWrite-comment.json +++ b/test/spec/crud/unified/bulkWrite-comment.json @@ -412,6 +412,7 @@ "description": "BulkWrite with comment - pre 4.4", "runOnRequirements": [ { + "minServerVersion": "3.4.0", "maxServerVersion": "4.2.99" } ], diff --git a/test/spec/crud/unified/bulkWrite-comment.yml b/test/spec/crud/unified/bulkWrite-comment.yml index 516313593c..965a0b8384 100644 --- a/test/spec/crud/unified/bulkWrite-comment.yml +++ b/test/spec/crud/unified/bulkWrite-comment.yml @@ -152,7 +152,8 @@ tests: - description: 'BulkWrite with comment - pre 4.4' runOnRequirements: - - maxServerVersion: "4.2.99" + - minServerVersion: "3.4.0" + maxServerVersion: "4.2.99" operations: - object: *collection0 name: bulkWrite diff --git a/test/spec/crud/unified/bulkWrite-delete-hint-clientError.yml b/test/spec/crud/unified/bulkWrite-delete-hint-clientError.yml index 2b0bdb1c21..5c17261004 100644 --- a/test/spec/crud/unified/bulkWrite-delete-hint-clientError.yml +++ b/test/spec/crud/unified/bulkWrite-delete-hint-clientError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: bulkWrite-delete-hint-clientError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/bulkWrite-delete-hint-serverError.yml b/test/spec/crud/unified/bulkWrite-delete-hint-serverError.yml index e757bade0c..06ad7787a7 100644 --- a/test/spec/crud/unified/bulkWrite-delete-hint-serverError.yml +++ b/test/spec/crud/unified/bulkWrite-delete-hint-serverError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: bulkWrite-delete-hint-serverError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/bulkWrite-delete-hint.yml b/test/spec/crud/unified/bulkWrite-delete-hint.yml index 8b7f84aa94..ac451bfc46 100644 --- a/test/spec/crud/unified/bulkWrite-delete-hint.yml +++ b/test/spec/crud/unified/bulkWrite-delete-hint.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: bulkWrite-delete-hint schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/bulkWrite-deleteMany-hint-unacknowledged.json b/test/spec/crud/unified/bulkWrite-deleteMany-hint-unacknowledged.json new file mode 100644 index 0000000000..2dda9486e8 --- /dev/null +++ b/test/spec/crud/unified/bulkWrite-deleteMany-hint-unacknowledged.json @@ -0,0 +1,269 @@ +{ + "description": "bulkWrite-deleteMany-hint-unacknowledged", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "db0" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + } + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "db0", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "Unacknowledged deleteMany with hint string fails with client-side error on pre-4.4 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.2.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "deleteMany": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_" + } + } + ] + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged deleteMany with hint document fails with client-side error on pre-4.4 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.2.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "deleteMany": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ] + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged deleteMany with hint string on 4.4+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.4.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "deleteMany": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_" + } + } + ] + }, + "expectResult": { + "$$unsetOrMatches": { + "acknowledged": { + "$$unsetOrMatches": false + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "delete": "coll0", + "deletes": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "$$type": [ + "string", + "object" + ] + }, + "limit": 0 + } + ], + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + }, + { + "description": "Unacknowledged deleteMany with hint document on 4.4+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.4.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "deleteMany": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ] + }, + "expectResult": { + "$$unsetOrMatches": { + "acknowledged": { + "$$unsetOrMatches": false + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "delete": "coll0", + "deletes": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "$$type": [ + "string", + "object" + ] + }, + "limit": 0 + } + ], + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/bulkWrite-deleteMany-hint-unacknowledged.yml b/test/spec/crud/unified/bulkWrite-deleteMany-hint-unacknowledged.yml new file mode 100644 index 0000000000..aa2cdbce92 --- /dev/null +++ b/test/spec/crud/unified/bulkWrite-deleteMany-hint-unacknowledged.yml @@ -0,0 +1,98 @@ +description: bulkWrite-deleteMany-hint-unacknowledged + +schemaVersion: '1.0' + +createEntities: + - client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name db0 + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + collectionOptions: + writeConcern: { w: 0 } + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: &documents + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - description: "Unacknowledged deleteMany with hint string fails with client-side error on pre-4.4 server" + runOnRequirements: + - maxServerVersion: "4.2.99" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - deleteMany: + filter: &filter { _id: { $gt: 1 } } + hint: _id_ + expectError: + isClientError: true + expectEvents: &noEvents + - client: *client0 + events: [] + + - description: "Unacknowledged deleteMany with hint document fails with client-side error on pre-4.4 server" + runOnRequirements: + - maxServerVersion: "4.2.99" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - deleteMany: + filter: *filter + hint: { _id: 1 } + expectError: + isClientError: true + expectEvents: *noEvents + + - description: "Unacknowledged deleteMany with hint string on 4.4+ server" + runOnRequirements: + - minServerVersion: "4.4.0" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - deleteMany: + filter: *filter + hint: _id_ + expectResult: &unacknowledgedResult { $$unsetOrMatches: { acknowledged: { $$unsetOrMatches: false } } } + expectEvents: &events + - client: *client0 + events: + - commandStartedEvent: + command: + delete: *collection0Name + deletes: + - q: *filter + hint: { $$type: [ string, object ]} + limit: 0 + writeConcern: { w: 0 } + + - description: "Unacknowledged deleteMany with hint document on 4.4+ server" + runOnRequirements: + - minServerVersion: "4.4.0" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - deleteMany: + filter: *filter + hint: { _id: 1 } + expectResult: *unacknowledgedResult + expectEvents: *events diff --git a/test/spec/crud/unified/bulkWrite-deleteOne-hint-unacknowledged.json b/test/spec/crud/unified/bulkWrite-deleteOne-hint-unacknowledged.json new file mode 100644 index 0000000000..aadf6d9e99 --- /dev/null +++ b/test/spec/crud/unified/bulkWrite-deleteOne-hint-unacknowledged.json @@ -0,0 +1,265 @@ +{ + "description": "bulkWrite-deleteOne-hint-unacknowledged", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "db0" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + } + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "db0", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "Unacknowledged deleteOne with hint string fails with client-side error on pre-4.4 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.2.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "deleteOne": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_" + } + } + ] + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged deleteOne with hint document fails with client-side error on pre-4.4 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.2.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "deleteOne": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ] + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged deleteOne with hint string on 4.4+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.4.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "deleteOne": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_" + } + } + ] + }, + "expectResult": { + "$$unsetOrMatches": { + "acknowledged": { + "$$unsetOrMatches": false + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "delete": "coll0", + "deletes": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "$$type": [ + "string", + "object" + ] + }, + "limit": 1 + } + ], + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + }, + { + "description": "Unacknowledged deleteOne with hint document on 4.4+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.4.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "deleteOne": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ] + }, + "expectResult": { + "$$unsetOrMatches": { + "acknowledged": { + "$$unsetOrMatches": false + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "delete": "coll0", + "deletes": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "$$type": [ + "string", + "object" + ] + }, + "limit": 1 + } + ], + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/bulkWrite-deleteOne-hint-unacknowledged.yml b/test/spec/crud/unified/bulkWrite-deleteOne-hint-unacknowledged.yml new file mode 100644 index 0000000000..820697008e --- /dev/null +++ b/test/spec/crud/unified/bulkWrite-deleteOne-hint-unacknowledged.yml @@ -0,0 +1,97 @@ +description: bulkWrite-deleteOne-hint-unacknowledged + +schemaVersion: '1.0' + +createEntities: + - client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name db0 + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + collectionOptions: + writeConcern: { w: 0 } + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: &documents + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - description: "Unacknowledged deleteOne with hint string fails with client-side error on pre-4.4 server" + runOnRequirements: + - maxServerVersion: "4.2.99" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - deleteOne: + filter: &filter { _id: { $gt: 1 } } + hint: _id_ + expectError: + isClientError: true + expectEvents: &noEvents + - client: *client0 + events: [] + + - description: "Unacknowledged deleteOne with hint document fails with client-side error on pre-4.4 server" + runOnRequirements: + - maxServerVersion: "4.2.99" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - deleteOne: + filter: *filter + hint: { _id: 1 } + expectError: + isClientError: true + expectEvents: *noEvents + + - description: "Unacknowledged deleteOne with hint string on 4.4+ server" + runOnRequirements: + - minServerVersion: "4.4.0" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - deleteOne: + filter: *filter + hint: _id_ + expectResult: &unacknowledgedResult { $$unsetOrMatches: { acknowledged: { $$unsetOrMatches: false } } } + expectEvents: &events + - client: *client0 + events: + - commandStartedEvent: + command: + delete: *collection0Name + deletes: + - q: *filter + hint: { $$type: [ string, object ]} + limit: 1 + writeConcern: { w: 0 } + + - description: "Unacknowledged deleteOne with hint document on 4.4+ server" + runOnRequirements: + - minServerVersion: "4.4.0" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - deleteOne: + filter: *filter + hint: { _id: 1 } + expectResult: *unacknowledgedResult + expectEvents: *events diff --git a/test/spec/crud/unified/bulkWrite-replaceOne-hint-unacknowledged.json b/test/spec/crud/unified/bulkWrite-replaceOne-hint-unacknowledged.json new file mode 100644 index 0000000000..e54cd704df --- /dev/null +++ b/test/spec/crud/unified/bulkWrite-replaceOne-hint-unacknowledged.json @@ -0,0 +1,293 @@ +{ + "description": "bulkWrite-replaceOne-hint-unacknowledged", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "db0" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + } + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "db0", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "Unacknowledged replaceOne with hint string fails with client-side error on pre-4.2 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.0.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "replaceOne": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 111 + }, + "hint": "_id_" + } + } + ] + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged replaceOne with hint document fails with client-side error on pre-4.2 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.0.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "replaceOne": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 111 + }, + "hint": { + "_id": 1 + } + } + } + ] + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged replaceOne with hint string on 4.2+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.2.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "replaceOne": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 111 + }, + "hint": "_id_" + } + } + ] + }, + "expectResult": { + "$$unsetOrMatches": { + "acknowledged": { + "$$unsetOrMatches": false + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "update": "coll0", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "x": 111 + }, + "multi": { + "$$unsetOrMatches": false + }, + "upsert": { + "$$unsetOrMatches": false + }, + "hint": { + "$$type": [ + "string", + "object" + ] + } + } + ], + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + }, + { + "description": "Unacknowledged replaceOne with hint document on 4.2+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.2.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "replaceOne": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 111 + }, + "hint": { + "_id": 1 + } + } + } + ] + }, + "expectResult": { + "$$unsetOrMatches": { + "acknowledged": { + "$$unsetOrMatches": false + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "update": "coll0", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "x": 111 + }, + "multi": { + "$$unsetOrMatches": false + }, + "upsert": { + "$$unsetOrMatches": false + }, + "hint": { + "$$type": [ + "string", + "object" + ] + } + } + ], + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/bulkWrite-replaceOne-hint-unacknowledged.yml b/test/spec/crud/unified/bulkWrite-replaceOne-hint-unacknowledged.yml new file mode 100644 index 0000000000..d656c5fc6b --- /dev/null +++ b/test/spec/crud/unified/bulkWrite-replaceOne-hint-unacknowledged.yml @@ -0,0 +1,103 @@ +description: bulkWrite-replaceOne-hint-unacknowledged + +schemaVersion: '1.0' + +createEntities: + - client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name db0 + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + collectionOptions: + writeConcern: { w: 0 } + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: &documents + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - description: "Unacknowledged replaceOne with hint string fails with client-side error on pre-4.2 server" + runOnRequirements: + - maxServerVersion: "4.0.99" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - replaceOne: + filter: &filter { _id: { $gt: 1 } } + replacement: &replacement { x: 111 } + hint: _id_ + expectError: + isClientError: true + expectEvents: &noEvents + - client: *client0 + events: [] + + - description: "Unacknowledged replaceOne with hint document fails with client-side error on pre-4.2 server" + runOnRequirements: + - maxServerVersion: "4.0.99" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - replaceOne: + filter: *filter + replacement: *replacement + hint: { _id: 1 } + expectError: + isClientError: true + expectEvents: *noEvents + + - description: "Unacknowledged replaceOne with hint string on 4.2+ server" + runOnRequirements: + - minServerVersion: "4.2.0" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - replaceOne: + filter: *filter + replacement: *replacement + hint: _id_ + expectResult: &unacknowledgedResult { $$unsetOrMatches: { acknowledged: { $$unsetOrMatches: false } } } + expectEvents: &events + - client: *client0 + events: + - commandStartedEvent: + command: + update: *collection0Name + updates: + - q: *filter + u: *replacement + multi: { $$unsetOrMatches: false } + upsert: { $$unsetOrMatches: false } + hint: { $$type: [ string, object ]} + writeConcern: { w: 0 } + + - description: "Unacknowledged replaceOne with hint document on 4.2+ server" + runOnRequirements: + - minServerVersion: "4.2.0" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - replaceOne: + filter: *filter + replacement: *replacement + hint: { _id: 1 } + expectResult: *unacknowledgedResult + expectEvents: *events diff --git a/test/spec/crud/unified/bulkWrite-update-hint-clientError.yml b/test/spec/crud/unified/bulkWrite-update-hint-clientError.yml index df1eae485e..cf75a7c450 100644 --- a/test/spec/crud/unified/bulkWrite-update-hint-clientError.yml +++ b/test/spec/crud/unified/bulkWrite-update-hint-clientError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: bulkWrite-update-hint-clientError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/bulkWrite-update-hint-serverError.yml b/test/spec/crud/unified/bulkWrite-update-hint-serverError.yml index 0b4ed166e0..64310a2eaf 100644 --- a/test/spec/crud/unified/bulkWrite-update-hint-serverError.yml +++ b/test/spec/crud/unified/bulkWrite-update-hint-serverError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: bulkWrite-update-hint-serverError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/bulkWrite-update-hint.yml b/test/spec/crud/unified/bulkWrite-update-hint.yml index 9f5a0e080e..e739074ea2 100644 --- a/test/spec/crud/unified/bulkWrite-update-hint.yml +++ b/test/spec/crud/unified/bulkWrite-update-hint.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: bulkWrite-update-hint schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/bulkWrite-updateMany-hint-unacknowledged.json b/test/spec/crud/unified/bulkWrite-updateMany-hint-unacknowledged.json new file mode 100644 index 0000000000..87478918d2 --- /dev/null +++ b/test/spec/crud/unified/bulkWrite-updateMany-hint-unacknowledged.json @@ -0,0 +1,305 @@ +{ + "description": "bulkWrite-updateMany-hint-unacknowledged", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "db0" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + } + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "db0", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "Unacknowledged updateMany with hint string fails with client-side error on pre-4.2 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.0.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "updateMany": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + } + ] + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged updateMany with hint document fails with client-side error on pre-4.2 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.0.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "updateMany": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ] + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged updateMany with hint string on 4.2+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.2.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "updateMany": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + } + ] + }, + "expectResult": { + "$$unsetOrMatches": { + "acknowledged": { + "$$unsetOrMatches": false + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "update": "coll0", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": true, + "upsert": { + "$$unsetOrMatches": false + }, + "hint": { + "$$type": [ + "string", + "object" + ] + } + } + ], + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + }, + { + "description": "Unacknowledged updateMany with hint document on 4.2+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.2.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "updateMany": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ] + }, + "expectResult": { + "$$unsetOrMatches": { + "acknowledged": { + "$$unsetOrMatches": false + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "update": "coll0", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": true, + "upsert": { + "$$unsetOrMatches": false + }, + "hint": { + "$$type": [ + "string", + "object" + ] + } + } + ], + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/bulkWrite-updateMany-hint-unacknowledged.yml b/test/spec/crud/unified/bulkWrite-updateMany-hint-unacknowledged.yml new file mode 100644 index 0000000000..7cb376c90c --- /dev/null +++ b/test/spec/crud/unified/bulkWrite-updateMany-hint-unacknowledged.yml @@ -0,0 +1,104 @@ +description: bulkWrite-updateMany-hint-unacknowledged + +schemaVersion: '1.0' + +createEntities: + - client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name db0 + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + collectionOptions: + writeConcern: { w: 0 } + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: &documents + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - description: "Unacknowledged updateMany with hint string fails with client-side error on pre-4.2 server" + runOnRequirements: + - maxServerVersion: "4.0.99" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - updateMany: + filter: &filter { _id: { $gt: 1 } } + update: &update { $inc: { x: 1 } } + hint: _id_ + expectError: + isClientError: true + expectEvents: &noEvents + - client: *client0 + events: [] + + - description: "Unacknowledged updateMany with hint document fails with client-side error on pre-4.2 server" + runOnRequirements: + - maxServerVersion: "4.0.99" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - updateMany: + filter: *filter + update: *update + hint: { _id: 1 } + expectError: + isClientError: true + expectEvents: *noEvents + + - description: "Unacknowledged updateMany with hint string on 4.2+ server" + runOnRequirements: + - minServerVersion: "4.2.0" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - updateMany: + filter: *filter + update: *update + hint: _id_ + expectResult: &unacknowledgedResult { $$unsetOrMatches: { acknowledged: { $$unsetOrMatches: false } } } + expectEvents: &events + - client: *client0 + events: + - commandStartedEvent: + command: + update: *collection0Name + updates: + - q: *filter + u: *update + multi: true + upsert: { $$unsetOrMatches: false } + hint: { $$type: [ string, object ]} + writeConcern: { w: 0 } + + - description: "Unacknowledged updateMany with hint document on 4.2+ server" + runOnRequirements: + - minServerVersion: "4.2.0" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - updateMany: + filter: *filter + update: *update + hint: { _id: 1 } + expectResult: *unacknowledgedResult + expectEvents: *events diff --git a/test/spec/crud/unified/bulkWrite-updateOne-hint-unacknowledged.json b/test/spec/crud/unified/bulkWrite-updateOne-hint-unacknowledged.json new file mode 100644 index 0000000000..1345f6b536 --- /dev/null +++ b/test/spec/crud/unified/bulkWrite-updateOne-hint-unacknowledged.json @@ -0,0 +1,305 @@ +{ + "description": "bulkWrite-updateOne-hint-unacknowledged", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "db0" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + } + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "db0", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "Unacknowledged updateOne with hint string fails with client-side error on pre-4.2 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.0.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "updateOne": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + } + ] + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged updateOne with hint document fails with client-side error on pre-4.2 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.0.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "updateOne": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ] + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged updateOne with hint string on 4.2+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.2.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "updateOne": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + } + ] + }, + "expectResult": { + "$$unsetOrMatches": { + "acknowledged": { + "$$unsetOrMatches": false + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "update": "coll0", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": { + "$$unsetOrMatches": false + }, + "upsert": { + "$$unsetOrMatches": false + }, + "hint": { + "$$type": [ + "string", + "object" + ] + } + } + ], + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + }, + { + "description": "Unacknowledged updateOne with hint document on 4.2+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.2.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "updateOne": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ] + }, + "expectResult": { + "$$unsetOrMatches": { + "acknowledged": { + "$$unsetOrMatches": false + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "update": "coll0", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": { + "$$unsetOrMatches": false + }, + "upsert": { + "$$unsetOrMatches": false + }, + "hint": { + "$$type": [ + "string", + "object" + ] + } + } + ], + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/bulkWrite-updateOne-hint-unacknowledged.yml b/test/spec/crud/unified/bulkWrite-updateOne-hint-unacknowledged.yml new file mode 100644 index 0000000000..5997c54c2b --- /dev/null +++ b/test/spec/crud/unified/bulkWrite-updateOne-hint-unacknowledged.yml @@ -0,0 +1,103 @@ +description: bulkWrite-updateOne-hint-unacknowledged + +schemaVersion: '1.0' + +createEntities: + - client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name db0 + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + collectionOptions: + writeConcern: { w: 0 } + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: &documents + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - description: "Unacknowledged updateOne with hint string fails with client-side error on pre-4.2 server" + runOnRequirements: + - maxServerVersion: "4.0.99" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - updateOne: + filter: &filter { _id: { $gt: 1 } } + update: &update { $inc: { x: 1 } } + hint: _id_ + expectError: + isClientError: true + expectEvents: &noEvents + - client: *client0 + events: [] + + - description: "Unacknowledged updateOne with hint document fails with client-side error on pre-4.2 server" + runOnRequirements: + - maxServerVersion: "4.0.99" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - updateOne: + filter: *filter + update: *update + hint: { _id: 1 } + expectError: + isClientError: true + expectEvents: *noEvents + + - description: "Unacknowledged updateOne with hint string on 4.2+ server" + runOnRequirements: + - minServerVersion: "4.2.0" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - updateOne: + filter: *filter + update: *update + hint: _id_ + expectResult: &unacknowledgedResult { $$unsetOrMatches: { acknowledged: { $$unsetOrMatches: false } } } + expectEvents: &events + - client: *client0 + events: + - commandStartedEvent: + command: + update: *collection0Name + updates: + - q: *filter + u: *update + multi: { $$unsetOrMatches: false } + upsert: { $$unsetOrMatches: false } + hint: { $$type: [ string, object ]} + writeConcern: { w: 0 } + + - description: "Unacknowledged updateOne with hint document on 4.2+ server" + runOnRequirements: + - minServerVersion: "4.2.0" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - updateOne: + filter: *filter + update: *update + hint: { _id: 1 } + expectResult: *unacknowledgedResult + expectEvents: *events diff --git a/test/spec/crud/unified/bulkWrite.json b/test/spec/crud/unified/bulkWrite.json new file mode 100644 index 0000000000..59b33cbac5 --- /dev/null +++ b/test/spec/crud/unified/bulkWrite.json @@ -0,0 +1,829 @@ +{ + "description": "bulkWrite", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "2.6" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "BulkWrite with deleteOne operations", + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "deleteOne": { + "filter": { + "_id": 3 + } + } + }, + { + "deleteOne": { + "filter": { + "_id": 2 + } + } + } + ], + "ordered": true + }, + "expectResult": { + "deletedCount": 1, + "insertedCount": 0, + "insertedIds": { + "$$unsetOrMatches": {} + }, + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 0, + "upsertedIds": {} + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "BulkWrite with deleteMany operations", + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "deleteMany": { + "filter": { + "x": { + "$lt": 11 + } + } + } + }, + { + "deleteMany": { + "filter": { + "x": { + "$lte": 22 + } + } + } + } + ], + "ordered": true + }, + "expectResult": { + "deletedCount": 2, + "insertedCount": 0, + "insertedIds": { + "$$unsetOrMatches": {} + }, + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 0, + "upsertedIds": {} + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [] + } + ] + }, + { + "description": "BulkWrite with insertOne operations", + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "insertOne": { + "document": { + "_id": 3, + "x": 33 + } + } + }, + { + "insertOne": { + "document": { + "_id": 4, + "x": 44 + } + } + } + ], + "ordered": true + }, + "expectResult": { + "deletedCount": 0, + "insertedCount": 2, + "insertedIds": { + "$$unsetOrMatches": { + "0": 3, + "1": 4 + } + }, + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 0, + "upsertedIds": {} + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ] + }, + { + "description": "BulkWrite with replaceOne operations", + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "replaceOne": { + "filter": { + "_id": 3 + }, + "replacement": { + "x": 33 + } + } + }, + { + "replaceOne": { + "filter": { + "_id": 1 + }, + "replacement": { + "x": 12 + } + } + }, + { + "replaceOne": { + "filter": { + "_id": 3 + }, + "replacement": { + "x": 33 + }, + "upsert": true + } + } + ], + "ordered": true + }, + "expectResult": { + "deletedCount": 0, + "insertedCount": 0, + "insertedIds": { + "$$unsetOrMatches": {} + }, + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 1, + "upsertedIds": { + "2": 3 + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "BulkWrite with updateOne operations", + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "updateOne": { + "filter": { + "_id": 0 + }, + "update": { + "$set": { + "x": 0 + } + } + } + }, + { + "updateOne": { + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "x": 11 + } + } + } + }, + { + "updateOne": { + "filter": { + "_id": 2 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "updateOne": { + "filter": { + "_id": 3 + }, + "update": { + "$set": { + "x": 33 + } + }, + "upsert": true + } + } + ], + "ordered": true + }, + "expectResult": { + "deletedCount": 0, + "insertedCount": 0, + "insertedIds": { + "$$unsetOrMatches": {} + }, + "matchedCount": 2, + "modifiedCount": 1, + "upsertedCount": 1, + "upsertedIds": { + "3": 3 + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 23 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "BulkWrite with updateMany operations", + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "updateMany": { + "filter": { + "x": { + "$lt": 11 + } + }, + "update": { + "$set": { + "x": 0 + } + } + } + }, + { + "updateMany": { + "filter": { + "x": { + "$lte": 22 + } + }, + "update": { + "$unset": { + "y": 1 + } + } + } + }, + { + "updateMany": { + "filter": { + "x": { + "$lte": 22 + } + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "updateMany": { + "filter": { + "_id": 3 + }, + "update": { + "$set": { + "x": 33 + } + }, + "upsert": true + } + } + ], + "ordered": true + }, + "expectResult": { + "deletedCount": 0, + "insertedCount": 0, + "insertedIds": { + "$$unsetOrMatches": {} + }, + "matchedCount": 4, + "modifiedCount": 2, + "upsertedCount": 1, + "upsertedIds": { + "3": 3 + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 23 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "BulkWrite with mixed ordered operations", + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "insertOne": { + "document": { + "_id": 3, + "x": 33 + } + } + }, + { + "updateOne": { + "filter": { + "_id": 2 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "updateMany": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "insertOne": { + "document": { + "_id": 4, + "x": 44 + } + } + }, + { + "deleteMany": { + "filter": { + "x": { + "$nin": [ + 24, + 34 + ] + } + } + } + }, + { + "replaceOne": { + "filter": { + "_id": 4 + }, + "replacement": { + "_id": 4, + "x": 44 + }, + "upsert": true + } + } + ], + "ordered": true + }, + "expectResult": { + "deletedCount": 2, + "insertedCount": 2, + "insertedIds": { + "$$unsetOrMatches": { + "0": 3, + "3": 4 + } + }, + "matchedCount": 3, + "modifiedCount": 3, + "upsertedCount": 1, + "upsertedIds": { + "5": 4 + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 2, + "x": 24 + }, + { + "_id": 3, + "x": 34 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ] + }, + { + "description": "BulkWrite with mixed unordered operations", + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "replaceOne": { + "filter": { + "_id": 3 + }, + "replacement": { + "_id": 3, + "x": 33 + }, + "upsert": true + } + }, + { + "deleteOne": { + "filter": { + "_id": 1 + } + } + }, + { + "updateOne": { + "filter": { + "_id": 2 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + } + ], + "ordered": false + }, + "expectResult": { + "deletedCount": 1, + "insertedCount": 0, + "insertedIds": { + "$$unsetOrMatches": {} + }, + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 1, + "upsertedIds": { + "0": 3 + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 2, + "x": 23 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "BulkWrite continue-on-error behavior with unordered (preexisting duplicate key)", + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "insertOne": { + "document": { + "_id": 2, + "x": 22 + } + } + }, + { + "insertOne": { + "document": { + "_id": 3, + "x": 33 + } + } + }, + { + "insertOne": { + "document": { + "_id": 4, + "x": 44 + } + } + } + ], + "ordered": false + }, + "expectError": { + "isError": true, + "expectResult": { + "deletedCount": 0, + "insertedCount": 2, + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 0, + "upsertedIds": {} + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ] + }, + { + "description": "BulkWrite continue-on-error behavior with unordered (duplicate key in requests)", + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "insertOne": { + "document": { + "_id": 3, + "x": 33 + } + } + }, + { + "insertOne": { + "document": { + "_id": 3, + "x": 33 + } + } + }, + { + "insertOne": { + "document": { + "_id": 4, + "x": 44 + } + } + } + ], + "ordered": false + }, + "expectError": { + "isError": true, + "expectResult": { + "deletedCount": 0, + "insertedCount": 2, + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 0, + "upsertedIds": {} + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/bulkWrite.yml b/test/spec/crud/unified/bulkWrite.yml new file mode 100644 index 0000000000..677e6725c4 --- /dev/null +++ b/test/spec/crud/unified/bulkWrite.yml @@ -0,0 +1,448 @@ +description: bulkWrite + +schemaVersion: '1.0' + +runOnRequirements: + - + minServerVersion: '2.6' + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'BulkWrite with deleteOne operations' + operations: + - + object: *collection0 + name: bulkWrite + arguments: + # Note: as in the "DeleteOne when many documents match" test in + # deleteOne.yml, we omit a deleteOne operation that might match + # multiple documents as that would hinder our ability to assert the + # final state of the collection under test. + requests: + - + # does not match an existing document + deleteOne: + filter: { _id: 3 } + - + # deletes the matched document + deleteOne: + filter: { _id: 2 } + ordered: true + expectResult: + deletedCount: 1 + insertedCount: 0 + insertedIds: + $$unsetOrMatches: { } + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'BulkWrite with deleteMany operations' + operations: + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + # does not match any existing documents + deleteMany: + filter: { x: { $lt: 11 } } + - + # deletes the matched documents + deleteMany: + filter: { x: { $lte: 22 } } + ordered: true + expectResult: + deletedCount: 2 + insertedCount: 0 + insertedIds: + $$unsetOrMatches: { } + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: [] + - + description: 'BulkWrite with insertOne operations' + operations: + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + insertOne: + document: { _id: 3, x: 33 } + - + insertOne: + document: { _id: 4, x: 44 } + ordered: true + expectResult: + deletedCount: 0 + insertedCount: 2 + insertedIds: + $$unsetOrMatches: + '0': 3 + '1': 4 + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - { _id: 4, x: 44 } + - + description: 'BulkWrite with replaceOne operations' + operations: + - + object: *collection0 + name: bulkWrite + arguments: + # Note: as in the "ReplaceOne when many documents match" test in + # replaceOne.yml, we omit a replaceOne operation that might match + # multiple documents as that would hinder our ability to assert the + # final state of the collection under test. + requests: + - + # does not match an existing document + replaceOne: + filter: { _id: 3 } + replacement: { x: 33 } + - + # modifies the matched document + replaceOne: + filter: { _id: 1 } + replacement: { x: 12 } + - + # does not match an existing document and upserts + replaceOne: + filter: { _id: 3 } + replacement: { x: 33 } + upsert: true + ordered: true + expectResult: + deletedCount: 0 + insertedCount: 0 + insertedIds: + $$unsetOrMatches: { } + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 1 + upsertedIds: { '2': 3 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'BulkWrite with updateOne operations' + operations: + - + object: *collection0 + name: bulkWrite + arguments: + # Note: as in the "UpdateOne when many documents match" test in + # updateOne.yml, we omit an updateOne operation that might match + # multiple documents as that would hinder our ability to assert the + # final state of the collection under test. + requests: + - + # does not match an existing document + updateOne: + filter: { _id: 0 } + update: { $set: { x: 0 } } + - + # does not modify the matched document + updateOne: + filter: { _id: 1 } + update: { $set: { x: 11 } } + - + # modifies the matched document + updateOne: + filter: { _id: 2 } + update: { $inc: { x: 1 } } + - + # does not match an existing document and upserts + updateOne: + filter: { _id: 3 } + update: { $set: { x: 33 } } + upsert: true + ordered: true + expectResult: + deletedCount: 0 + insertedCount: 0 + insertedIds: + $$unsetOrMatches: { } + matchedCount: 2 + modifiedCount: 1 + upsertedCount: 1 + upsertedIds: { '3': 3 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 23 } + - { _id: 3, x: 33 } + - + description: 'BulkWrite with updateMany operations' + operations: + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + # does not match any existing documents + updateMany: + filter: { x: { $lt: 11 } } + update: { $set: { x: 0 } } + - + # does not modify the matched documents + updateMany: + filter: { x: { $lte: 22 } } + update: { $unset: { y: 1 } } + - + # modifies the matched documents + updateMany: + filter: { x: { $lte: 22 } } + update: { $inc: { x: 1 } } + - + # does not match any existing documents and upserts + updateMany: + filter: { _id: 3 } + update: { $set: { x: 33 } } + upsert: true + ordered: true + expectResult: + deletedCount: 0 + insertedCount: 0 + insertedIds: + $$unsetOrMatches: { } + matchedCount: 4 + modifiedCount: 2 + upsertedCount: 1 + upsertedIds: { '3': 3 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 23 } + - { _id: 3, x: 33 } + - + description: 'BulkWrite with mixed ordered operations' + operations: + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + insertOne: + document: { _id: 3, x: 33 } + - + updateOne: + filter: { _id: 2 } + update: { $inc: { x: 1 } } + - + updateMany: + filter: { _id: { $gt: 1 } } + update: { $inc: { x: 1 } } + - + insertOne: + document: { _id: 4, x: 44 } + - + deleteMany: + filter: { x: { $nin: [ 24, 34 ] } } + - + replaceOne: + filter: { _id: 4 } + replacement: { _id: 4, x: 44 } + upsert: true + ordered: true + expectResult: + deletedCount: 2 + insertedCount: 2 + insertedIds: + $$unsetOrMatches: + '0': 3 + '3': 4 + matchedCount: 3 + modifiedCount: 3 + upsertedCount: 1 + upsertedIds: { '5': 4 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 24 } + - { _id: 3, x: 34 } + - { _id: 4, x: 44 } + - + description: 'BulkWrite with mixed unordered operations' + operations: + - + object: *collection0 + name: bulkWrite + arguments: + # We omit inserting multiple documents and updating documents that may + # not exist at the start of this test as we cannot assume the order in + # which the operations will execute. + requests: + - + replaceOne: + filter: { _id: 3 } + replacement: { _id: 3, x: 33 } + upsert: true + - + deleteOne: + filter: { _id: 1 } + - + updateOne: + filter: { _id: 2 } + update: { $inc: { x: 1 } } + ordered: false + expectResult: + deletedCount: 1 + insertedCount: 0 + insertedIds: + $$unsetOrMatches: { } + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 1 + upsertedIds: { '0': 3 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 23 } + - { _id: 3, x: 33 } + - + description: 'BulkWrite continue-on-error behavior with unordered (preexisting duplicate key)' + operations: + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + insertOne: + document: { _id: 2, x: 22 } + - + insertOne: + document: { _id: 3, x: 33 } + - + insertOne: + document: { _id: 4, x: 44 } + ordered: false + expectError: + isError: true + expectResult: + deletedCount: 0 + insertedCount: 2 + # Since the map of insertedIds is generated before execution it + # could indicate inserts that did not actually succeed. We omit this + # field rather than expect drivers to provide an accurate map + # filtered by write errors. + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - { _id: 4, x: 44 } + - + description: 'BulkWrite continue-on-error behavior with unordered (duplicate key in requests)' + operations: + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + insertOne: + document: { _id: 3, x: 33 } + - + insertOne: + document: { _id: 3, x: 33 } + - + insertOne: + document: { _id: 4, x: 44 } + ordered: false + expectError: + isError: true + expectResult: + deletedCount: 0 + insertedCount: 2 + # Since the map of insertedIds is generated before execution it + # could indicate inserts that did not actually succeed. We omit this + # field rather than expect drivers to provide an accurate map + # filtered by write errors. + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - { _id: 4, x: 44 } diff --git a/test/spec/crud/unified/client-bulkWrite-delete-options.json b/test/spec/crud/unified/client-bulkWrite-delete-options.json new file mode 100644 index 0000000000..5bdf2b124a --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-delete-options.json @@ -0,0 +1,267 @@ +{ + "description": "client bulkWrite delete options", + "schemaVersion": "1.1", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "_yamlAnchors": { + "namespace": "crud-tests.coll0", + "collation": { + "locale": "simple" + }, + "hint": "_id_" + }, + "tests": [ + { + "description": "client bulk write delete with collation", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + }, + "collation": { + "locale": "simple" + } + } + }, + { + "deleteMany": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": { + "$gt": 1 + } + }, + "collation": { + "locale": "simple" + } + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 3, + "insertResults": {}, + "updateResults": {}, + "deleteResults": { + "0": { + "deletedCount": 1 + }, + "1": { + "deletedCount": 2 + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "delete": 0, + "filter": { + "_id": 1 + }, + "collation": { + "locale": "simple" + }, + "multi": false + }, + { + "delete": 0, + "filter": { + "_id": { + "$gt": 1 + } + }, + "collation": { + "locale": "simple" + }, + "multi": true + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "databaseName": "crud-tests", + "collectionName": "coll0", + "documents": [] + } + ] + }, + { + "description": "client bulk write delete with hint", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + }, + "hint": "_id_" + } + }, + { + "deleteMany": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_" + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 3, + "insertResults": {}, + "updateResults": {}, + "deleteResults": { + "0": { + "deletedCount": 1 + }, + "1": { + "deletedCount": 2 + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "delete": 0, + "filter": { + "_id": 1 + }, + "hint": "_id_", + "multi": false + }, + { + "delete": 0, + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_", + "multi": true + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "databaseName": "crud-tests", + "collectionName": "coll0", + "documents": [] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/client-bulkWrite-delete-options.yml b/test/spec/crud/unified/client-bulkWrite-delete-options.yml new file mode 100644 index 0000000000..db8b9f46d7 --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-delete-options.yml @@ -0,0 +1,136 @@ +description: "client bulkWrite delete options" +schemaVersion: "1.1" +runOnRequirements: + - minServerVersion: "8.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name crud-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +_yamlAnchors: + namespace: &namespace "crud-tests.coll0" + collation: &collation { "locale": "simple" } + hint: &hint _id_ + +tests: + - description: "client bulk write delete with collation" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - deleteOne: + namespace: *namespace + filter: { _id: 1 } + collation: *collation + - deleteMany: + namespace: *namespace + filter: { _id: { $gt: 1 } } + collation: *collation + verboseResults: true + expectResult: + insertedCount: 0 + upsertedCount: 0 + matchedCount: 0 + modifiedCount: 0 + deletedCount: 3 + insertResults: {} + updateResults: {} + deleteResults: + 0: + deletedCount: 1 + 1: + deletedCount: 2 + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + ops: + - delete: 0 + filter: { _id: 1 } + collation: *collation + multi: false + - delete: 0 + filter: { _id: { $gt: 1 } } + collation: *collation + multi: true + nsInfo: + - ns: *namespace + outcome: + - databaseName: *database0Name + collectionName: *collection0Name + documents: [] + - description: "client bulk write delete with hint" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - deleteOne: + namespace: *namespace + filter: { _id: 1 } + hint: *hint + - deleteMany: + namespace: *namespace + filter: { _id: { $gt: 1 } } + hint: *hint + verboseResults: true + expectResult: + insertedCount: 0 + upsertedCount: 0 + matchedCount: 0 + modifiedCount: 0 + deletedCount: 3 + insertResults: {} + updateResults: {} + deleteResults: + 0: + deletedCount: 1 + 1: + deletedCount: 2 + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + ops: + - delete: 0 + filter: { _id: 1 } + hint: *hint + multi: false + - delete: 0 + filter: { _id: { $gt: 1 } } + hint: *hint + multi: true + outcome: + - databaseName: *database0Name + collectionName: *collection0Name + documents: [] diff --git a/test/spec/crud/unified/client-bulkWrite-errorResponse.json b/test/spec/crud/unified/client-bulkWrite-errorResponse.json new file mode 100644 index 0000000000..edf2339d8a --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-errorResponse.json @@ -0,0 +1,68 @@ +{ + "description": "client bulkWrite errorResponse", + "schemaVersion": "1.12", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + } + ], + "_yamlAnchors": { + "namespace": "crud-tests.coll0" + }, + "tests": [ + { + "description": "client bulkWrite operations support errorResponse assertions", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "errorCode": 8 + } + } + } + }, + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 1 + } + } + } + ] + }, + "expectError": { + "errorCode": 8, + "errorResponse": { + "code": 8 + } + } + } + ] + } + ] +} diff --git a/test/spec/crud/unified/client-bulkWrite-errorResponse.yml b/test/spec/crud/unified/client-bulkWrite-errorResponse.yml new file mode 100644 index 0000000000..45e53171ec --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-errorResponse.yml @@ -0,0 +1,37 @@ +description: "client bulkWrite errorResponse" +schemaVersion: "1.12" +runOnRequirements: + - minServerVersion: "8.0" + +createEntities: + - client: + id: &client0 client0 + useMultipleMongoses: false # Avoid setting fail points with multiple mongoses + +_yamlAnchors: + namespace: &namespace "crud-tests.coll0" + +tests: + - description: "client bulkWrite operations support errorResponse assertions" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ bulkWrite ] + errorCode: &errorCode 8 # UnknownError + - object: *client0 + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *namespace + document: { _id: 1 } + expectError: + errorCode: *errorCode + errorResponse: + code: *errorCode diff --git a/test/spec/crud/unified/client-bulkWrite-errors.json b/test/spec/crud/unified/client-bulkWrite-errors.json new file mode 100644 index 0000000000..9f17f85331 --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-errors.json @@ -0,0 +1,454 @@ +{ + "description": "client bulkWrite errors", + "schemaVersion": "1.21", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ], + "uriOptions": { + "retryWrites": false + }, + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "_yamlAnchors": { + "namespace": "crud-tests.coll0", + "writeConcernErrorCode": 91, + "writeConcernErrorMessage": "Replication is being shut down", + "undefinedVarCode": 17276 + }, + "tests": [ + { + "description": "an individual operation fails during an ordered bulkWrite", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + } + } + }, + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "$expr": { + "$eq": [ + "$_id", + "$$id2" + ] + } + } + } + }, + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 3 + } + } + } + ], + "verboseResults": true + }, + "expectError": { + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 1, + "insertResults": {}, + "updateResults": {}, + "deleteResults": { + "0": { + "deletedCount": 1 + } + } + }, + "writeErrors": { + "1": { + "code": 17276 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "an individual operation fails during an unordered bulkWrite", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + } + } + }, + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "$expr": { + "$eq": [ + "$_id", + "$$id2" + ] + } + } + } + }, + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 3 + } + } + } + ], + "verboseResults": true, + "ordered": false + }, + "expectError": { + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 2, + "insertResults": {}, + "updateResults": {}, + "deleteResults": { + "0": { + "deletedCount": 1 + }, + "2": { + "deletedCount": 1 + } + } + }, + "writeErrors": { + "1": { + "code": 17276 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "detailed results are omitted from error when verboseResults is false", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + } + } + }, + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "$expr": { + "$eq": [ + "$_id", + "$$id2" + ] + } + } + } + }, + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 3 + } + } + } + ], + "verboseResults": false + }, + "expectError": { + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 1, + "insertResults": { + "$$unsetOrMatches": {} + }, + "updateResults": { + "$$unsetOrMatches": {} + }, + "deleteResults": { + "$$unsetOrMatches": {} + } + }, + "writeErrors": { + "1": { + "code": 17276 + } + } + } + } + ] + }, + { + "description": "a top-level failure occurs during a bulkWrite", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "errorCode": 8 + } + } + } + }, + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "x": 1 + } + } + } + ], + "verboseResults": true + }, + "expectError": { + "errorCode": 8 + } + } + ] + }, + { + "description": "a bulk write with only errors does not report a partial result", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "$expr": { + "$eq": [ + "$_id", + "$$id2" + ] + } + } + } + } + ], + "verboseResults": true + }, + "expectError": { + "expectResult": { + "$$unsetOrMatches": {} + }, + "writeErrors": { + "0": { + "code": 17276 + } + } + } + } + ] + }, + { + "description": "a write concern error occurs during a bulkWrite", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "writeConcernError": { + "code": 91, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 10 + } + } + } + ], + "verboseResults": true + }, + "expectError": { + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 10 + } + }, + "updateResults": {}, + "deleteResults": {} + }, + "writeConcernErrors": [ + { + "code": 91, + "message": "Replication is being shut down" + } + ] + } + } + ] + }, + { + "description": "an empty list of write models is a client-side error", + "operations": [ + { + "name": "clientBulkWrite", + "object": "client0", + "arguments": { + "models": [], + "verboseResults": true + }, + "expectError": { + "isClientError": true + } + } + ] + } + ] +} diff --git a/test/spec/crud/unified/client-bulkWrite-errors.yml b/test/spec/crud/unified/client-bulkWrite-errors.yml new file mode 100644 index 0000000000..3a420f1429 --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-errors.yml @@ -0,0 +1,240 @@ +description: "client bulkWrite errors" +schemaVersion: "1.21" +runOnRequirements: + - minServerVersion: "8.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + uriOptions: + retryWrites: false + useMultipleMongoses: false # Target a single mongos with failpoint + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name crud-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +_yamlAnchors: + namespace: &namespace "crud-tests.coll0" + writeConcernErrorCode: &writeConcernErrorCode 91 + writeConcernErrorMessage: &writeConcernErrorMessage "Replication is being shut down" + undefinedVarCode: &undefinedVarCode 17276 # Use of an undefined variable + +tests: + - description: "an individual operation fails during an ordered bulkWrite" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - deleteOne: + namespace: *namespace + filter: { _id: 1 } + - deleteOne: + namespace: *namespace + filter: + $expr: + $eq: [ "$_id", "$$id2" ] # Attempt to access a nonexistent let var + - deleteOne: + namespace: *namespace + filter: { _id: 3 } + verboseResults: true + expectError: + expectResult: + insertedCount: 0 + upsertedCount: 0 + matchedCount: 0 + modifiedCount: 0 + deletedCount: 1 + insertResults: {} + updateResults: {} + deleteResults: + 0: + deletedCount: 1 + writeErrors: + 1: + code: *undefinedVarCode + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - description: "an individual operation fails during an unordered bulkWrite" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - deleteOne: + namespace: *namespace + filter: { _id: 1 } + - deleteOne: + namespace: *namespace + filter: + $expr: + $eq: [ "$_id", "$$id2" ] # Attempt to access a nonexistent let var + - deleteOne: + namespace: *namespace + filter: { _id: 3 } + verboseResults: true + ordered: false + expectError: + expectResult: + insertedCount: 0 + upsertedCount: 0 + matchedCount: 0 + modifiedCount: 0 + deletedCount: 2 + insertResults: {} + updateResults: {} + deleteResults: + 0: + deletedCount: 1 + 2: + deletedCount: 1 + writeErrors: + 1: + code: *undefinedVarCode + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 2, x: 22 } + - description: "detailed results are omitted from error when verboseResults is false" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - deleteOne: + namespace: *namespace + filter: { _id: 1 } + - deleteOne: + namespace: *namespace + filter: + $expr: + $eq: [ "$_id", "$$id2" ] # Attempt to access a nonexistent let var + - deleteOne: + namespace: *namespace + filter: { _id: 3 } + verboseResults: false + expectError: + expectResult: + insertedCount: 0 + upsertedCount: 0 + matchedCount: 0 + modifiedCount: 0 + deletedCount: 1 + insertResults: + $$unsetOrMatches: {} + updateResults: + $$unsetOrMatches: {} + deleteResults: + $$unsetOrMatches: {} + writeErrors: + 1: + code: *undefinedVarCode + - description: "a top-level failure occurs during a bulkWrite" + operations: + - object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - bulkWrite + errorCode: 8 # UnknownError + - object: *client0 + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *namespace + document: { x: 1 } + verboseResults: true + expectError: + errorCode: 8 + - description: "a bulk write with only errors does not report a partial result" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - deleteOne: + namespace: *namespace + filter: + $expr: + $eq: [ "$_id", "$$id2" ] # Attempt to access a nonexistent let var + verboseResults: true + expectError: + expectResult: + $$unsetOrMatches: {} # Empty or nonexistent result when no successful writes occurred + writeErrors: + 0: + code: *undefinedVarCode + - description: "a write concern error occurs during a bulkWrite" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - bulkWrite + writeConcernError: + code: *writeConcernErrorCode + errmsg: *writeConcernErrorMessage + - object: *client0 + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *namespace + document: { _id: 10 } + verboseResults: true + expectError: + expectResult: + insertedCount: 1 + upsertedCount: 0 + matchedCount: 0 + modifiedCount: 0 + deletedCount: 0 + insertResults: + 0: + insertedId: 10 + updateResults: {} + deleteResults: {} + writeConcernErrors: + - code: *writeConcernErrorCode + message: *writeConcernErrorMessage + - description: "an empty list of write models is a client-side error" + operations: + - name: clientBulkWrite + object: *client0 + arguments: + models: [] + verboseResults: true + expectError: + isClientError: true diff --git a/test/spec/crud/unified/client-bulkWrite-mixed-namespaces.json b/test/spec/crud/unified/client-bulkWrite-mixed-namespaces.json new file mode 100644 index 0000000000..f90755dc85 --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-mixed-namespaces.json @@ -0,0 +1,314 @@ +{ + "description": "client bulkWrite with mixed namespaces", + "schemaVersion": "1.1", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "db0" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + }, + { + "collection": { + "id": "collection1", + "database": "database0", + "collectionName": "coll1" + } + }, + { + "database": { + "id": "database1", + "client": "client0", + "databaseName": "db1" + } + }, + { + "collection": { + "id": "collection2", + "database": "database1", + "collectionName": "coll2" + } + } + ], + "initialData": [ + { + "databaseName": "db0", + "collectionName": "coll0", + "documents": [] + }, + { + "databaseName": "db0", + "collectionName": "coll1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + }, + { + "databaseName": "db1", + "collectionName": "coll2", + "documents": [ + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ], + "_yamlAnchors": { + "db0Coll0Namespace": "db0.coll0", + "db0Coll1Namespace": "db0.coll1", + "db1Coll2Namespace": "db1.coll2" + }, + "tests": [ + { + "description": "client bulkWrite with mixed namespaces", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "db0.coll0", + "document": { + "_id": 1 + } + } + }, + { + "insertOne": { + "namespace": "db0.coll0", + "document": { + "_id": 2 + } + } + }, + { + "updateOne": { + "namespace": "db0.coll1", + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "deleteOne": { + "namespace": "db1.coll2", + "filter": { + "_id": 3 + } + } + }, + { + "deleteOne": { + "namespace": "db0.coll1", + "filter": { + "_id": 2 + } + } + }, + { + "replaceOne": { + "namespace": "db1.coll2", + "filter": { + "_id": 4 + }, + "replacement": { + "x": 45 + } + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 2, + "upsertedCount": 0, + "matchedCount": 2, + "modifiedCount": 2, + "deletedCount": 2, + "insertResults": { + "0": { + "insertedId": 1 + }, + "1": { + "insertedId": 2 + } + }, + "updateResults": { + "2": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + }, + "5": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + } + }, + "deleteResults": { + "3": { + "deletedCount": 1 + }, + "4": { + "deletedCount": 1 + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "bulkWrite": 1, + "ops": [ + { + "insert": 0, + "document": { + "_id": 1 + } + }, + { + "insert": 0, + "document": { + "_id": 2 + } + }, + { + "update": 1, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": false + }, + { + "delete": 2, + "filter": { + "_id": 3 + }, + "multi": false + }, + { + "delete": 1, + "filter": { + "_id": 2 + }, + "multi": false + }, + { + "update": 2, + "filter": { + "_id": 4 + }, + "updateMods": { + "x": 45 + }, + "multi": false + } + ], + "nsInfo": [ + { + "ns": "db0.coll0" + }, + { + "ns": "db0.coll1" + }, + { + "ns": "db1.coll2" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "databaseName": "db0", + "collectionName": "coll0", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + }, + { + "databaseName": "db0", + "collectionName": "coll1", + "documents": [ + { + "_id": 1, + "x": 12 + } + ] + }, + { + "databaseName": "db1", + "collectionName": "coll2", + "documents": [ + { + "_id": 4, + "x": 45 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/client-bulkWrite-mixed-namespaces.yml b/test/spec/crud/unified/client-bulkWrite-mixed-namespaces.yml new file mode 100644 index 0000000000..4e4cb01e16 --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-mixed-namespaces.yml @@ -0,0 +1,146 @@ +description: "client bulkWrite with mixed namespaces" +schemaVersion: "1.1" +runOnRequirements: + - minServerVersion: "8.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name db0 + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + - collection: + id: &collection1 collection1 + database: *database0 + collectionName: &collection1Name coll1 + - database: + id: &database1 database1 + client: *client0 + databaseName: &database1Name db1 + - collection: + id: &collection2 collection2 + database: *database1 + collectionName: &collection2Name coll2 + +initialData: + - databaseName: *database0Name + collectionName: *collection0Name + documents: [] + - databaseName: *database0Name + collectionName: *collection1Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - databaseName: *database1Name + collectionName: *collection2Name + documents: + - { _id: 3, x: 33 } + - { _id: 4, x: 44 } + +_yamlAnchors: + db0Coll0Namespace: &db0Coll0Namespace "db0.coll0" + db0Coll1Namespace: &db0Coll1Namespace "db0.coll1" + db1Coll2Namespace: &db1Coll2Namespace "db1.coll2" + +tests: + - description: "client bulkWrite with mixed namespaces" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *db0Coll0Namespace + document: { _id: 1 } + - insertOne: + namespace: *db0Coll0Namespace + document: { _id: 2 } + - updateOne: + namespace: *db0Coll1Namespace + filter: { _id: 1 } + update: { $inc: { x: 1 } } + - deleteOne: + namespace: *db1Coll2Namespace + filter: { _id: 3 } + - deleteOne: + namespace: *db0Coll1Namespace + filter: { _id: 2 } + - replaceOne: + namespace: *db1Coll2Namespace + filter: { _id: 4 } + replacement: { x: 45 } + verboseResults: true + expectResult: + insertedCount: 2 + upsertedCount: 0 + matchedCount: 2 + modifiedCount: 2 + deletedCount: 2 + insertResults: + 0: + insertedId: 1 + 1: + insertedId: 2 + updateResults: + 2: + matchedCount: 1 + modifiedCount: 1 + upsertedId: { $$exists: false } + 5: + matchedCount: 1 + modifiedCount: 1 + upsertedId: { $$exists: false } + deleteResults: + 3: + deletedCount: 1 + 4: + deletedCount: 1 + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + bulkWrite: 1 + ops: + - insert: 0 + document: { _id: 1 } + - insert: 0 + document: { _id: 2 } + - update: 1 + filter: { _id: 1 } + updateMods: { $inc: { x: 1 } } + multi: false + - delete: 2 + filter: { _id: 3 } + multi: false + - delete: 1 + filter: { _id: 2 } + multi: false + - update: 2 + filter: { _id: 4 } + updateMods: { x: 45 } + multi: false + nsInfo: + - ns: *db0Coll0Namespace + - ns: *db0Coll1Namespace + - ns: *db1Coll2Namespace + outcome: + - databaseName: *database0Name + collectionName: *collection0Name + documents: + - { _id: 1 } + - { _id: 2 } + - databaseName: *database0Name + collectionName: *collection1Name + documents: + - { _id: 1, x: 12 } + - databaseName: *database1Name + collectionName: *collection2Name + documents: + - { _id: 4, x: 45 } diff --git a/test/spec/crud/unified/client-bulkWrite-options.json b/test/spec/crud/unified/client-bulkWrite-options.json new file mode 100644 index 0000000000..a1e6af3bf3 --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-options.json @@ -0,0 +1,715 @@ +{ + "description": "client bulkWrite top-level options", + "schemaVersion": "1.1", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "client": { + "id": "writeConcernClient", + "uriOptions": { + "w": 1 + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "_yamlAnchors": { + "namespace": "crud-tests.coll0", + "comment": { + "bulk": "write" + }, + "let": { + "id1": 1, + "id2": 2 + }, + "writeConcern": { + "w": "majority" + } + }, + "tests": [ + { + "description": "client bulkWrite comment", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 3, + "x": 33 + } + } + } + ], + "comment": { + "bulk": "write" + }, + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 3 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "comment": { + "bulk": "write" + }, + "ops": [ + { + "insert": 0, + "document": { + "_id": 3, + "x": 33 + } + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "client bulkWrite bypassDocumentValidation", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 3, + "x": 33 + } + } + } + ], + "bypassDocumentValidation": true, + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 3 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "bypassDocumentValidation": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 3, + "x": 33 + } + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "client bulkWrite let", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "updateOne": { + "namespace": "crud-tests.coll0", + "filter": { + "$expr": { + "$eq": [ + "$_id", + "$$id1" + ] + } + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "$expr": { + "$eq": [ + "$_id", + "$$id2" + ] + } + } + } + } + ], + "let": { + "id1": 1, + "id2": 2 + }, + "verboseResults": true + }, + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 1, + "modifiedCount": 1, + "deletedCount": 1, + "insertResults": {}, + "updateResults": { + "0": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + } + }, + "deleteResults": { + "1": { + "deletedCount": 1 + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "let": { + "id1": 1, + "id2": 2 + }, + "ops": [ + { + "update": 0, + "filter": { + "$expr": { + "$eq": [ + "$_id", + "$$id1" + ] + } + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": false + }, + { + "delete": 0, + "filter": { + "$expr": { + "$eq": [ + "$_id", + "$$id2" + ] + } + }, + "multi": false + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "databaseName": "crud-tests", + "collectionName": "coll0", + "documents": [ + { + "_id": 1, + "x": 12 + } + ] + } + ] + }, + { + "description": "client bulkWrite bypassDocumentValidation: false is sent", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 3, + "x": 33 + } + } + } + ], + "bypassDocumentValidation": false, + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 3 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "bypassDocumentValidation": false, + "ops": [ + { + "insert": 0, + "document": { + "_id": 3, + "x": 33 + } + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "client bulkWrite writeConcern", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 3, + "x": 33 + } + } + } + ], + "writeConcern": { + "w": "majority" + }, + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 3 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "writeConcern": { + "w": "majority" + }, + "ops": [ + { + "insert": 0, + "document": { + "_id": 3, + "x": 33 + } + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ] + }, + { + "description": "client bulkWrite inherits writeConcern from client", + "operations": [ + { + "object": "writeConcernClient", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 3, + "x": 33 + } + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 3 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "writeConcernClient", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "writeConcern": { + "w": 1 + }, + "ops": [ + { + "insert": 0, + "document": { + "_id": 3, + "x": 33 + } + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ] + }, + { + "description": "client bulkWrite writeConcern option overrides client writeConcern", + "operations": [ + { + "object": "writeConcernClient", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 3, + "x": 33 + } + } + } + ], + "writeConcern": { + "w": "majority" + }, + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 3 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "writeConcernClient", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "writeConcern": { + "w": "majority" + }, + "ops": [ + { + "insert": 0, + "document": { + "_id": 3, + "x": 33 + } + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/client-bulkWrite-options.yml b/test/spec/crud/unified/client-bulkWrite-options.yml new file mode 100644 index 0000000000..fdcf788799 --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-options.yml @@ -0,0 +1,350 @@ +description: "client bulkWrite top-level options" +schemaVersion: "1.1" +runOnRequirements: + - minServerVersion: "8.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + - client: + id: &writeConcernClient writeConcernClient + uriOptions: + &clientWriteConcern { w: 1 } + observeEvents: [ commandStartedEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name crud-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +_yamlAnchors: + namespace: &namespace "crud-tests.coll0" + comment: &comment { bulk: "write" } + let: &let { id1: 1, id2: 2 } + writeConcern: &majorityWriteConcern { w: "majority" } + +tests: + - description: "client bulkWrite comment" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *namespace + document: { _id: 3, x: 33 } + comment: *comment + verboseResults: true + expectResult: + insertedCount: 1 + upsertedCount: 0 + matchedCount: 0 + modifiedCount: 0 + deletedCount: 0 + insertResults: + 0: + insertedId: 3 + updateResults: {} + deleteResults: {} + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + comment: *comment + ops: + - insert: 0 + document: { _id: 3, x: 33 } + nsInfo: + - ns: *namespace + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - description: "client bulkWrite bypassDocumentValidation" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *namespace + document: { _id: 3, x: 33 } + bypassDocumentValidation: true + verboseResults: true + expectResult: + insertedCount: 1 + upsertedCount: 0 + matchedCount: 0 + modifiedCount: 0 + deletedCount: 0 + insertResults: + 0: + insertedId: 3 + updateResults: {} + deleteResults: {} + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + bypassDocumentValidation: true + ops: + - insert: 0 + document: { _id: 3, x: 33 } + nsInfo: + - ns: *namespace + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - description: "client bulkWrite let" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - updateOne: + namespace: *namespace + filter: + $expr: + $eq: [ "$_id", "$$id1" ] + update: + $inc: { x: 1 } + - deleteOne: + namespace: *namespace + filter: + $expr: + $eq: [ "$_id", "$$id2" ] + let: *let + verboseResults: true + expectResult: + insertedCount: 0 + upsertedCount: 0 + matchedCount: 1 + modifiedCount: 1 + deletedCount: 1 + insertResults: {} + updateResults: + 0: + matchedCount: 1 + modifiedCount: 1 + upsertedId: { $$exists: false } + deleteResults: + 1: + deletedCount: 1 + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + let: *let + ops: + - update: 0 + filter: + $expr: + $eq: [ "$_id", "$$id1" ] + updateMods: { $inc: { x: 1 } } + multi: false + - delete: 0 + filter: + $expr: + $eq: [ "$_id", "$$id2" ] + multi: false + nsInfo: + - ns: *namespace + outcome: + - databaseName: *database0Name + collectionName: *collection0Name + documents: + - { _id: 1, x: 12 } + - description: "client bulkWrite bypassDocumentValidation: false is sent" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *namespace + document: { _id: 3, x: 33 } + bypassDocumentValidation: false + verboseResults: true + expectResult: + insertedCount: 1 + upsertedCount: 0 + matchedCount: 0 + modifiedCount: 0 + deletedCount: 0 + insertResults: + 0: + insertedId: 3 + updateResults: {} + deleteResults: {} + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + bypassDocumentValidation: false + ops: + - insert: 0 + document: { _id: 3, x: 33 } + nsInfo: + - ns: *namespace + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - description: "client bulkWrite writeConcern" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *namespace + document: { _id: 3, x: 33 } + writeConcern: *majorityWriteConcern + verboseResults: true + expectResult: + insertedCount: 1 + upsertedCount: 0 + matchedCount: 0 + modifiedCount: 0 + deletedCount: 0 + insertResults: + 0: + insertedId: 3 + updateResults: {} + deleteResults: {} + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + writeConcern: *majorityWriteConcern + ops: + - insert: 0 + document: { _id: 3, x: 33 } + nsInfo: + - ns: *namespace + - description: "client bulkWrite inherits writeConcern from client" + operations: + - object: *writeConcernClient + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *namespace + document: { _id: 3, x: 33 } + verboseResults: true + expectResult: + insertedCount: 1 + upsertedCount: 0 + matchedCount: 0 + modifiedCount: 0 + deletedCount: 0 + insertResults: + 0: + insertedId: 3 + updateResults: {} + deleteResults: {} + expectEvents: + - client: *writeConcernClient + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + writeConcern: { w: 1 } + ops: + - insert: 0 + document: { _id: 3, x: 33 } + nsInfo: + - ns: *namespace + - description: "client bulkWrite writeConcern option overrides client writeConcern" + operations: + - object: *writeConcernClient + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *namespace + document: { _id: 3, x: 33 } + writeConcern: *majorityWriteConcern + verboseResults: true + expectResult: + insertedCount: 1 + upsertedCount: 0 + matchedCount: 0 + modifiedCount: 0 + deletedCount: 0 + insertResults: + 0: + insertedId: 3 + updateResults: {} + deleteResults: {} + expectEvents: + - client: *writeConcernClient + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + writeConcern: *majorityWriteConcern + ops: + - insert: 0 + document: { _id: 3, x: 33 } + nsInfo: + - ns: *namespace diff --git a/test/spec/crud/unified/client-bulkWrite-ordered.json b/test/spec/crud/unified/client-bulkWrite-ordered.json new file mode 100644 index 0000000000..a55d6619b5 --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-ordered.json @@ -0,0 +1,290 @@ +{ + "description": "client bulkWrite with ordered option", + "schemaVersion": "1.1", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [] + } + ], + "_yamlAnchors": { + "namespace": "crud-tests.coll0" + }, + "tests": [ + { + "description": "client bulkWrite with ordered: false", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 1, + "x": 11 + } + } + } + ], + "verboseResults": true, + "ordered": false + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 1 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": false, + "ops": [ + { + "insert": 0, + "document": { + "_id": 1, + "x": 11 + } + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "client bulkWrite with ordered: true", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 1, + "x": 11 + } + } + } + ], + "verboseResults": true, + "ordered": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 1 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 1, + "x": 11 + } + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "client bulkWrite defaults to ordered: true", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 1, + "x": 11 + } + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 1 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 1, + "x": 11 + } + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/client-bulkWrite-ordered.yml b/test/spec/crud/unified/client-bulkWrite-ordered.yml new file mode 100644 index 0000000000..dc56dcb860 --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-ordered.yml @@ -0,0 +1,152 @@ +description: "client bulkWrite with ordered option" +schemaVersion: "1.1" +runOnRequirements: + - minServerVersion: "8.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name crud-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: [] + +_yamlAnchors: + namespace: &namespace "crud-tests.coll0" + +tests: + - description: "client bulkWrite with ordered: false" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *namespace + document: { _id: 1, x: 11 } + verboseResults: true + ordered: false + expectResult: + insertedCount: 1 + upsertedCount: 0 + matchedCount: 0 + modifiedCount: 0 + deletedCount: 0 + insertResults: + 0: + insertedId: 1 + updateResults: {} + deleteResults: {} + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: false + ops: + - insert: 0 + document: { _id: 1, x: 11 } + nsInfo: + - ns: *namespace + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - description: "client bulkWrite with ordered: true" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *namespace + document: { _id: 1, x: 11 } + verboseResults: true + ordered: true + expectResult: + insertedCount: 1 + upsertedCount: 0 + matchedCount: 0 + modifiedCount: 0 + deletedCount: 0 + insertResults: + 0: + insertedId: 1 + updateResults: {} + deleteResults: {} + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + ops: + - insert: 0 + document: { _id: 1, x: 11 } + nsInfo: + - ns: *namespace + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - description: "client bulkWrite defaults to ordered: true" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *namespace + document: { _id: 1, x: 11 } + verboseResults: true + expectResult: + insertedCount: 1 + upsertedCount: 0 + matchedCount: 0 + modifiedCount: 0 + deletedCount: 0 + insertResults: + 0: + insertedId: 1 + updateResults: {} + deleteResults: {} + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + ops: + - insert: 0 + document: { _id: 1, x: 11 } + nsInfo: + - ns: *namespace + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } diff --git a/test/spec/crud/unified/client-bulkWrite-results.json b/test/spec/crud/unified/client-bulkWrite-results.json new file mode 100644 index 0000000000..97a9e50b21 --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-results.json @@ -0,0 +1,832 @@ +{ + "description": "client bulkWrite results", + "schemaVersion": "1.1", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 5, + "x": 55 + }, + { + "_id": 6, + "x": 66 + }, + { + "_id": 7, + "x": 77 + } + ] + } + ], + "_yamlAnchors": { + "namespace": "crud-tests.coll0" + }, + "tests": [ + { + "description": "client bulkWrite with verboseResults: true returns detailed results", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 8, + "x": 88 + } + } + }, + { + "updateOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "updateMany": { + "namespace": "crud-tests.coll0", + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "update": { + "$inc": { + "x": 2 + } + } + } + }, + { + "replaceOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 4 + }, + "replacement": { + "x": 44 + }, + "upsert": true + } + }, + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 5 + } + } + }, + { + "deleteMany": { + "namespace": "crud-tests.coll0", + "filter": { + "$and": [ + { + "_id": { + "$gt": 5 + } + }, + { + "_id": { + "$lte": 7 + } + } + ] + } + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 1, + "matchedCount": 3, + "modifiedCount": 3, + "deletedCount": 3, + "insertResults": { + "0": { + "insertedId": 8 + } + }, + "updateResults": { + "1": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + }, + "2": { + "matchedCount": 2, + "modifiedCount": 2, + "upsertedId": { + "$$exists": false + } + }, + "3": { + "matchedCount": 1, + "modifiedCount": 0, + "upsertedId": 4 + } + }, + "deleteResults": { + "4": { + "deletedCount": 1 + }, + "5": { + "deletedCount": 2 + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 8, + "x": 88 + } + }, + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": false + }, + { + "update": 0, + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "updateMods": { + "$inc": { + "x": 2 + } + }, + "multi": true + }, + { + "update": 0, + "filter": { + "_id": 4 + }, + "updateMods": { + "x": 44 + }, + "upsert": true, + "multi": false + }, + { + "delete": 0, + "filter": { + "_id": 5 + }, + "multi": false + }, + { + "delete": 0, + "filter": { + "$and": [ + { + "_id": { + "$gt": 5 + } + }, + { + "_id": { + "$lte": 7 + } + } + ] + }, + "multi": true + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 24 + }, + { + "_id": 3, + "x": 35 + }, + { + "_id": 4, + "x": 44 + }, + { + "_id": 8, + "x": 88 + } + ] + } + ] + }, + { + "description": "client bulkWrite with verboseResults: false omits detailed results", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 8, + "x": 88 + } + } + }, + { + "updateOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "updateMany": { + "namespace": "crud-tests.coll0", + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "update": { + "$inc": { + "x": 2 + } + } + } + }, + { + "replaceOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 4 + }, + "replacement": { + "x": 44 + }, + "upsert": true + } + }, + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 5 + } + } + }, + { + "deleteMany": { + "namespace": "crud-tests.coll0", + "filter": { + "$and": [ + { + "_id": { + "$gt": 5 + } + }, + { + "_id": { + "$lte": 7 + } + } + ] + } + } + } + ], + "verboseResults": false + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 1, + "matchedCount": 3, + "modifiedCount": 3, + "deletedCount": 3, + "insertResults": { + "$$unsetOrMatches": {} + }, + "updateResults": { + "$$unsetOrMatches": {} + }, + "deleteResults": { + "$$unsetOrMatches": {} + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": true, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 8, + "x": 88 + } + }, + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": false + }, + { + "update": 0, + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "updateMods": { + "$inc": { + "x": 2 + } + }, + "multi": true + }, + { + "update": 0, + "filter": { + "_id": 4 + }, + "updateMods": { + "x": 44 + }, + "upsert": true, + "multi": false + }, + { + "delete": 0, + "filter": { + "_id": 5 + }, + "multi": false + }, + { + "delete": 0, + "filter": { + "$and": [ + { + "_id": { + "$gt": 5 + } + }, + { + "_id": { + "$lte": 7 + } + } + ] + }, + "multi": true + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 24 + }, + { + "_id": 3, + "x": 35 + }, + { + "_id": 4, + "x": 44 + }, + { + "_id": 8, + "x": 88 + } + ] + } + ] + }, + { + "description": "client bulkWrite defaults to verboseResults: false", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 8, + "x": 88 + } + } + }, + { + "updateOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "updateMany": { + "namespace": "crud-tests.coll0", + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "update": { + "$inc": { + "x": 2 + } + } + } + }, + { + "replaceOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 4 + }, + "replacement": { + "x": 44 + }, + "upsert": true + } + }, + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 5 + } + } + }, + { + "deleteMany": { + "namespace": "crud-tests.coll0", + "filter": { + "$and": [ + { + "_id": { + "$gt": 5 + } + }, + { + "_id": { + "$lte": 7 + } + } + ] + } + } + } + ] + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 1, + "matchedCount": 3, + "modifiedCount": 3, + "deletedCount": 3, + "insertResults": { + "$$unsetOrMatches": {} + }, + "updateResults": { + "$$unsetOrMatches": {} + }, + "deleteResults": { + "$$unsetOrMatches": {} + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": true, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 8, + "x": 88 + } + }, + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": false + }, + { + "update": 0, + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "updateMods": { + "$inc": { + "x": 2 + } + }, + "multi": true + }, + { + "update": 0, + "filter": { + "_id": 4 + }, + "updateMods": { + "x": 44 + }, + "upsert": true, + "multi": false + }, + { + "delete": 0, + "filter": { + "_id": 5 + }, + "multi": false + }, + { + "delete": 0, + "filter": { + "$and": [ + { + "_id": { + "$gt": 5 + } + }, + { + "_id": { + "$lte": 7 + } + } + ] + }, + "multi": true + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 24 + }, + { + "_id": 3, + "x": 35 + }, + { + "_id": 4, + "x": 44 + }, + { + "_id": 8, + "x": 88 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/client-bulkWrite-results.yml b/test/spec/crud/unified/client-bulkWrite-results.yml new file mode 100644 index 0000000000..eb001bbb42 --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-results.yml @@ -0,0 +1,311 @@ +description: "client bulkWrite results" +schemaVersion: "1.1" +runOnRequirements: + - minServerVersion: "8.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name crud-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - { _id: 5, x: 55 } + - { _id: 6, x: 66 } + - { _id: 7, x: 77 } + +_yamlAnchors: + namespace: &namespace "crud-tests.coll0" + +tests: + - description: "client bulkWrite with verboseResults: true returns detailed results" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *namespace + document: { _id: 8, x: 88 } + - updateOne: + namespace: *namespace + filter: { _id: 1 } + update: { $inc: { x: 1 } } + - updateMany: + namespace: *namespace + filter: + $and: [ { _id: { $gt: 1 } }, { _id: { $lte: 3 } } ] + update: { $inc: { x: 2 } } + - replaceOne: + namespace: *namespace + filter: { _id: 4 } + replacement: { x: 44 } + upsert: true + - deleteOne: + namespace: *namespace + filter: { _id: 5 } + - deleteMany: + namespace: *namespace + filter: + $and: [ { _id: { $gt: 5 } }, { _id: { $lte: 7 } } ] + verboseResults: true + expectResult: + insertedCount: 1 + upsertedCount: 1 + matchedCount: 3 + modifiedCount: 3 + deletedCount: 3 + insertResults: + 0: + insertedId: 8 + updateResults: + 1: + matchedCount: 1 + modifiedCount: 1 + upsertedId: { $$exists: false } + 2: + matchedCount: 2 + modifiedCount: 2 + upsertedId: { $$exists: false } + 3: + matchedCount: 1 + modifiedCount: 0 + upsertedId: 4 + deleteResults: + 4: + deletedCount: 1 + 5: + deletedCount: 2 + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + ops: + - insert: 0 + document: { _id: 8, x: 88 } + - update: 0 + filter: { _id: 1 } + updateMods: { $inc: { x: 1 } } + multi: false + - update: 0 + filter: + $and: [ { _id: { $gt: 1 } }, { _id: { $lte: 3 } } ] + updateMods: { $inc: { x: 2 } } + multi: true + - update: 0 + filter: { _id: 4 } + updateMods: { x: 44 } + upsert: true + multi: false + - delete: 0 + filter: { _id: 5 } + multi: false + - delete: 0 + filter: + $and: [ { _id: { $gt: 5 } }, { _id: { $lte: 7 } } ] + multi: true + nsInfo: + - ns: *namespace + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 24 } + - { _id: 3, x: 35 } + - { _id: 4, x: 44 } + - { _id: 8, x: 88 } + - description: "client bulkWrite with verboseResults: false omits detailed results" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *namespace + document: { _id: 8, x: 88 } + - updateOne: + namespace: *namespace + filter: { _id: 1 } + update: { $inc: { x: 1 } } + - updateMany: + namespace: *namespace + filter: + $and: [ { _id: { $gt: 1 } }, { _id: { $lte: 3 } } ] + update: { $inc: { x: 2 } } + - replaceOne: + namespace: *namespace + filter: { _id: 4 } + replacement: { x: 44 } + upsert: true + - deleteOne: + namespace: *namespace + filter: { _id: 5 } + - deleteMany: + namespace: *namespace + filter: + $and: [ { _id: { $gt: 5 } }, { _id: { $lte: 7 } } ] + verboseResults: false + expectResult: + insertedCount: 1 + upsertedCount: 1 + matchedCount: 3 + modifiedCount: 3 + deletedCount: 3 + insertResults: + $$unsetOrMatches: {} + updateResults: + $$unsetOrMatches: {} + deleteResults: + $$unsetOrMatches: {} + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: true + ordered: true + ops: + - insert: 0 + document: { _id: 8, x: 88 } + - update: 0 + filter: { _id: 1 } + updateMods: { $inc: { x: 1 } } + multi: false + - update: 0 + filter: + $and: [ { _id: { $gt: 1 } }, { _id: { $lte: 3 } } ] + updateMods: { $inc: { x: 2 } } + multi: true + - update: 0 + filter: { _id: 4 } + updateMods: { x: 44 } + upsert: true + multi: false + - delete: 0 + filter: { _id: 5 } + multi: false + - delete: 0 + filter: + $and: [ { _id: { $gt: 5 } }, { _id: { $lte: 7 } } ] + multi: true + nsInfo: + - ns: *namespace + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 24 } + - { _id: 3, x: 35 } + - { _id: 4, x: 44 } + - { _id: 8, x: 88 } + - description: "client bulkWrite defaults to verboseResults: false" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *namespace + document: { _id: 8, x: 88 } + - updateOne: + namespace: *namespace + filter: { _id: 1 } + update: { $inc: { x: 1 } } + - updateMany: + namespace: *namespace + filter: + $and: [ { _id: { $gt: 1 } }, { _id: { $lte: 3 } } ] + update: { $inc: { x: 2 } } + - replaceOne: + namespace: *namespace + filter: { _id: 4 } + replacement: { x: 44 } + upsert: true + - deleteOne: + namespace: *namespace + filter: { _id: 5 } + - deleteMany: + namespace: *namespace + filter: + $and: [ { _id: { $gt: 5 } }, { _id: { $lte: 7 } } ] + expectResult: + insertedCount: 1 + upsertedCount: 1 + matchedCount: 3 + modifiedCount: 3 + deletedCount: 3 + insertResults: + $$unsetOrMatches: {} + updateResults: + $$unsetOrMatches: {} + deleteResults: + $$unsetOrMatches: {} + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: true + ordered: true + ops: + - insert: 0 + document: { _id: 8, x: 88 } + - update: 0 + filter: { _id: 1 } + updateMods: { $inc: { x: 1 } } + multi: false + - update: 0 + filter: + $and: [ { _id: { $gt: 1 } }, { _id: { $lte: 3 } } ] + updateMods: { $inc: { x: 2 } } + multi: true + - update: 0 + filter: { _id: 4 } + updateMods: { x: 44 } + upsert: true + multi: false + - delete: 0 + filter: { _id: 5 } + multi: false + - delete: 0 + filter: + $and: [ { _id: { $gt: 5 } }, { _id: { $lte: 7 } } ] + multi: true + nsInfo: + - ns: *namespace + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 24 } + - { _id: 3, x: 35 } + - { _id: 4, x: 44 } + - { _id: 8, x: 88 } diff --git a/test/spec/crud/unified/client-bulkWrite-update-options.json b/test/spec/crud/unified/client-bulkWrite-update-options.json new file mode 100644 index 0000000000..93a2774e5f --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-update-options.json @@ -0,0 +1,948 @@ +{ + "description": "client bulkWrite update options", + "schemaVersion": "1.1", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "array": [ + 1, + 2, + 3 + ] + }, + { + "_id": 2, + "array": [ + 1, + 2, + 3 + ] + }, + { + "_id": 3, + "array": [ + 1, + 2, + 3 + ] + }, + { + "_id": 4, + "array": [ + 1, + 2, + 3 + ] + } + ] + } + ], + "_yamlAnchors": { + "namespace": "crud-tests.coll0", + "collation": { + "locale": "simple" + }, + "hint": "_id_" + }, + "tests": [ + { + "description": "client bulkWrite update with arrayFilters", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "updateOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "array.$[i]": 4 + } + }, + "arrayFilters": [ + { + "i": { + "$gte": 2 + } + } + ] + } + }, + { + "updateMany": { + "namespace": "crud-tests.coll0", + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "update": { + "$set": { + "array.$[i]": 5 + } + }, + "arrayFilters": [ + { + "i": { + "$gte": 2 + } + } + ] + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 3, + "modifiedCount": 3, + "deletedCount": 0, + "insertResults": {}, + "updateResults": { + "0": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + }, + "1": { + "matchedCount": 2, + "modifiedCount": 2, + "upsertedId": { + "$$exists": false + } + } + }, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$set": { + "array.$[i]": 4 + } + }, + "arrayFilters": [ + { + "i": { + "$gte": 2 + } + } + ], + "multi": false + }, + { + "update": 0, + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "updateMods": { + "$set": { + "array.$[i]": 5 + } + }, + "arrayFilters": [ + { + "i": { + "$gte": 2 + } + } + ], + "multi": true + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "databaseName": "crud-tests", + "collectionName": "coll0", + "documents": [ + { + "_id": 1, + "array": [ + 1, + 4, + 4 + ] + }, + { + "_id": 2, + "array": [ + 1, + 5, + 5 + ] + }, + { + "_id": 3, + "array": [ + 1, + 5, + 5 + ] + }, + { + "_id": 4, + "array": [ + 1, + 2, + 3 + ] + } + ] + } + ] + }, + { + "description": "client bulkWrite update with collation", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "updateOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "array": [ + 1, + 2, + 4 + ] + } + }, + "collation": { + "locale": "simple" + } + } + }, + { + "updateMany": { + "namespace": "crud-tests.coll0", + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "update": { + "$set": { + "array": [ + 1, + 2, + 5 + ] + } + }, + "collation": { + "locale": "simple" + } + } + }, + { + "replaceOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 4 + }, + "replacement": { + "array": [ + 1, + 2, + 6 + ] + }, + "collation": { + "locale": "simple" + } + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 4, + "modifiedCount": 4, + "deletedCount": 0, + "insertResults": {}, + "updateResults": { + "0": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + }, + "1": { + "matchedCount": 2, + "modifiedCount": 2, + "upsertedId": { + "$$exists": false + } + }, + "2": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + } + }, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$set": { + "array": [ + 1, + 2, + 4 + ] + } + }, + "collation": { + "locale": "simple" + }, + "multi": false + }, + { + "update": 0, + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "updateMods": { + "$set": { + "array": [ + 1, + 2, + 5 + ] + } + }, + "collation": { + "locale": "simple" + }, + "multi": true + }, + { + "update": 0, + "filter": { + "_id": 4 + }, + "updateMods": { + "array": [ + 1, + 2, + 6 + ] + }, + "collation": { + "locale": "simple" + }, + "multi": false + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "databaseName": "crud-tests", + "collectionName": "coll0", + "documents": [ + { + "_id": 1, + "array": [ + 1, + 2, + 4 + ] + }, + { + "_id": 2, + "array": [ + 1, + 2, + 5 + ] + }, + { + "_id": 3, + "array": [ + 1, + 2, + 5 + ] + }, + { + "_id": 4, + "array": [ + 1, + 2, + 6 + ] + } + ] + } + ] + }, + { + "description": "client bulkWrite update with hint", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "updateOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "array": [ + 1, + 2, + 4 + ] + } + }, + "hint": "_id_" + } + }, + { + "updateMany": { + "namespace": "crud-tests.coll0", + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "update": { + "$set": { + "array": [ + 1, + 2, + 5 + ] + } + }, + "hint": "_id_" + } + }, + { + "replaceOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 4 + }, + "replacement": { + "array": [ + 1, + 2, + 6 + ] + }, + "hint": "_id_" + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 4, + "modifiedCount": 4, + "deletedCount": 0, + "insertResults": {}, + "updateResults": { + "0": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + }, + "1": { + "matchedCount": 2, + "modifiedCount": 2, + "upsertedId": { + "$$exists": false + } + }, + "2": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + } + }, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$set": { + "array": [ + 1, + 2, + 4 + ] + } + }, + "hint": "_id_", + "multi": false + }, + { + "update": 0, + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "updateMods": { + "$set": { + "array": [ + 1, + 2, + 5 + ] + } + }, + "hint": "_id_", + "multi": true + }, + { + "update": 0, + "filter": { + "_id": 4 + }, + "updateMods": { + "array": [ + 1, + 2, + 6 + ] + }, + "hint": "_id_", + "multi": false + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "databaseName": "crud-tests", + "collectionName": "coll0", + "documents": [ + { + "_id": 1, + "array": [ + 1, + 2, + 4 + ] + }, + { + "_id": 2, + "array": [ + 1, + 2, + 5 + ] + }, + { + "_id": 3, + "array": [ + 1, + 2, + 5 + ] + }, + { + "_id": 4, + "array": [ + 1, + 2, + 6 + ] + } + ] + } + ] + }, + { + "description": "client bulkWrite update with upsert", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "updateOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 5 + }, + "update": { + "$set": { + "array": [ + 1, + 2, + 4 + ] + } + }, + "upsert": true + } + }, + { + "replaceOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 6 + }, + "replacement": { + "array": [ + 1, + 2, + 6 + ] + }, + "upsert": true + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 0, + "upsertedCount": 2, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": {}, + "updateResults": { + "0": { + "matchedCount": 1, + "modifiedCount": 0, + "upsertedId": 5 + }, + "1": { + "matchedCount": 1, + "modifiedCount": 0, + "upsertedId": 6 + } + }, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "update": 0, + "filter": { + "_id": 5 + }, + "updateMods": { + "$set": { + "array": [ + 1, + 2, + 4 + ] + } + }, + "upsert": true, + "multi": false + }, + { + "update": 0, + "filter": { + "_id": 6 + }, + "updateMods": { + "array": [ + 1, + 2, + 6 + ] + }, + "upsert": true, + "multi": false + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "databaseName": "crud-tests", + "collectionName": "coll0", + "documents": [ + { + "_id": 1, + "array": [ + 1, + 2, + 3 + ] + }, + { + "_id": 2, + "array": [ + 1, + 2, + 3 + ] + }, + { + "_id": 3, + "array": [ + 1, + 2, + 3 + ] + }, + { + "_id": 4, + "array": [ + 1, + 2, + 3 + ] + }, + { + "_id": 5, + "array": [ + 1, + 2, + 4 + ] + }, + { + "_id": 6, + "array": [ + 1, + 2, + 6 + ] + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/client-bulkWrite-update-options.yml b/test/spec/crud/unified/client-bulkWrite-update-options.yml new file mode 100644 index 0000000000..fe188a490c --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-update-options.yml @@ -0,0 +1,337 @@ +description: "client bulkWrite update options" +schemaVersion: "1.1" +runOnRequirements: + - minServerVersion: "8.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name crud-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, array: [ 1, 2, 3 ] } + - { _id: 2, array: [ 1, 2, 3 ] } + - { _id: 3, array: [ 1, 2, 3 ] } + - { _id: 4, array: [ 1, 2, 3 ] } + +_yamlAnchors: + namespace: &namespace "crud-tests.coll0" + collation: &collation { "locale": "simple" } + hint: &hint _id_ + +tests: + - description: "client bulkWrite update with arrayFilters" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - updateOne: + namespace: *namespace + filter: { _id: 1 } + update: + $set: + array.$[i]: 4 + arrayFilters: [ i: { $gte: 2 } ] + - updateMany: + namespace: *namespace + filter: + $and: [ { _id: { $gt: 1 } }, { _id: { $lte: 3 } } ] + update: + $set: + array.$[i]: 5 + arrayFilters: [ i: { $gte: 2 } ] + verboseResults: true + expectResult: + insertedCount: 0 + upsertedCount: 0 + matchedCount: 3 + modifiedCount: 3 + deletedCount: 0 + insertResults: {} + updateResults: + 0: + matchedCount: 1 + modifiedCount: 1 + upsertedId: { $$exists: false } + 1: + matchedCount: 2 + modifiedCount: 2 + upsertedId: { $$exists: false } + deleteResults: {} + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + ops: + - update: 0 + filter: { _id: 1 } + updateMods: + $set: + array.$[i]: 4 + arrayFilters: [ i: { $gte: 2 } ] + multi: false + - update: 0 + filter: + $and: [ { _id: { $gt: 1 } }, { _id: { $lte: 3 } } ] + updateMods: + $set: + array.$[i]: 5 + arrayFilters: [ i: { $gte: 2 } ] + multi: true + nsInfo: + - ns: *namespace + outcome: + - databaseName: *database0Name + collectionName: *collection0Name + documents: + - { _id: 1, array: [ 1, 4, 4 ] } + - { _id: 2, array: [ 1, 5, 5 ] } + - { _id: 3, array: [ 1, 5, 5 ] } + - { _id: 4, array: [ 1, 2, 3 ] } + - description: "client bulkWrite update with collation" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - updateOne: + namespace: *namespace + filter: { _id: 1 } + update: { $set: { array: [ 1, 2, 4 ] } } + collation: *collation + - updateMany: + namespace: *namespace + filter: + $and: [ { _id: { $gt: 1 } }, { _id: { $lte: 3 } } ] + update: { $set: { array: [ 1, 2, 5 ] } } + collation: *collation + - replaceOne: + namespace: *namespace + filter: { _id: 4 } + replacement: { array: [ 1, 2, 6 ] } + collation: *collation + verboseResults: true + expectResult: + insertedCount: 0 + upsertedCount: 0 + matchedCount: 4 + modifiedCount: 4 + deletedCount: 0 + insertResults: {} + updateResults: + 0: + matchedCount: 1 + modifiedCount: 1 + upsertedId: { $$exists: false } + 1: + matchedCount: 2 + modifiedCount: 2 + upsertedId: { $$exists: false } + 2: + matchedCount: 1 + modifiedCount: 1 + upsertedId: { $$exists: false } + deleteResults: {} + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + ops: + - update: 0 + filter: { _id: 1 } + updateMods: { $set: { array: [ 1, 2, 4 ] } } + collation: *collation + multi: false + - update: 0 + filter: + $and: [ { _id: { $gt: 1 } }, { _id: { $lte: 3 } } ] + updateMods: { $set: { array: [ 1, 2, 5 ] } } + collation: *collation + multi: true + - update: 0 + filter: { _id: 4 } + updateMods: { array: [ 1, 2, 6 ] } + collation: *collation + multi: false + nsInfo: + - ns: *namespace + outcome: + - databaseName: *database0Name + collectionName: *collection0Name + documents: + - { _id: 1, array: [ 1, 2, 4 ] } + - { _id: 2, array: [ 1, 2, 5 ] } + - { _id: 3, array: [ 1, 2, 5 ] } + - { _id: 4, array: [ 1, 2, 6 ] } + - description: "client bulkWrite update with hint" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - updateOne: + namespace: *namespace + filter: { _id: 1 } + update: { $set: { array: [ 1, 2, 4 ] } } + hint: *hint + - updateMany: + namespace: *namespace + filter: + $and: [ { _id: { $gt: 1 } }, { _id: { $lte: 3 } } ] + update: { $set: { array: [ 1, 2, 5 ] } } + hint: *hint + - replaceOne: + namespace: *namespace + filter: { _id: 4 } + replacement: { array: [ 1, 2, 6 ] } + hint: *hint + verboseResults: true + expectResult: + insertedCount: 0 + upsertedCount: 0 + matchedCount: 4 + modifiedCount: 4 + deletedCount: 0 + insertResults: {} + updateResults: + 0: + matchedCount: 1 + modifiedCount: 1 + upsertedId: { $$exists: false } + 1: + matchedCount: 2 + modifiedCount: 2 + upsertedId: { $$exists: false } + 2: + matchedCount: 1 + modifiedCount: 1 + upsertedId: { $$exists: false } + deleteResults: {} + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + ops: + - update: 0 + filter: { _id: 1 } + updateMods: { $set: { array: [ 1, 2, 4 ] } } + hint: *hint + multi: false + - update: 0 + filter: + $and: [ { _id: { $gt: 1 } }, { _id: { $lte: 3 } } ] + updateMods: { $set: { array: [ 1, 2, 5 ] } } + hint: *hint + multi: true + - update: 0 + filter: { _id: 4 } + updateMods: { array: [ 1, 2, 6 ] } + hint: *hint + multi: false + nsInfo: + - ns: *namespace + outcome: + - databaseName: *database0Name + collectionName: *collection0Name + documents: + - { _id: 1, array: [ 1, 2, 4 ] } + - { _id: 2, array: [ 1, 2, 5 ] } + - { _id: 3, array: [ 1, 2, 5 ] } + - { _id: 4, array: [ 1, 2, 6 ] } + - description: "client bulkWrite update with upsert" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - updateOne: + namespace: *namespace + filter: { _id: 5 } + update: { $set: { array: [ 1, 2, 4 ] } } + upsert: true + - replaceOne: + namespace: *namespace + filter: { _id: 6 } + replacement: { array: [ 1, 2, 6 ] } + upsert: true + verboseResults: true + expectResult: + insertedCount: 0 + upsertedCount: 2 + matchedCount: 0 + modifiedCount: 0 + deletedCount: 0 + insertResults: {} + updateResults: + 0: + matchedCount: 1 + modifiedCount: 0 + upsertedId: 5 + 1: + matchedCount: 1 + modifiedCount: 0 + upsertedId: 6 + deleteResults: {} + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + ops: + - update: 0 + filter: { _id: 5 } + updateMods: { $set: { array: [ 1, 2, 4 ] } } + upsert: true + multi: false + - update: 0 + filter: { _id: 6 } + updateMods: { array: [ 1, 2, 6 ] } + upsert: true + multi: false + nsInfo: + - ns: *namespace + outcome: + - databaseName: *database0Name + collectionName: *collection0Name + documents: + - { _id: 1, array: [ 1, 2, 3 ] } + - { _id: 2, array: [ 1, 2, 3 ] } + - { _id: 3, array: [ 1, 2, 3 ] } + - { _id: 4, array: [ 1, 2, 3 ] } + - { _id: 5, array: [ 1, 2, 4 ] } + - { _id: 6, array: [ 1, 2, 6 ] } diff --git a/test/spec/crud/unified/client-bulkWrite-update-pipeline.json b/test/spec/crud/unified/client-bulkWrite-update-pipeline.json new file mode 100644 index 0000000000..57b6c9c1ba --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-update-pipeline.json @@ -0,0 +1,257 @@ +{ + "description": "client bulkWrite update pipeline", + "schemaVersion": "1.1", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 1 + }, + { + "_id": 2, + "x": 2 + } + ] + } + ], + "_yamlAnchors": { + "namespace": "crud-tests.coll0" + }, + "tests": [ + { + "description": "client bulkWrite updateOne with pipeline", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "updateOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + }, + "update": [ + { + "$addFields": { + "foo": 1 + } + } + ] + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 1, + "modifiedCount": 1, + "deletedCount": 0, + "insertResults": {}, + "updateResults": { + "0": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + } + }, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": [ + { + "$addFields": { + "foo": 1 + } + } + ], + "multi": false + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "databaseName": "crud-tests", + "collectionName": "coll0", + "documents": [ + { + "_id": 1, + "x": 1, + "foo": 1 + }, + { + "_id": 2, + "x": 2 + } + ] + } + ] + }, + { + "description": "client bulkWrite updateMany with pipeline", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "updateMany": { + "namespace": "crud-tests.coll0", + "filter": {}, + "update": [ + { + "$addFields": { + "foo": 1 + } + } + ] + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 2, + "modifiedCount": 2, + "deletedCount": 0, + "insertResults": {}, + "updateResults": { + "0": { + "matchedCount": 2, + "modifiedCount": 2, + "upsertedId": { + "$$exists": false + } + } + }, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "update": 0, + "filter": {}, + "updateMods": [ + { + "$addFields": { + "foo": 1 + } + } + ], + "multi": true + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "databaseName": "crud-tests", + "collectionName": "coll0", + "documents": [ + { + "_id": 1, + "x": 1, + "foo": 1 + }, + { + "_id": 2, + "x": 2, + "foo": 1 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/client-bulkWrite-update-pipeline.yml b/test/spec/crud/unified/client-bulkWrite-update-pipeline.yml new file mode 100644 index 0000000000..fe0e29a508 --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-update-pipeline.yml @@ -0,0 +1,132 @@ +description: "client bulkWrite update pipeline" +schemaVersion: "1.1" +runOnRequirements: + - minServerVersion: "8.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name crud-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - {_id: 1, x: 1} + - {_id: 2, x: 2} + +_yamlAnchors: + namespace: &namespace "crud-tests.coll0" + +tests: + - description: "client bulkWrite updateOne with pipeline" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - updateOne: + namespace: *namespace + filter: { _id: 1 } + update: + - $addFields: + foo: 1 + verboseResults: true + expectResult: + insertedCount: 0 + upsertedCount: 0 + matchedCount: 1 + modifiedCount: 1 + deletedCount: 0 + insertResults: {} + updateResults: + 0: + matchedCount: 1 + modifiedCount: 1 + upsertedId: { "$$exists": false } + deleteResults: {} + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + ops: + - update: 0 + filter: { _id: 1 } + updateMods: + - $addFields: + foo: 1 + multi: false + nsInfo: + - ns: *namespace + outcome: + - databaseName: *database0Name + collectionName: *collection0Name + documents: + - {_id: 1, x: 1, foo: 1} + - {_id: 2, x: 2 } + + - description: "client bulkWrite updateMany with pipeline" + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - updateMany: + namespace: *namespace + filter: {} + update: + - $addFields: + foo: 1 + verboseResults: true + expectResult: + insertedCount: 0 + upsertedCount: 0 + matchedCount: 2 + modifiedCount: 2 + deletedCount: 0 + insertResults: {} + updateResults: + 0: + matchedCount: 2 + modifiedCount: 2 + upsertedId: { "$$exists": false } + deleteResults: {} + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + ops: + - update: 0 + filter: { } + updateMods: + - $addFields: + foo: 1 + multi: true + nsInfo: + - ns: *namespace + outcome: + - databaseName: *database0Name + collectionName: *collection0Name + documents: + - {_id: 1, x: 1, foo: 1} + - {_id: 2, x: 2, foo: 1} diff --git a/test/spec/crud/unified/unacknowledged-bulkWrite-delete-hint-clientError.json b/test/spec/crud/unified/client-bulkWrite-update-validation.json similarity index 51% rename from test/spec/crud/unified/unacknowledged-bulkWrite-delete-hint-clientError.json rename to test/spec/crud/unified/client-bulkWrite-update-validation.json index dbaa2e84f4..617e711338 100644 --- a/test/spec/crud/unified/unacknowledged-bulkWrite-delete-hint-clientError.json +++ b/test/spec/crud/unified/client-bulkWrite-update-validation.json @@ -1,6 +1,6 @@ { - "description": "unacknowledged-bulkWrite-delete-hint-clientError", - "schemaVersion": "1.0", + "description": "client-bulkWrite-update-validation", + "schemaVersion": "1.1", "createEntities": [ { "client": { @@ -14,26 +14,21 @@ "database": { "id": "database0", "client": "client0", - "databaseName": "crud-v2" + "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", - "collectionName": "BulkWrite_delete_hint", - "collectionOptions": { - "writeConcern": { - "w": 0 - } - } + "collectionName": "coll0" } } ], "initialData": [ { - "collectionName": "BulkWrite_delete_hint", - "databaseName": "crud-v2", + "collectionName": "coll0", + "databaseName": "crud-tests", "documents": [ { "_id": 1, @@ -46,46 +41,39 @@ { "_id": 3, "x": 33 - }, - { - "_id": 4, - "x": 44 } ] } ], + "_yamlAnchors": { + "namespace": "crud-tests.coll0" + }, "tests": [ { - "description": "Unacknowledged bulkWrite deleteOne with hints fails with client-side error", + "description": "client bulkWrite replaceOne prohibits atomic modifiers", "operations": [ { - "object": "collection0", - "name": "bulkWrite", + "name": "clientBulkWrite", + "object": "client0", "arguments": { - "requests": [ + "models": [ { - "deleteOne": { + "replaceOne": { + "namespace": "crud-tests.coll0", "filter": { "_id": 1 }, - "hint": "_id_" - } - }, - { - "deleteOne": { - "filter": { - "_id": 2 - }, - "hint": { - "_id": 1 + "replacement": { + "$set": { + "x": 22 + } } } } - ], - "ordered": true + ] }, "expectError": { - "isError": true + "isClientError": true } } ], @@ -97,8 +85,8 @@ ], "outcome": [ { - "collectionName": "BulkWrite_delete_hint", - "databaseName": "crud-v2", + "collectionName": "coll0", + "databaseName": "crud-tests", "documents": [ { "_id": 1, @@ -111,50 +99,89 @@ { "_id": 3, "x": 33 - }, - { - "_id": 4, - "x": 44 } ] } ] }, { - "description": "Unacknowledged bulkWrite deleteMany with hints fails with client-side error", + "description": "client bulkWrite updateOne requires atomic modifiers", "operations": [ { - "object": "collection0", - "name": "bulkWrite", + "name": "clientBulkWrite", + "object": "client0", "arguments": { - "requests": [ + "models": [ { - "deleteMany": { + "updateOne": { + "namespace": "crud-tests.coll0", "filter": { - "_id": { - "$lt": 3 - } + "_id": 1 }, - "hint": "_id_" + "update": { + "x": 22 + } } - }, + } + ] + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "client bulkWrite updateMany requires atomic modifiers", + "operations": [ + { + "name": "clientBulkWrite", + "object": "client0", + "arguments": { + "models": [ { - "deleteMany": { + "updateMany": { + "namespace": "crud-tests.coll0", "filter": { "_id": { - "$gte": 4 + "$gt": 1 } }, - "hint": { - "_id": 1 + "update": { + "x": 44 } } } - ], - "ordered": true + ] }, "expectError": { - "isError": true + "isClientError": true } } ], @@ -166,8 +193,8 @@ ], "outcome": [ { - "collectionName": "BulkWrite_delete_hint", - "databaseName": "crud-v2", + "collectionName": "coll0", + "databaseName": "crud-tests", "documents": [ { "_id": 1, @@ -180,10 +207,6 @@ { "_id": 3, "x": 33 - }, - { - "_id": 4, - "x": 44 } ] } diff --git a/test/spec/crud/unified/client-bulkWrite-update-validation.yml b/test/spec/crud/unified/client-bulkWrite-update-validation.yml new file mode 100644 index 0000000000..478554c322 --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-update-validation.yml @@ -0,0 +1,79 @@ +description: "client-bulkWrite-update-validation" + +schemaVersion: "1.1" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name crud-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + +initialData: &initialData + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +_yamlAnchors: + namespace: &namespace "crud-tests.coll0" + +tests: + - description: "client bulkWrite replaceOne prohibits atomic modifiers" + operations: + - name: clientBulkWrite + object: *client0 + arguments: + models: + - replaceOne: + namespace: *namespace + filter: { _id: 1 } + replacement: { $set: { x: 22 } } + expectError: + isClientError: true + expectEvents: + - client: *client0 + events: [] + outcome: *initialData + + - description: "client bulkWrite updateOne requires atomic modifiers" + operations: + - name: clientBulkWrite + object: *client0 + arguments: + models: + - updateOne: + namespace: *namespace + filter: { _id: 1 } + update: { x: 22 } + expectError: + isClientError: true + expectEvents: + - client: *client0 + events: [] + outcome: *initialData + + - description: "client bulkWrite updateMany requires atomic modifiers" + operations: + - name: clientBulkWrite + object: *client0 + arguments: + models: + - updateMany: + namespace: *namespace + filter: { _id: { $gt: 1 } } + update: { x: 44 } + expectError: + isClientError: true + expectEvents: + - client: *client0 + events: [] + outcome: *initialData diff --git a/test/spec/crud/unified/count-collation.json b/test/spec/crud/unified/count-collation.json new file mode 100644 index 0000000000..eef65e0880 --- /dev/null +++ b/test/spec/crud/unified/count-collation.json @@ -0,0 +1,83 @@ +{ + "description": "count-collation", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "3.4", + "serverless": "forbid" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": "ping" + } + ] + } + ], + "tests": [ + { + "description": "Count documents with collation", + "operations": [ + { + "object": "collection0", + "name": "countDocuments", + "arguments": { + "filter": { + "x": "ping" + }, + "collation": { + "locale": "en_US", + "strength": 2 + } + }, + "expectResult": 1 + } + ] + }, + { + "description": "Deprecated count with collation", + "operations": [ + { + "object": "collection0", + "name": "count", + "arguments": { + "filter": { + "x": "ping" + }, + "collation": { + "locale": "en_US", + "strength": 2 + } + }, + "expectResult": 1 + } + ] + } + ] +} diff --git a/test/spec/crud/unified/count-collation.yml b/test/spec/crud/unified/count-collation.yml new file mode 100644 index 0000000000..692a3c6988 --- /dev/null +++ b/test/spec/crud/unified/count-collation.yml @@ -0,0 +1,57 @@ +description: count-collation + +schemaVersion: '1.4' + +runOnRequirements: + - + minServerVersion: '3.4' + serverless: forbid + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: ping } + +tests: + - + description: 'Count documents with collation' + operations: + - + object: *collection0 + name: countDocuments + arguments: + filter: { x: ping } + # https://www.mongodb.com/docs/manual/reference/collation/#collation-document + collation: + locale: en_US + strength: 2 + expectResult: 1 + - + description: 'Deprecated count with collation' + operations: + - + object: *collection0 + name: count + arguments: + filter: { x: ping } + collation: + locale: en_US + strength: 2 + expectResult: 1 diff --git a/test/spec/crud/unified/count-empty.json b/test/spec/crud/unified/count-empty.json new file mode 100644 index 0000000000..29d8d76f67 --- /dev/null +++ b/test/spec/crud/unified/count-empty.json @@ -0,0 +1,71 @@ +{ + "description": "count-empty", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [] + } + ], + "tests": [ + { + "description": "Estimated document count with empty collection", + "operations": [ + { + "object": "collection0", + "name": "estimatedDocumentCount", + "arguments": {}, + "expectResult": 0 + } + ] + }, + { + "description": "Count documents with empty collection", + "operations": [ + { + "object": "collection0", + "name": "countDocuments", + "arguments": { + "filter": {} + }, + "expectResult": 0 + } + ] + }, + { + "description": "Deprecated count with empty collection", + "operations": [ + { + "object": "collection0", + "name": "count", + "arguments": { + "filter": {} + }, + "expectResult": 0 + } + ] + } + ] +} diff --git a/test/spec/crud/unified/count-empty.yml b/test/spec/crud/unified/count-empty.yml new file mode 100644 index 0000000000..a5d5ae35b7 --- /dev/null +++ b/test/spec/crud/unified/count-empty.yml @@ -0,0 +1,52 @@ +description: count-empty + +schemaVersion: '1.0' + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: [] + +tests: + - + description: 'Estimated document count with empty collection' + operations: + - + object: *collection0 + name: estimatedDocumentCount + arguments: { } + expectResult: 0 + - + description: 'Count documents with empty collection' + operations: + - + object: *collection0 + name: countDocuments + arguments: + filter: { } + expectResult: 0 + - + description: 'Deprecated count with empty collection' + operations: + - + object: *collection0 + name: count + arguments: + filter: { } + expectResult: 0 diff --git a/test/spec/crud/unified/count.json b/test/spec/crud/unified/count.json new file mode 100644 index 0000000000..80fff5a30c --- /dev/null +++ b/test/spec/crud/unified/count.json @@ -0,0 +1,148 @@ +{ + "description": "count", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "Estimated document count", + "operations": [ + { + "object": "collection0", + "name": "estimatedDocumentCount", + "arguments": {}, + "expectResult": 3 + } + ] + }, + { + "description": "Count documents without a filter", + "operations": [ + { + "object": "collection0", + "name": "countDocuments", + "arguments": { + "filter": {} + }, + "expectResult": 3 + } + ] + }, + { + "description": "Count documents with a filter", + "operations": [ + { + "object": "collection0", + "name": "countDocuments", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + } + }, + "expectResult": 2 + } + ] + }, + { + "description": "Count documents with skip and limit", + "operations": [ + { + "object": "collection0", + "name": "countDocuments", + "arguments": { + "filter": {}, + "skip": 1, + "limit": 3 + }, + "expectResult": 2 + } + ] + }, + { + "description": "Deprecated count without a filter", + "operations": [ + { + "object": "collection0", + "name": "count", + "arguments": { + "filter": {} + }, + "expectResult": 3 + } + ] + }, + { + "description": "Deprecated count with a filter", + "operations": [ + { + "object": "collection0", + "name": "count", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + } + }, + "expectResult": 2 + } + ] + }, + { + "description": "Deprecated count with skip and limit", + "operations": [ + { + "object": "collection0", + "name": "count", + "arguments": { + "filter": {}, + "skip": 1, + "limit": 3 + }, + "expectResult": 2 + } + ] + } + ] +} diff --git a/test/spec/crud/unified/count.yml b/test/spec/crud/unified/count.yml new file mode 100644 index 0000000000..5f9fbb7633 --- /dev/null +++ b/test/spec/crud/unified/count.yml @@ -0,0 +1,95 @@ +description: count + +schemaVersion: '1.0' + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - + description: 'Estimated document count' + operations: + - + object: *collection0 + name: estimatedDocumentCount + arguments: { } + expectResult: 3 + - + description: 'Count documents without a filter' + operations: + - + object: *collection0 + name: countDocuments + arguments: + filter: { } + expectResult: 3 + - + description: 'Count documents with a filter' + operations: + - + object: *collection0 + name: countDocuments + arguments: + filter: { _id: { $gt: 1 } } + expectResult: 2 + - + description: 'Count documents with skip and limit' + operations: + - + object: *collection0 + name: countDocuments + arguments: + filter: { } + skip: 1 + limit: 3 + expectResult: 2 + - + description: 'Deprecated count without a filter' + operations: + - + object: *collection0 + name: count + arguments: + filter: { } + expectResult: 3 + - + description: 'Deprecated count with a filter' + operations: + - + object: *collection0 + name: count + arguments: + filter: { _id: { $gt: 1 } } + expectResult: 2 + - + description: 'Deprecated count with skip and limit' + operations: + - + object: *collection0 + name: count + arguments: + filter: { } + skip: 1 + limit: 3 + expectResult: 2 diff --git a/test/spec/crud/unified/countDocuments-comment.json b/test/spec/crud/unified/countDocuments-comment.json new file mode 100644 index 0000000000..e6c7ae8170 --- /dev/null +++ b/test/spec/crud/unified/countDocuments-comment.json @@ -0,0 +1,208 @@ +{ + "description": "countDocuments-comment", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "countDocuments-comments-test" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "countDocuments-comments-test", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "countDocuments with document comment", + "runOnRequirements": [ + { + "minServerVersion": "4.4.0" + } + ], + "operations": [ + { + "name": "countDocuments", + "object": "collection0", + "arguments": { + "filter": {}, + "comment": { + "key": "value" + } + }, + "expectResult": 3 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll0", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ], + "comment": { + "key": "value" + } + }, + "commandName": "aggregate", + "databaseName": "countDocuments-comments-test" + } + } + ] + } + ] + }, + { + "description": "countDocuments with string comment", + "runOnRequirements": [ + { + "minServerVersion": "3.6.0" + } + ], + "operations": [ + { + "name": "countDocuments", + "object": "collection0", + "arguments": { + "filter": {}, + "comment": "comment" + }, + "expectResult": 3 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll0", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ], + "comment": "comment" + }, + "commandName": "aggregate", + "databaseName": "countDocuments-comments-test" + } + } + ] + } + ] + }, + { + "description": "countDocuments with document comment on less than 4.4.0 - server error", + "runOnRequirements": [ + { + "minServerVersion": "3.6.0", + "maxServerVersion": "4.3.99" + } + ], + "operations": [ + { + "name": "countDocuments", + "object": "collection0", + "arguments": { + "filter": {}, + "comment": { + "key": "value" + } + }, + "expectError": { + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll0", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ], + "comment": { + "key": "value" + } + }, + "commandName": "aggregate", + "databaseName": "countDocuments-comments-test" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/countDocuments-comment.yml b/test/spec/crud/unified/countDocuments-comment.yml new file mode 100644 index 0000000000..8f1f7bc4b4 --- /dev/null +++ b/test/spec/crud/unified/countDocuments-comment.yml @@ -0,0 +1,92 @@ +description: "countDocuments-comment" + +schemaVersion: "1.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name countDocuments-comments-test + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - description: "countDocuments with document comment" + runOnRequirements: + - minServerVersion: 4.4.0 + operations: + - name: countDocuments + object: *collection0 + arguments: + filter: {} + comment: &documentComment { key: "value" } + expectResult: 3 + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + aggregate: *collection0Name + pipeline: &pipeline + - $match: {} + - $group: { _id: 1, n: { $sum: 1 } } + comment: *documentComment + commandName: aggregate + databaseName: *database0Name + + - description: "countDocuments with string comment" + runOnRequirements: + - minServerVersion: 3.6.0 + operations: + - name: countDocuments + object: *collection0 + arguments: + filter: {} + comment: &stringComment "comment" + expectResult: 3 + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + aggregate: *collection0Name + pipeline: *pipeline + comment: *stringComment + commandName: aggregate + databaseName: *database0Name + + - description: "countDocuments with document comment on less than 4.4.0 - server error" + runOnRequirements: + - minServerVersion: 3.6.0 + maxServerVersion: 4.3.99 + operations: + - name: countDocuments + object: *collection0 + arguments: + filter: {} + comment: *documentComment + expectError: + isClientError: false + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + aggregate: *collection0Name + pipeline: *pipeline + comment: *documentComment + commandName: aggregate + databaseName: *database0Name diff --git a/test/spec/crud/unified/db-aggregate.yml b/test/spec/crud/unified/db-aggregate.yml index 032f94c731..df82c32b05 100644 --- a/test/spec/crud/unified/db-aggregate.yml +++ b/test/spec/crud/unified/db-aggregate.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: db-aggregate schemaVersion: '1.4' runOnRequirements: diff --git a/test/spec/crud/unified/deleteMany-collation.json b/test/spec/crud/unified/deleteMany-collation.json new file mode 100644 index 0000000000..23d2f037cb --- /dev/null +++ b/test/spec/crud/unified/deleteMany-collation.json @@ -0,0 +1,86 @@ +{ + "description": "deleteMany-collation", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "3.4", + "serverless": "forbid" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": "ping" + }, + { + "_id": 3, + "x": "pINg" + } + ] + } + ], + "tests": [ + { + "description": "DeleteMany when many documents match with collation", + "operations": [ + { + "object": "collection0", + "name": "deleteMany", + "arguments": { + "filter": { + "x": "PING" + }, + "collation": { + "locale": "en_US", + "strength": 2 + } + }, + "expectResult": { + "deletedCount": 2 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/deleteMany-collation.yml b/test/spec/crud/unified/deleteMany-collation.yml new file mode 100644 index 0000000000..b7caab67dd --- /dev/null +++ b/test/spec/crud/unified/deleteMany-collation.yml @@ -0,0 +1,54 @@ +description: deleteMany-collation + +schemaVersion: '1.4' + +runOnRequirements: + - + minServerVersion: '3.4' + serverless: forbid + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: ping } + - { _id: 3, x: pINg } + +tests: + - + description: 'DeleteMany when many documents match with collation' + operations: + - + object: *collection0 + name: deleteMany + arguments: + filter: { x: PING } + # https://www.mongodb.com/docs/manual/reference/collation/#collation-document + collation: + locale: en_US + strength: 2 + expectResult: + deletedCount: 2 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } diff --git a/test/spec/crud/unified/deleteMany-comment.json b/test/spec/crud/unified/deleteMany-comment.json index ea6a8524d9..6abc5fd58a 100644 --- a/test/spec/crud/unified/deleteMany-comment.json +++ b/test/spec/crud/unified/deleteMany-comment.json @@ -175,6 +175,7 @@ "description": "deleteMany with comment - pre 4.4", "runOnRequirements": [ { + "minServerVersion": "3.4.0", "maxServerVersion": "4.2.99" } ], diff --git a/test/spec/crud/unified/deleteMany-comment.yml b/test/spec/crud/unified/deleteMany-comment.yml index b06016247b..8f1b3522a7 100644 --- a/test/spec/crud/unified/deleteMany-comment.yml +++ b/test/spec/crud/unified/deleteMany-comment.yml @@ -74,7 +74,8 @@ tests: - description: "deleteMany with comment - pre 4.4" runOnRequirements: - - maxServerVersion: "4.2.99" + - minServerVersion: "3.4.0" + maxServerVersion: "4.2.99" operations: - name: deleteMany object: *collection0 diff --git a/test/spec/crud/unified/deleteMany-hint-clientError.yml b/test/spec/crud/unified/deleteMany-hint-clientError.yml index 21ff1debbe..c04d7507e3 100644 --- a/test/spec/crud/unified/deleteMany-hint-clientError.yml +++ b/test/spec/crud/unified/deleteMany-hint-clientError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: deleteMany-hint-clientError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/deleteMany-hint-serverError.yml b/test/spec/crud/unified/deleteMany-hint-serverError.yml index 2e20988d0b..24260e2611 100644 --- a/test/spec/crud/unified/deleteMany-hint-serverError.yml +++ b/test/spec/crud/unified/deleteMany-hint-serverError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: deleteMany-hint-serverError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/deleteMany-hint-unacknowledged.json b/test/spec/crud/unified/deleteMany-hint-unacknowledged.json new file mode 100644 index 0000000000..ab7e9c7c09 --- /dev/null +++ b/test/spec/crud/unified/deleteMany-hint-unacknowledged.json @@ -0,0 +1,245 @@ +{ + "description": "deleteMany-hint-unacknowledged", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "db0" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + } + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "db0", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "Unacknowledged deleteMany with hint string fails with client-side error on pre-4.4 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.2.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_" + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged deleteMany with hint document fails with client-side error on pre-4.4 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.2.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged deleteMany with hint string on 4.4+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.4.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_" + }, + "expectResult": { + "$$unsetOrMatches": { + "acknowledged": { + "$$unsetOrMatches": false + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "delete": "coll0", + "deletes": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "$$type": [ + "string", + "object" + ] + }, + "limit": 0 + } + ], + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + }, + { + "description": "Unacknowledged deleteMany with hint document on 4.4+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.4.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "acknowledged": { + "$$unsetOrMatches": false + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "delete": "coll0", + "deletes": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "$$type": [ + "string", + "object" + ] + }, + "limit": 0 + } + ], + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/deleteMany-hint-unacknowledged.yml b/test/spec/crud/unified/deleteMany-hint-unacknowledged.yml new file mode 100644 index 0000000000..827618d174 --- /dev/null +++ b/test/spec/crud/unified/deleteMany-hint-unacknowledged.yml @@ -0,0 +1,90 @@ +description: deleteMany-hint-unacknowledged + +schemaVersion: '1.0' + +createEntities: + - client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name db0 + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + collectionOptions: + writeConcern: { w: 0 } + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: &documents + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - description: "Unacknowledged deleteMany with hint string fails with client-side error on pre-4.4 server" + runOnRequirements: + - maxServerVersion: "4.2.99" + operations: + - object: *collection0 + name: deleteMany + arguments: + filter: &filter { _id: { $gt: 1 } } + hint: _id_ + expectError: + isClientError: true + expectEvents: &noEvents + - client: *client0 + events: [] + + - description: "Unacknowledged deleteMany with hint document fails with client-side error on pre-4.4 server" + runOnRequirements: + - maxServerVersion: "4.2.99" + operations: + - object: *collection0 + name: deleteMany + arguments: + filter: *filter + hint: { _id: 1 } + expectError: + isClientError: true + expectEvents: *noEvents + + - description: "Unacknowledged deleteMany with hint string on 4.4+ server" + runOnRequirements: + - minServerVersion: "4.4.0" + operations: + - object: *collection0 + name: deleteMany + arguments: + filter: *filter + hint: _id_ + expectResult: &unacknowledgedResult { $$unsetOrMatches: { acknowledged: { $$unsetOrMatches: false } } } + expectEvents: &events + - client: *client0 + events: + - commandStartedEvent: + command: + delete: *collection0Name + deletes: + - q: *filter + hint: { $$type: [ string, object ]} + limit: 0 + writeConcern: { w: 0 } + + - description: "Unacknowledged deleteMany with hint document on 4.4+ server" + runOnRequirements: + - minServerVersion: "4.4.0" + operations: + - object: *collection0 + name: deleteMany + arguments: + filter: *filter + hint: { _id: 1 } + expectResult: *unacknowledgedResult + expectEvents: *events diff --git a/test/spec/crud/unified/deleteMany-hint.yml b/test/spec/crud/unified/deleteMany-hint.yml index 512b95e76b..ce5f0a058d 100644 --- a/test/spec/crud/unified/deleteMany-hint.yml +++ b/test/spec/crud/unified/deleteMany-hint.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: deleteMany-hint schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/unacknowledged-deleteMany-hint-clientError.json b/test/spec/crud/unified/deleteMany.json similarity index 51% rename from test/spec/crud/unified/unacknowledged-deleteMany-hint-clientError.json rename to test/spec/crud/unified/deleteMany.json index c5d9f6af36..36cdff8dc0 100644 --- a/test/spec/crud/unified/unacknowledged-deleteMany-hint-clientError.json +++ b/test/spec/crud/unified/deleteMany.json @@ -1,39 +1,31 @@ { - "description": "unacknowledged-deleteMany-hint-clientError", + "description": "deleteMany", "schemaVersion": "1.0", "createEntities": [ { "client": { - "id": "client0", - "observeEvents": [ - "commandStartedEvent" - ] + "id": "client0" } }, { "database": { "id": "database0", "client": "client0", - "databaseName": "crud-v2" + "databaseName": "crud-v1" } }, { "collection": { "id": "collection0", "database": "database0", - "collectionName": "DeleteMany_hint", - "collectionOptions": { - "writeConcern": { - "w": 0 - } - } + "collectionName": "coll" } } ], "initialData": [ { - "collectionName": "DeleteMany_hint", - "databaseName": "crud-v2", + "collectionName": "coll", + "databaseName": "crud-v1", "documents": [ { "_id": 1, @@ -52,7 +44,7 @@ ], "tests": [ { - "description": "Unacknowledged deleteMany with hint string fails with client-side error", + "description": "DeleteMany when many documents match", "operations": [ { "object": "collection0", @@ -62,72 +54,46 @@ "_id": { "$gt": 1 } - }, - "hint": "_id_" + } }, - "expectError": { - "isError": true + "expectResult": { + "deletedCount": 2 } } ], - "expectEvents": [ - { - "client": "client0", - "events": [] - } - ], "outcome": [ { - "collectionName": "DeleteMany_hint", - "databaseName": "crud-v2", + "collectionName": "coll", + "databaseName": "crud-v1", "documents": [ { "_id": 1, "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 } ] } ] }, { - "description": "Unacknowledged deleteMany with hint document fails with client-side error", + "description": "DeleteMany when no document matches", "operations": [ { "object": "collection0", "name": "deleteMany", "arguments": { "filter": { - "_id": { - "$gt": 1 - } - }, - "hint": { - "_id": 1 + "_id": 4 } }, - "expectError": { - "isError": true + "expectResult": { + "deletedCount": 0 } } ], - "expectEvents": [ - { - "client": "client0", - "events": [] - } - ], "outcome": [ { - "collectionName": "DeleteMany_hint", - "databaseName": "crud-v2", + "collectionName": "coll", + "databaseName": "crud-v1", "documents": [ { "_id": 1, diff --git a/test/spec/crud/unified/deleteMany.yml b/test/spec/crud/unified/deleteMany.yml new file mode 100644 index 0000000000..832201ed51 --- /dev/null +++ b/test/spec/crud/unified/deleteMany.yml @@ -0,0 +1,63 @@ +description: deleteMany + +schemaVersion: '1.0' + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - + description: 'DeleteMany when many documents match' + operations: + - + object: *collection0 + name: deleteMany + arguments: + filter: { _id: { $gt: 1 } } + expectResult: + deletedCount: 2 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'DeleteMany when no document matches' + operations: + - + object: *collection0 + name: deleteMany + arguments: + filter: { _id: 4 } + expectResult: + deletedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } diff --git a/test/spec/crud/unified/deleteOne-collation.json b/test/spec/crud/unified/deleteOne-collation.json new file mode 100644 index 0000000000..44bab6e120 --- /dev/null +++ b/test/spec/crud/unified/deleteOne-collation.json @@ -0,0 +1,90 @@ +{ + "description": "deleteOne-collation", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "3.4", + "serverless": "forbid" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": "ping" + }, + { + "_id": 3, + "x": "pINg" + } + ] + } + ], + "tests": [ + { + "description": "DeleteOne when many documents matches with collation", + "operations": [ + { + "object": "collection0", + "name": "deleteOne", + "arguments": { + "filter": { + "x": "PING" + }, + "collation": { + "locale": "en_US", + "strength": 2 + } + }, + "expectResult": { + "deletedCount": 1 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 3, + "x": "pINg" + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/deleteOne-collation.yml b/test/spec/crud/unified/deleteOne-collation.yml new file mode 100644 index 0000000000..2ec971550a --- /dev/null +++ b/test/spec/crud/unified/deleteOne-collation.yml @@ -0,0 +1,55 @@ +description: deleteOne-collation + +schemaVersion: '1.4' + +runOnRequirements: + - + minServerVersion: '3.4' + serverless: forbid + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: ping } + - { _id: 3, x: pINg } + +tests: + - + description: 'DeleteOne when many documents matches with collation' + operations: + - + object: *collection0 + name: deleteOne + arguments: + filter: { x: PING } + # https://www.mongodb.com/docs/manual/reference/collation/#collation-document + collation: + locale: en_US + strength: 2 + expectResult: + deletedCount: 1 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 3, x: pINg } diff --git a/test/spec/crud/unified/deleteOne-comment.json b/test/spec/crud/unified/deleteOne-comment.json index 37f356ec6f..0f42b086a3 100644 --- a/test/spec/crud/unified/deleteOne-comment.json +++ b/test/spec/crud/unified/deleteOne-comment.json @@ -177,6 +177,7 @@ "description": "deleteOne with comment - pre 4.4", "runOnRequirements": [ { + "minServerVersion": "3.4.0", "maxServerVersion": "4.2.99" } ], diff --git a/test/spec/crud/unified/deleteOne-comment.yml b/test/spec/crud/unified/deleteOne-comment.yml index b68dcbacd0..1e52298f39 100644 --- a/test/spec/crud/unified/deleteOne-comment.yml +++ b/test/spec/crud/unified/deleteOne-comment.yml @@ -75,7 +75,8 @@ tests: - description: "deleteOne with comment - pre 4.4" runOnRequirements: - - maxServerVersion: "4.2.99" + - minServerVersion: "3.4.0" + maxServerVersion: "4.2.99" operations: - name: deleteOne object: *collection0 diff --git a/test/spec/crud/unified/deleteOne-hint-clientError.yml b/test/spec/crud/unified/deleteOne-hint-clientError.yml index be218fc9b5..7ff6f8d961 100644 --- a/test/spec/crud/unified/deleteOne-hint-clientError.yml +++ b/test/spec/crud/unified/deleteOne-hint-clientError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: deleteOne-hint-clientError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/deleteOne-hint-serverError.yml b/test/spec/crud/unified/deleteOne-hint-serverError.yml index 6c8c0ea817..191d96aeaf 100644 --- a/test/spec/crud/unified/deleteOne-hint-serverError.yml +++ b/test/spec/crud/unified/deleteOne-hint-serverError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: deleteOne-hint-serverError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/deleteOne-hint-unacknowledged.json b/test/spec/crud/unified/deleteOne-hint-unacknowledged.json new file mode 100644 index 0000000000..1782f0f525 --- /dev/null +++ b/test/spec/crud/unified/deleteOne-hint-unacknowledged.json @@ -0,0 +1,241 @@ +{ + "description": "deleteOne-hint-unacknowledged", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "db0" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + } + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "db0", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "Unacknowledged deleteOne with hint string fails with client-side error on pre-4.4 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.2.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "deleteOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_" + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged deleteOne with hint document fails with client-side error on pre-4.4 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.2.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "deleteOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged deleteOne with hint string on 4.4+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.4.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "deleteOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_" + }, + "expectResult": { + "$$unsetOrMatches": { + "acknowledged": { + "$$unsetOrMatches": false + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "delete": "coll0", + "deletes": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "$$type": [ + "string", + "object" + ] + }, + "limit": 1 + } + ], + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + }, + { + "description": "Unacknowledged deleteOne with hint document on 4.4+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.4.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "deleteOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "acknowledged": { + "$$unsetOrMatches": false + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "delete": "coll0", + "deletes": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "$$type": [ + "string", + "object" + ] + }, + "limit": 1 + } + ], + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/deleteOne-hint-unacknowledged.yml b/test/spec/crud/unified/deleteOne-hint-unacknowledged.yml new file mode 100644 index 0000000000..4ccbe13d60 --- /dev/null +++ b/test/spec/crud/unified/deleteOne-hint-unacknowledged.yml @@ -0,0 +1,89 @@ +description: deleteOne-hint-unacknowledged + +schemaVersion: '1.0' + +createEntities: + - client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name db0 + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + collectionOptions: + writeConcern: { w: 0 } + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: &documents + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - description: "Unacknowledged deleteOne with hint string fails with client-side error on pre-4.4 server" + runOnRequirements: + - maxServerVersion: "4.2.99" + operations: + - object: *collection0 + name: deleteOne + arguments: + filter: &filter { _id: { $gt: 1 } } + hint: _id_ + expectError: + isClientError: true + expectEvents: &noEvents + - client: *client0 + events: [] + + - description: "Unacknowledged deleteOne with hint document fails with client-side error on pre-4.4 server" + runOnRequirements: + - maxServerVersion: "4.2.99" + operations: + - object: *collection0 + name: deleteOne + arguments: + filter: *filter + hint: { _id: 1 } + expectError: + isClientError: true + expectEvents: *noEvents + + - description: "Unacknowledged deleteOne with hint string on 4.4+ server" + runOnRequirements: + - minServerVersion: "4.4.0" + operations: + - object: *collection0 + name: deleteOne + arguments: + filter: *filter + hint: _id_ + expectResult: &unacknowledgedResult { $$unsetOrMatches: { acknowledged: { $$unsetOrMatches: false } } } + expectEvents: &events + - client: *client0 + events: + - commandStartedEvent: + command: + delete: *collection0Name + deletes: + - q: *filter + hint: { $$type: [ string, object ]} + limit: 1 + writeConcern: { w: 0 } + + - description: "Unacknowledged deleteOne with hint document on 4.4+ server" + runOnRequirements: + - minServerVersion: "4.4.0" + operations: + - object: *collection0 + name: deleteOne + arguments: + filter: *filter + hint: { _id: 1 } + expectResult: *unacknowledgedResult + expectEvents: *events diff --git a/test/spec/crud/unified/deleteOne-hint.yml b/test/spec/crud/unified/deleteOne-hint.yml index f72356c99c..ce23b8a987 100644 --- a/test/spec/crud/unified/deleteOne-hint.yml +++ b/test/spec/crud/unified/deleteOne-hint.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: deleteOne-hint schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/unacknowledged-deleteOne-hint-clientError.json b/test/spec/crud/unified/deleteOne.json similarity index 53% rename from test/spec/crud/unified/unacknowledged-deleteOne-hint-clientError.json rename to test/spec/crud/unified/deleteOne.json index 177ad889bb..8177b2fb6b 100644 --- a/test/spec/crud/unified/unacknowledged-deleteOne-hint-clientError.json +++ b/test/spec/crud/unified/deleteOne.json @@ -1,39 +1,31 @@ { - "description": "unacknowledged-deleteOne-hint-clientError", + "description": "deleteOne", "schemaVersion": "1.0", "createEntities": [ { "client": { - "id": "client0", - "observeEvents": [ - "commandStartedEvent" - ] + "id": "client0" } }, { "database": { "id": "database0", "client": "client0", - "databaseName": "crud-v2" + "databaseName": "crud-v1" } }, { "collection": { "id": "collection0", "database": "database0", - "collectionName": "DeleteOne_hint", - "collectionOptions": { - "writeConcern": { - "w": 0 - } - } + "collectionName": "coll" } } ], "initialData": [ { - "collectionName": "DeleteOne_hint", - "databaseName": "crud-v2", + "collectionName": "coll", + "databaseName": "crud-v1", "documents": [ { "_id": 1, @@ -42,80 +34,87 @@ { "_id": 2, "x": 22 + }, + { + "_id": 3, + "x": 33 } ] } ], "tests": [ { - "description": "Unacknowledged deleteOne with hint string fails with client-side error", + "description": "DeleteOne when many documents match", "operations": [ { "object": "collection0", "name": "deleteOne", "arguments": { "filter": { - "_id": 1 - }, - "hint": "_id_" + "_id": { + "$gt": 1 + } + } }, - "expectError": { - "isError": true + "expectResult": { + "deletedCount": 1 } } - ], - "expectEvents": [ + ] + }, + { + "description": "DeleteOne when one document matches", + "operations": [ { - "client": "client0", - "events": [] + "object": "collection0", + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 2 + } + }, + "expectResult": { + "deletedCount": 1 + } } ], "outcome": [ { - "collectionName": "DeleteOne_hint", - "databaseName": "crud-v2", + "collectionName": "coll", + "databaseName": "crud-v1", "documents": [ { "_id": 1, "x": 11 }, { - "_id": 2, - "x": 22 + "_id": 3, + "x": 33 } ] } ] }, { - "description": "Unacknowledged deleteOne with hint document fails with client-side error", + "description": "DeleteOne when no documents match", "operations": [ { "object": "collection0", "name": "deleteOne", "arguments": { "filter": { - "_id": 1 - }, - "hint": { - "_id": 1 + "_id": 4 } }, - "expectError": { - "isError": true + "expectResult": { + "deletedCount": 0 } } ], - "expectEvents": [ - { - "client": "client0", - "events": [] - } - ], "outcome": [ { - "collectionName": "DeleteOne_hint", - "databaseName": "crud-v2", + "collectionName": "coll", + "databaseName": "crud-v1", "documents": [ { "_id": 1, @@ -124,6 +123,10 @@ { "_id": 2, "x": 22 + }, + { + "_id": 3, + "x": 33 } ] } diff --git a/test/spec/crud/unified/deleteOne.yml b/test/spec/crud/unified/deleteOne.yml new file mode 100644 index 0000000000..6c7dc95191 --- /dev/null +++ b/test/spec/crud/unified/deleteOne.yml @@ -0,0 +1,76 @@ +description: deleteOne + +schemaVersion: '1.0' + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - + # This test doesn't verify the output collection because we cannot assume + # which document gets deleted. + description: 'DeleteOne when many documents match' + operations: + - + object: *collection0 + name: deleteOne + arguments: + filter: { _id: { $gt: 1 } } + expectResult: + deletedCount: 1 + - + description: 'DeleteOne when one document matches' + operations: + - + object: *collection0 + name: deleteOne + arguments: + filter: { _id: 2 } + expectResult: + deletedCount: 1 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 3, x: 33 } + - + description: 'DeleteOne when no documents match' + operations: + - + object: *collection0 + name: deleteOne + arguments: + filter: { _id: 4 } + expectResult: + deletedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } diff --git a/test/spec/crud/unified/distinct-collation.json b/test/spec/crud/unified/distinct-collation.json new file mode 100644 index 0000000000..e40cb0b2cf --- /dev/null +++ b/test/spec/crud/unified/distinct-collation.json @@ -0,0 +1,69 @@ +{ + "description": "distinct-collation", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "3.4", + "serverless": "forbid" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "string": "PING" + }, + { + "_id": 2, + "string": "ping" + } + ] + } + ], + "tests": [ + { + "description": "Distinct with a collation", + "operations": [ + { + "object": "collection0", + "name": "distinct", + "arguments": { + "fieldName": "string", + "filter": {}, + "collation": { + "locale": "en_US", + "strength": 2 + } + }, + "expectResult": [ + "PING" + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/distinct-collation.yml b/test/spec/crud/unified/distinct-collation.yml new file mode 100644 index 0000000000..74cf1bae35 --- /dev/null +++ b/test/spec/crud/unified/distinct-collation.yml @@ -0,0 +1,48 @@ +description: distinct-collation + +schemaVersion: '1.4' + +runOnRequirements: + - + minServerVersion: '3.4' + serverless: forbid + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - {_id: 1, string: 'PING'} + - {_id: 2, string: 'ping'} + +tests: + - + description: 'Distinct with a collation' + operations: + - + object: *collection0 + name: distinct + arguments: + fieldName: string + filter: { } + # https://www.mongodb.com/docs/manual/reference/collation/#collation-document + collation: + locale: en_US + strength: 2 + expectResult: + - PING diff --git a/test/spec/crud/unified/distinct.json b/test/spec/crud/unified/distinct.json new file mode 100644 index 0000000000..9accffabc9 --- /dev/null +++ b/test/spec/crud/unified/distinct.json @@ -0,0 +1,86 @@ +{ + "description": "distinct", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "Distinct without a filter", + "operations": [ + { + "object": "collection0", + "name": "distinct", + "arguments": { + "fieldName": "x", + "filter": {} + }, + "expectResult": [ + 11, + 22, + 33 + ] + } + ] + }, + { + "description": "Distinct with a filter", + "operations": [ + { + "object": "collection0", + "name": "distinct", + "arguments": { + "fieldName": "x", + "filter": { + "_id": { + "$gt": 1 + } + } + }, + "expectResult": [ + 22, + 33 + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/distinct.yml b/test/spec/crud/unified/distinct.yml new file mode 100644 index 0000000000..c554a7671b --- /dev/null +++ b/test/spec/crud/unified/distinct.yml @@ -0,0 +1,54 @@ +description: distinct + +schemaVersion: '1.0' + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - + description: 'Distinct without a filter' + operations: + - + object: *collection0 + name: distinct + arguments: + fieldName: x + filter: { } + expectResult: + - 11 + - 22 + - 33 + - + description: 'Distinct with a filter' + operations: + - + object: *collection0 + name: distinct + arguments: + fieldName: x + filter: { _id: { $gt: 1 } } + expectResult: + - 22 + - 33 diff --git a/test/spec/crud/unified/find-allowdiskuse-clientError.yml b/test/spec/crud/unified/find-allowdiskuse-clientError.yml index 2bc26908fe..da7f6365f1 100644 --- a/test/spec/crud/unified/find-allowdiskuse-clientError.yml +++ b/test/spec/crud/unified/find-allowdiskuse-clientError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: find-allowdiskuse-clientError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/find-allowdiskuse-serverError.yml b/test/spec/crud/unified/find-allowdiskuse-serverError.yml index de73d8b37d..86f48d18e5 100644 --- a/test/spec/crud/unified/find-allowdiskuse-serverError.yml +++ b/test/spec/crud/unified/find-allowdiskuse-serverError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: find-allowdiskuse-serverError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/find-allowdiskuse.yml b/test/spec/crud/unified/find-allowdiskuse.yml index 1bf8eee562..2f4190b9c3 100644 --- a/test/spec/crud/unified/find-allowdiskuse.yml +++ b/test/spec/crud/unified/find-allowdiskuse.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: find-allowdiskuse schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/find-collation.json b/test/spec/crud/unified/find-collation.json new file mode 100644 index 0000000000..13b105ad5a --- /dev/null +++ b/test/spec/crud/unified/find-collation.json @@ -0,0 +1,69 @@ +{ + "description": "find-collation", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "3.4", + "serverless": "forbid" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": "ping" + } + ] + } + ], + "tests": [ + { + "description": "Find with a collation", + "operations": [ + { + "object": "collection0", + "name": "find", + "arguments": { + "filter": { + "x": "PING" + }, + "collation": { + "locale": "en_US", + "strength": 2 + } + }, + "expectResult": [ + { + "_id": 1, + "x": "ping" + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/find-collation.yml b/test/spec/crud/unified/find-collation.yml new file mode 100644 index 0000000000..9810b60970 --- /dev/null +++ b/test/spec/crud/unified/find-collation.yml @@ -0,0 +1,46 @@ +description: find-collation + +schemaVersion: '1.4' + +runOnRequirements: + - + minServerVersion: '3.4' + serverless: forbid + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: ping } + +tests: + - + description: 'Find with a collation' + operations: + - + object: *collection0 + name: find + arguments: + filter: { x: PING } + # https://www.mongodb.com/docs/manual/reference/collation/#collation-document + collation: + locale: en_US + strength: 2 + expectResult: + - { _id: 1, x: ping } diff --git a/test/spec/crud/unified/find.json b/test/spec/crud/unified/find.json index 275d5d351a..6bf1e4e445 100644 --- a/test/spec/crud/unified/find.json +++ b/test/spec/crud/unified/find.json @@ -151,6 +151,92 @@ ] } ] + }, + { + "description": "Find with filter", + "operations": [ + { + "object": "collection0", + "name": "find", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectResult": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "Find with filter, sort, skip, and limit", + "operations": [ + { + "object": "collection0", + "name": "find", + "arguments": { + "filter": { + "_id": { + "$gt": 2 + } + }, + "sort": { + "_id": 1 + }, + "skip": 2, + "limit": 2 + }, + "expectResult": [ + { + "_id": 5, + "x": 55 + }, + { + "_id": 6, + "x": 66 + } + ] + } + ] + }, + { + "description": "Find with limit, sort, and batchsize", + "operations": [ + { + "object": "collection0", + "name": "find", + "arguments": { + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4, + "batchSize": 2 + }, + "expectResult": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ] } ] } diff --git a/test/spec/crud/unified/find.yml b/test/spec/crud/unified/find.yml index 5615f07234..76676900fa 100644 --- a/test/spec/crud/unified/find.yml +++ b/test/spec/crud/unified/find.yml @@ -65,4 +65,43 @@ tests: batchSize: 2 commandName: getMore databaseName: *database0Name - + - + description: 'Find with filter' + operations: + - + object: *collection0 + name: find + arguments: + filter: { _id: 1 } + expectResult: + - { _id: 1, x: 11 } + - + description: 'Find with filter, sort, skip, and limit' + operations: + - + object: *collection0 + name: find + arguments: + filter: { _id: { $gt: 2 } } + sort: { _id: 1 } + skip: 2 + limit: 2 + expectResult: + - { _id: 5, x: 55 } + - { _id: 6, x: 66 } + - + description: 'Find with limit, sort, and batchsize' + operations: + - + object: *collection0 + name: find + arguments: + filter: { } + sort: { _id: 1 } + limit: 4 + batchSize: 2 + expectResult: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - { _id: 4, x: 44 } diff --git a/test/spec/crud/unified/findOneAndDelete-collation.json b/test/spec/crud/unified/findOneAndDelete-collation.json new file mode 100644 index 0000000000..a0452876a3 --- /dev/null +++ b/test/spec/crud/unified/findOneAndDelete-collation.json @@ -0,0 +1,98 @@ +{ + "description": "findOneAndDelete-collation", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "3.4", + "serverless": "forbid" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": "ping" + }, + { + "_id": 3, + "x": "pINg" + } + ] + } + ], + "tests": [ + { + "description": "FindOneAndDelete when one document matches with collation", + "operations": [ + { + "object": "collection0", + "name": "findOneAndDelete", + "arguments": { + "filter": { + "_id": 2, + "x": "PING" + }, + "projection": { + "x": 1, + "_id": 0 + }, + "sort": { + "x": 1 + }, + "collation": { + "locale": "en_US", + "strength": 2 + } + }, + "expectResult": { + "x": "ping" + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 3, + "x": "pINg" + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/findOneAndDelete-collation.yml b/test/spec/crud/unified/findOneAndDelete-collation.yml new file mode 100644 index 0000000000..2e6de9b08e --- /dev/null +++ b/test/spec/crud/unified/findOneAndDelete-collation.yml @@ -0,0 +1,56 @@ +description: findOneAndDelete-collation + +schemaVersion: '1.4' + +runOnRequirements: + - + minServerVersion: '3.4' + serverless: forbid + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: ping } + - { _id: 3, x: pINg } + +tests: + - + description: 'FindOneAndDelete when one document matches with collation' + operations: + - + object: *collection0 + name: findOneAndDelete + arguments: + filter: { _id: 2, x: PING } + projection: { x: 1, _id: 0 } + sort: { x: 1 } + # https://www.mongodb.com/docs/manual/reference/collation/#collation-document + collation: + locale: en_US + strength: 2 + expectResult: { x: ping } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 3, x: pINg } diff --git a/test/spec/crud/unified/findOneAndDelete-hint-clientError.yml b/test/spec/crud/unified/findOneAndDelete-hint-clientError.yml index 220496872a..46c7521ad8 100644 --- a/test/spec/crud/unified/findOneAndDelete-hint-clientError.yml +++ b/test/spec/crud/unified/findOneAndDelete-hint-clientError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: findOneAndDelete-hint-clientError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/findOneAndDelete-hint-serverError.yml b/test/spec/crud/unified/findOneAndDelete-hint-serverError.yml index 5fd21eedc0..db75131545 100644 --- a/test/spec/crud/unified/findOneAndDelete-hint-serverError.yml +++ b/test/spec/crud/unified/findOneAndDelete-hint-serverError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: findOneAndDelete-hint-serverError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/findOneAndDelete-hint-unacknowledged.json b/test/spec/crud/unified/findOneAndDelete-hint-unacknowledged.json new file mode 100644 index 0000000000..077f9892b9 --- /dev/null +++ b/test/spec/crud/unified/findOneAndDelete-hint-unacknowledged.json @@ -0,0 +1,225 @@ +{ + "description": "findOneAndDelete-hint-unacknowledged", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "db0" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + } + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "db0", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "Unacknowledged findOneAndDelete with hint string fails with client-side error on pre-4.4 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.2.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "findOneAndDelete", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_" + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged findOneAndDelete with hint document fails with client-side error on pre-4.4 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.2.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "findOneAndDelete", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged findOneAndDelete with hint string on 4.4+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.4.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "findOneAndDelete", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_" + }, + "expectResult": { + "$$unsetOrMatches": null + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "findAndModify": "coll0", + "query": { + "_id": { + "$gt": 1 + } + }, + "remove": true, + "hint": { + "$$type": [ + "string", + "object" + ] + }, + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + }, + { + "description": "Unacknowledged findOneAndDelete with hint document on 4.4+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.4.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "findOneAndDelete", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "expectResult": { + "$$unsetOrMatches": null + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "findAndModify": "coll0", + "query": { + "_id": { + "$gt": 1 + } + }, + "remove": true, + "hint": { + "$$type": [ + "string", + "object" + ] + }, + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/findOneAndDelete-hint-unacknowledged.yml b/test/spec/crud/unified/findOneAndDelete-hint-unacknowledged.yml new file mode 100644 index 0000000000..2b29a4923e --- /dev/null +++ b/test/spec/crud/unified/findOneAndDelete-hint-unacknowledged.yml @@ -0,0 +1,88 @@ +description: findOneAndDelete-hint-unacknowledged + +schemaVersion: '1.0' + +createEntities: + - client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name db0 + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + collectionOptions: + writeConcern: { w: 0 } + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: &documents + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - description: "Unacknowledged findOneAndDelete with hint string fails with client-side error on pre-4.4 server" + runOnRequirements: + - maxServerVersion: "4.2.99" + operations: + - object: *collection0 + name: findOneAndDelete + arguments: + filter: &filter { _id: { $gt: 1 } } + hint: _id_ + expectError: + isClientError: true + expectEvents: &noEvents + - client: *client0 + events: [] + + - description: "Unacknowledged findOneAndDelete with hint document fails with client-side error on pre-4.4 server" + runOnRequirements: + - maxServerVersion: "4.2.99" + operations: + - object: *collection0 + name: findOneAndDelete + arguments: + filter: *filter + hint: { _id: 1 } + expectError: + isClientError: true + expectEvents: *noEvents + + - description: "Unacknowledged findOneAndDelete with hint string on 4.4+ server" + runOnRequirements: + - minServerVersion: "4.4.0" + operations: + - object: *collection0 + name: findOneAndDelete + arguments: + filter: *filter + hint: _id_ + expectResult: &unacknowledgedResult { $$unsetOrMatches: null } + expectEvents: &events + - client: *client0 + events: + - commandStartedEvent: + command: + findAndModify: *collection0Name + query: *filter + remove: true + hint: { $$type: [ string, object ]} + writeConcern: { w: 0 } + + - description: "Unacknowledged findOneAndDelete with hint document on 4.4+ server" + runOnRequirements: + - minServerVersion: "4.4.0" + operations: + - object: *collection0 + name: findOneAndDelete + arguments: + filter: *filter + hint: { _id: 1 } + expectResult: *unacknowledgedResult + expectEvents: *events diff --git a/test/spec/crud/unified/findOneAndDelete-hint.yml b/test/spec/crud/unified/findOneAndDelete-hint.yml index 3dc4f3ff41..9090779831 100644 --- a/test/spec/crud/unified/findOneAndDelete-hint.yml +++ b/test/spec/crud/unified/findOneAndDelete-hint.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: findOneAndDelete-hint schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/unacknowledged-updateMany-hint-clientError.json b/test/spec/crud/unified/findOneAndDelete.json similarity index 50% rename from test/spec/crud/unified/unacknowledged-updateMany-hint-clientError.json rename to test/spec/crud/unified/findOneAndDelete.json index 6199dfa2be..e434b3b740 100644 --- a/test/spec/crud/unified/unacknowledged-updateMany-hint-clientError.json +++ b/test/spec/crud/unified/findOneAndDelete.json @@ -1,39 +1,31 @@ { - "description": "unacknowledged-updateMany-hint-clientError", + "description": "findOneAndDelete", "schemaVersion": "1.0", "createEntities": [ { "client": { - "id": "client0", - "observeEvents": [ - "commandStartedEvent" - ] + "id": "client0" } }, { "database": { "id": "database0", "client": "client0", - "databaseName": "crud-v2" + "databaseName": "crud-v1" } }, { "collection": { "id": "collection0", "database": "database0", - "collectionName": "Updatemany_hint", - "collectionOptions": { - "writeConcern": { - "w": 0 - } - } + "collectionName": "coll" } } ], "initialData": [ { - "collectionName": "Updatemany_hint", - "databaseName": "crud-v2", + "collectionName": "coll", + "databaseName": "crud-v1", "documents": [ { "_id": 1, @@ -52,48 +44,39 @@ ], "tests": [ { - "description": "Unacknowledged updateMany with hint string fails with client-side error", + "description": "FindOneAndDelete when many documents match", "operations": [ { "object": "collection0", - "name": "updateMany", + "name": "findOneAndDelete", "arguments": { "filter": { "_id": { "$gt": 1 } }, - "update": { - "$inc": { - "x": 1 - } + "projection": { + "x": 1, + "_id": 0 }, - "hint": "_id_" + "sort": { + "x": 1 + } }, - "expectError": { - "isError": true + "expectResult": { + "x": 22 } } ], - "expectEvents": [ - { - "client": "client0", - "events": [] - } - ], "outcome": [ { - "collectionName": "Updatemany_hint", - "databaseName": "crud-v2", + "collectionName": "coll", + "databaseName": "crud-v1", "documents": [ { "_id": 1, "x": 11 }, - { - "_id": 2, - "x": 22 - }, { "_id": 3, "x": 33 @@ -103,41 +86,70 @@ ] }, { - "description": "Unacknowledged updateMany with hint document fails with client-side error", + "description": "FindOneAndDelete when one document matches", "operations": [ { "object": "collection0", - "name": "updateMany", + "name": "findOneAndDelete", "arguments": { "filter": { - "_id": { - "$gt": 1 - } + "_id": 2 }, - "update": { - "$inc": { - "x": 1 - } + "projection": { + "x": 1, + "_id": 0 }, - "hint": { - "_id": 1 + "sort": { + "x": 1 } }, - "expectError": { - "isError": true + "expectResult": { + "x": 22 } } ], - "expectEvents": [ + "outcome": [ { - "client": "client0", - "events": [] + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "FindOneAndDelete when no documents match", + "operations": [ + { + "object": "collection0", + "name": "findOneAndDelete", + "arguments": { + "filter": { + "_id": 4 + }, + "projection": { + "x": 1, + "_id": 0 + }, + "sort": { + "x": 1 + } + }, + "expectResult": null } ], "outcome": [ { - "collectionName": "Updatemany_hint", - "databaseName": "crud-v2", + "collectionName": "coll", + "databaseName": "crud-v1", "documents": [ { "_id": 1, diff --git a/test/spec/crud/unified/findOneAndDelete.yml b/test/spec/crud/unified/findOneAndDelete.yml new file mode 100644 index 0000000000..6bb3a1ccca --- /dev/null +++ b/test/spec/crud/unified/findOneAndDelete.yml @@ -0,0 +1,84 @@ +description: findOneAndDelete + +schemaVersion: '1.0' + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - + description: 'FindOneAndDelete when many documents match' + operations: + - + object: *collection0 + name: findOneAndDelete + arguments: + filter: { _id: { $gt: 1 } } + projection: { x: 1, _id: 0 } + sort: { x: 1 } + expectResult: { x: 22 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 3, x: 33 } + - + description: 'FindOneAndDelete when one document matches' + operations: + - + object: *collection0 + name: findOneAndDelete + arguments: + filter: { _id: 2 } + projection: { x: 1, _id: 0 } + sort: { x: 1 } + expectResult: { x: 22 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 3, x: 33 } + - + description: 'FindOneAndDelete when no documents match' + operations: + - + object: *collection0 + name: findOneAndDelete + arguments: + filter: { _id: 4 } + projection: { x: 1, _id: 0 } + sort: { x: 1 } + expectResult: null + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } diff --git a/test/spec/crud/unified/findOneAndReplace-collation.json b/test/spec/crud/unified/findOneAndReplace-collation.json new file mode 100644 index 0000000000..0d60d54164 --- /dev/null +++ b/test/spec/crud/unified/findOneAndReplace-collation.json @@ -0,0 +1,97 @@ +{ + "description": "findOneAndReplace-collation", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "3.4", + "serverless": "forbid" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": "ping" + } + ] + } + ], + "tests": [ + { + "description": "FindOneAndReplace when one document matches with collation returning the document after modification", + "operations": [ + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "x": "PING" + }, + "replacement": { + "x": "pong" + }, + "projection": { + "x": 1, + "_id": 0 + }, + "returnDocument": "After", + "sort": { + "x": 1 + }, + "collation": { + "locale": "en_US", + "strength": 2 + } + }, + "expectResult": { + "x": "pong" + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": "pong" + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/findOneAndReplace-collation.yml b/test/spec/crud/unified/findOneAndReplace-collation.yml new file mode 100644 index 0000000000..c3d8a8e78f --- /dev/null +++ b/test/spec/crud/unified/findOneAndReplace-collation.yml @@ -0,0 +1,57 @@ +description: findOneAndReplace-collation + +schemaVersion: '1.4' + +runOnRequirements: + - + minServerVersion: '3.4' + serverless: forbid + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: ping } + +tests: + - + description: 'FindOneAndReplace when one document matches with collation returning the document after modification' + operations: + - + object: *collection0 + name: findOneAndReplace + arguments: + filter: { x: PING } + replacement: { x: pong } + projection: { x: 1, _id: 0 } + returnDocument: After + sort: { x: 1 } + # https://www.mongodb.com/docs/manual/reference/collation/#collation-document + collation: + locale: en_US + strength: 2 + expectResult: { x: pong } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: pong } diff --git a/test/spec/crud/unified/findOneAndReplace-hint-clientError.yml b/test/spec/crud/unified/findOneAndReplace-hint-clientError.yml index f59952ffc0..a0a8f94beb 100644 --- a/test/spec/crud/unified/findOneAndReplace-hint-clientError.yml +++ b/test/spec/crud/unified/findOneAndReplace-hint-clientError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: findOneAndReplace-hint-clientError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/findOneAndReplace-hint-serverError.yml b/test/spec/crud/unified/findOneAndReplace-hint-serverError.yml index 664cd0bbc5..1fea6f364b 100644 --- a/test/spec/crud/unified/findOneAndReplace-hint-serverError.yml +++ b/test/spec/crud/unified/findOneAndReplace-hint-serverError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: findOneAndReplace-hint-serverError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/findOneAndReplace-hint-unacknowledged.json b/test/spec/crud/unified/findOneAndReplace-hint-unacknowledged.json new file mode 100644 index 0000000000..8228d8a2aa --- /dev/null +++ b/test/spec/crud/unified/findOneAndReplace-hint-unacknowledged.json @@ -0,0 +1,248 @@ +{ + "description": "findOneAndReplace-hint-unacknowledged", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "db0" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + } + } + }, + { + "collection": { + "id": "collection1", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "db0", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "Unacknowledged findOneAndReplace with hint string fails with client-side error on pre-4.4 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.2.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 111 + }, + "hint": "_id_" + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged findOneAndReplace with hint document fails with client-side error on pre-4.4 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.2.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 111 + }, + "hint": { + "_id": 1 + } + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged findOneAndReplace with hint string on 4.4+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.4.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 111 + }, + "hint": "_id_" + }, + "expectResult": { + "$$unsetOrMatches": null + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "findAndModify": "coll0", + "query": { + "_id": { + "$gt": 1 + } + }, + "update": { + "x": 111 + }, + "hint": { + "$$type": [ + "string", + "object" + ] + }, + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + }, + { + "description": "Unacknowledged findOneAndReplace with hint document on 4.4+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.4.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 111 + }, + "hint": { + "_id": 1 + } + }, + "expectResult": { + "$$unsetOrMatches": null + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "findAndModify": "coll0", + "query": { + "_id": { + "$gt": 1 + } + }, + "update": { + "x": 111 + }, + "hint": { + "$$type": [ + "string", + "object" + ] + }, + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/findOneAndReplace-hint-unacknowledged.yml b/test/spec/crud/unified/findOneAndReplace-hint-unacknowledged.yml new file mode 100644 index 0000000000..20a2737de2 --- /dev/null +++ b/test/spec/crud/unified/findOneAndReplace-hint-unacknowledged.yml @@ -0,0 +1,96 @@ +description: findOneAndReplace-hint-unacknowledged + +schemaVersion: '1.0' + +createEntities: + - client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name db0 + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + collectionOptions: + writeConcern: { w: 0 } + - collection: + id: &collection1 collection1 + database: *database0 + collectionName: *collection0Name + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: &documents + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - description: "Unacknowledged findOneAndReplace with hint string fails with client-side error on pre-4.4 server" + runOnRequirements: + - maxServerVersion: "4.2.99" + operations: + - object: *collection0 + name: findOneAndReplace + arguments: + filter: &filter { _id: { $gt: 1 } } + replacement: &replacement { x: 111 } + hint: _id_ + expectError: + isClientError: true + expectEvents: &noEvents + - client: *client0 + events: [] + + - description: "Unacknowledged findOneAndReplace with hint document fails with client-side error on pre-4.4 server" + runOnRequirements: + - maxServerVersion: "4.2.99" + operations: + - object: *collection0 + name: findOneAndReplace + arguments: + filter: *filter + replacement: *replacement + hint: { _id: 1 } + expectError: + isClientError: true + expectEvents: *noEvents + + - description: "Unacknowledged findOneAndReplace with hint string on 4.4+ server" + runOnRequirements: + - minServerVersion: "4.4.0" + operations: + - object: *collection0 + name: findOneAndReplace + arguments: + filter: *filter + replacement: *replacement + hint: _id_ + expectResult: &unacknowledgedResult { $$unsetOrMatches: null } + expectEvents: &events + - client: *client0 + events: + - commandStartedEvent: + command: + findAndModify: *collection0Name + query: *filter + update: *replacement + hint: { $$type: [ string, object ]} + writeConcern: { w: 0 } + + - description: "Unacknowledged findOneAndReplace with hint document on 4.4+ server" + runOnRequirements: + - minServerVersion: "4.4.0" + operations: + - object: *collection0 + name: findOneAndReplace + arguments: + filter: *filter + replacement: *replacement + hint: { _id: 1 } + expectResult: *unacknowledgedResult + expectEvents: *events diff --git a/test/spec/crud/unified/findOneAndReplace-hint.yml b/test/spec/crud/unified/findOneAndReplace-hint.yml index 9c581270a7..67fbf2cb2b 100644 --- a/test/spec/crud/unified/findOneAndReplace-hint.yml +++ b/test/spec/crud/unified/findOneAndReplace-hint.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: findOneAndReplace-hint schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/findOneAndReplace-upsert.json b/test/spec/crud/unified/findOneAndReplace-upsert.json new file mode 100644 index 0000000000..f1f18996c8 --- /dev/null +++ b/test/spec/crud/unified/findOneAndReplace-upsert.json @@ -0,0 +1,254 @@ +{ + "description": "findOneAndReplace-upsert", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "2.6" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "FindOneAndReplace when no documents match without id specified with upsert returning the document before modification", + "operations": [ + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 4 + }, + "replacement": { + "x": 44 + }, + "projection": { + "x": 1, + "_id": 0 + }, + "upsert": true + }, + "expectResult": null + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ] + }, + { + "description": "FindOneAndReplace when no documents match without id specified with upsert returning the document after modification", + "operations": [ + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 4 + }, + "replacement": { + "x": 44 + }, + "projection": { + "x": 1, + "_id": 0 + }, + "returnDocument": "After", + "sort": { + "x": 1 + }, + "upsert": true + }, + "expectResult": { + "x": 44 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ] + }, + { + "description": "FindOneAndReplace when no documents match with id specified with upsert returning the document before modification", + "operations": [ + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 4 + }, + "replacement": { + "_id": 4, + "x": 44 + }, + "projection": { + "x": 1, + "_id": 0 + }, + "upsert": true + }, + "expectResult": null + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ] + }, + { + "description": "FindOneAndReplace when no documents match with id specified with upsert returning the document after modification", + "operations": [ + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 4 + }, + "replacement": { + "_id": 4, + "x": 44 + }, + "projection": { + "x": 1, + "_id": 0 + }, + "returnDocument": "After", + "sort": { + "x": 1 + }, + "upsert": true + }, + "expectResult": { + "x": 44 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/findOneAndReplace-upsert.yml b/test/spec/crud/unified/findOneAndReplace-upsert.yml new file mode 100644 index 0000000000..c52fdf11b1 --- /dev/null +++ b/test/spec/crud/unified/findOneAndReplace-upsert.yml @@ -0,0 +1,127 @@ +description: findOneAndReplace-upsert + +schemaVersion: '1.0' + +runOnRequirements: + - + minServerVersion: '2.6' + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - + description: 'FindOneAndReplace when no documents match without id specified with upsert returning the document before modification' + operations: + - + object: *collection0 + name: findOneAndReplace + arguments: + filter: { _id: 4 } + replacement: { x: 44 } + projection: { x: 1, _id: 0 } + # Omit the sort option as it has no effect when no documents match and + # would only cause an inconsistent return value on pre-3.0 servers + # when combined with returnDocument "before" (see: SERVER-17650). + upsert: true + expectResult: null + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - { _id: 4, x: 44 } + - + description: 'FindOneAndReplace when no documents match without id specified with upsert returning the document after modification' + operations: + - + object: *collection0 + name: findOneAndReplace + arguments: + filter: { _id: 4 } + replacement: { x: 44 } + projection: { x: 1, _id: 0 } + returnDocument: After + sort: { x: 1 } + upsert: true + expectResult: { x: 44 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - { _id: 4, x: 44 } + - + description: 'FindOneAndReplace when no documents match with id specified with upsert returning the document before modification' + operations: + - + object: *collection0 + name: findOneAndReplace + arguments: + filter: { _id: 4 } + replacement: { _id: 4, x: 44 } + projection: { x: 1, _id: 0 } + # Omit the sort option as it has no effect when no documents match and + # would only cause an inconsistent return value on pre-3.0 servers + # when combined with returnDocument "before" (see: SERVER-17650). + upsert: true + expectResult: null + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - { _id: 4, x: 44 } + - + description: 'FindOneAndReplace when no documents match with id specified with upsert returning the document after modification' + operations: + - + object: *collection0 + name: findOneAndReplace + arguments: + filter: { _id: 4 } + replacement: { _id: 4, x: 44 } + projection: { x: 1, _id: 0 } + returnDocument: After + sort: { x: 1 } + upsert: true + expectResult: { x: 44 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - { _id: 4, x: 44 } diff --git a/test/spec/crud/unified/findOneAndReplace.json b/test/spec/crud/unified/findOneAndReplace.json new file mode 100644 index 0000000000..a4731602c4 --- /dev/null +++ b/test/spec/crud/unified/findOneAndReplace.json @@ -0,0 +1,332 @@ +{ + "description": "findOneAndReplace", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "FindOneAndReplace when many documents match returning the document before modification", + "operations": [ + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 32 + }, + "projection": { + "x": 1, + "_id": 0 + }, + "sort": { + "x": 1 + } + }, + "expectResult": { + "x": 22 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 32 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "FindOneAndReplace when many documents match returning the document after modification", + "operations": [ + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 32 + }, + "projection": { + "x": 1, + "_id": 0 + }, + "returnDocument": "After", + "sort": { + "x": 1 + } + }, + "expectResult": { + "x": 32 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 32 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "FindOneAndReplace when one document matches returning the document before modification", + "operations": [ + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 2 + }, + "replacement": { + "x": 32 + }, + "projection": { + "x": 1, + "_id": 0 + }, + "sort": { + "x": 1 + } + }, + "expectResult": { + "x": 22 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 32 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "FindOneAndReplace when one document matches returning the document after modification", + "operations": [ + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 2 + }, + "replacement": { + "x": 32 + }, + "projection": { + "x": 1, + "_id": 0 + }, + "returnDocument": "After", + "sort": { + "x": 1 + } + }, + "expectResult": { + "x": 32 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 32 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "FindOneAndReplace when no documents match returning the document before modification", + "operations": [ + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 4 + }, + "replacement": { + "x": 44 + }, + "projection": { + "x": 1, + "_id": 0 + }, + "sort": { + "x": 1 + } + }, + "expectResult": null + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "FindOneAndReplace when no documents match returning the document after modification", + "operations": [ + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 4 + }, + "replacement": { + "x": 44 + }, + "projection": { + "x": 1, + "_id": 0 + }, + "returnDocument": "After", + "sort": { + "x": 1 + } + }, + "expectResult": null + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/findOneAndReplace.yml b/test/spec/crud/unified/findOneAndReplace.yml new file mode 100644 index 0000000000..ddfd533558 --- /dev/null +++ b/test/spec/crud/unified/findOneAndReplace.yml @@ -0,0 +1,152 @@ +description: findOneAndReplace + +schemaVersion: '1.0' + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - + description: 'FindOneAndReplace when many documents match returning the document before modification' + operations: + - + object: *collection0 + name: findOneAndReplace + arguments: + filter: { _id: { $gt: 1 } } + replacement: { x: 32 } + projection: { x: 1, _id: 0 } + sort: { x: 1 } + expectResult: { x: 22 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 32 } + - { _id: 3, x: 33 } + - + description: 'FindOneAndReplace when many documents match returning the document after modification' + operations: + - + object: *collection0 + name: findOneAndReplace + arguments: + filter: { _id: { $gt: 1 } } + replacement: { x: 32 } + projection: { x: 1, _id: 0 } + returnDocument: After + sort: { x: 1 } + expectResult: { x: 32 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 32 } + - { _id: 3, x: 33 } + - + description: 'FindOneAndReplace when one document matches returning the document before modification' + operations: + - + object: *collection0 + name: findOneAndReplace + arguments: + filter: { _id: 2 } + replacement: { x: 32 } + projection: { x: 1, _id: 0 } + sort: { x: 1 } + expectResult: { x: 22 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 32 } + - { _id: 3, x: 33 } + - + description: 'FindOneAndReplace when one document matches returning the document after modification' + operations: + - + object: *collection0 + name: findOneAndReplace + arguments: + filter: { _id: 2 } + replacement: { x: 32 } + projection: { x: 1, _id: 0 } + returnDocument: After + sort: { x: 1 } + expectResult: { x: 32 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 32 } + - { _id: 3, x: 33 } + - + description: 'FindOneAndReplace when no documents match returning the document before modification' + operations: + - + object: *collection0 + name: findOneAndReplace + arguments: + filter: { _id: 4 } + replacement: { x: 44 } + projection: { x: 1, _id: 0 } + sort: { x: 1 } + expectResult: null + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'FindOneAndReplace when no documents match returning the document after modification' + operations: + - + object: *collection0 + name: findOneAndReplace + arguments: + filter: { _id: 4 } + replacement: { x: 44 } + projection: { x: 1, _id: 0 } + returnDocument: After + sort: { x: 1 } + expectResult: null + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } diff --git a/test/spec/crud/unified/findOneAndUpdate-arrayFilters.json b/test/spec/crud/unified/findOneAndUpdate-arrayFilters.json new file mode 100644 index 0000000000..6c99e4ff66 --- /dev/null +++ b/test/spec/crud/unified/findOneAndUpdate-arrayFilters.json @@ -0,0 +1,251 @@ +{ + "description": "findOneAndUpdate-arrayFilters", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "3.5.6" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 1 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + } + ] + } + ], + "tests": [ + { + "description": "FindOneAndUpdate when no document matches arrayFilters", + "operations": [ + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 4 + } + ] + }, + "expectResult": { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 1 + } + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 1 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + } + ] + } + ] + }, + { + "description": "FindOneAndUpdate when one document matches arrayFilters", + "operations": [ + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 3 + } + ] + }, + "expectResult": { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 1 + } + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "y": [ + { + "b": 2 + }, + { + "b": 1 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + } + ] + } + ] + }, + { + "description": "FindOneAndUpdate when multiple documents match arrayFilters", + "operations": [ + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 1 + } + ] + }, + "expectResult": { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 1 + } + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 2 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/findOneAndUpdate-arrayFilters.yml b/test/spec/crud/unified/findOneAndUpdate-arrayFilters.yml new file mode 100644 index 0000000000..42e392c2c5 --- /dev/null +++ b/test/spec/crud/unified/findOneAndUpdate-arrayFilters.yml @@ -0,0 +1,89 @@ +description: findOneAndUpdate-arrayFilters + +schemaVersion: '1.0' + +runOnRequirements: + - + minServerVersion: 3.5.6 + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, y: [ { b: 3 }, { b: 1 } ] } + - { _id: 2, y: [ { b: 0 }, { b: 1 } ] } + +tests: + - + description: 'FindOneAndUpdate when no document matches arrayFilters' + operations: + - + object: *collection0 + name: findOneAndUpdate + arguments: + filter: { } + update: { $set: { 'y.$[i].b': 2 } } + arrayFilters: + - { i.b: 4 } + expectResult: { _id: 1, y: [ { b: 3 }, { b: 1 } ] } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, y: [ { b: 3 }, { b: 1 } ] } + - { _id: 2, y: [ { b: 0 }, { b: 1 } ] } + - + description: 'FindOneAndUpdate when one document matches arrayFilters' + operations: + - + object: *collection0 + name: findOneAndUpdate + arguments: + filter: { } + update: { $set: { 'y.$[i].b': 2 } } + arrayFilters: + - { i.b: 3 } + expectResult: { _id: 1, y: [ { b: 3 }, { b: 1 } ] } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, y: [ { b: 2 }, { b: 1 } ] } + - { _id: 2, y: [ { b: 0 }, { b: 1 } ] } + - + description: 'FindOneAndUpdate when multiple documents match arrayFilters' + operations: + - + object: *collection0 + name: findOneAndUpdate + arguments: + filter: { } + update: { $set: { 'y.$[i].b': 2 } } + arrayFilters: + - { i.b: 1 } + expectResult: { _id: 1, y: [ { b: 3 }, { b: 1 } ] } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, y: [ { b: 3 }, { b: 2 } ] } + - { _id: 2, y: [ { b: 0 }, { b: 1 } ] } diff --git a/test/spec/crud/unified/findOneAndUpdate-collation.json b/test/spec/crud/unified/findOneAndUpdate-collation.json new file mode 100644 index 0000000000..7a49347a3a --- /dev/null +++ b/test/spec/crud/unified/findOneAndUpdate-collation.json @@ -0,0 +1,106 @@ +{ + "description": "findOneAndUpdate-collation", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "3.4", + "serverless": "forbid" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": "ping" + }, + { + "_id": 3, + "x": "pINg" + } + ] + } + ], + "tests": [ + { + "description": "FindOneAndUpdate when many documents match with collation returning the document before modification", + "operations": [ + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "x": "PING" + }, + "update": { + "$set": { + "x": "pong" + } + }, + "projection": { + "x": 1, + "_id": 0 + }, + "sort": { + "_id": 1 + }, + "collation": { + "locale": "en_US", + "strength": 2 + } + }, + "expectResult": { + "x": "ping" + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": "pong" + }, + { + "_id": 3, + "x": "pINg" + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/findOneAndUpdate-collation.yml b/test/spec/crud/unified/findOneAndUpdate-collation.yml new file mode 100644 index 0000000000..8b2048bc82 --- /dev/null +++ b/test/spec/crud/unified/findOneAndUpdate-collation.yml @@ -0,0 +1,58 @@ +description: findOneAndUpdate-collation + +schemaVersion: '1.4' + +runOnRequirements: + - + minServerVersion: '3.4' + serverless: forbid + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: ping } + - { _id: 3, x: pINg } + +tests: + - + description: 'FindOneAndUpdate when many documents match with collation returning the document before modification' + operations: + - + object: *collection0 + name: findOneAndUpdate + arguments: + filter: { x: PING } + update: { $set: { x: pong } } + projection: { x: 1, _id: 0 } + sort: { _id: 1 } + # https://www.mongodb.com/docs/manual/reference/collation/#collation-document + collation: + locale: en_US + strength: 2 + expectResult: { x: ping } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: pong } + - { _id: 3, x: pINg } diff --git a/test/spec/crud/unified/findOneAndUpdate-hint-clientError.yml b/test/spec/crud/unified/findOneAndUpdate-hint-clientError.yml index 5ad4f07ccf..77b41a165c 100644 --- a/test/spec/crud/unified/findOneAndUpdate-hint-clientError.yml +++ b/test/spec/crud/unified/findOneAndUpdate-hint-clientError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: findOneAndUpdate-hint-clientError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/findOneAndUpdate-hint-serverError.yml b/test/spec/crud/unified/findOneAndUpdate-hint-serverError.yml index f6b4f8d623..13abba5f5c 100644 --- a/test/spec/crud/unified/findOneAndUpdate-hint-serverError.yml +++ b/test/spec/crud/unified/findOneAndUpdate-hint-serverError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: findOneAndUpdate-hint-serverError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/findOneAndUpdate-hint-unacknowledged.json b/test/spec/crud/unified/findOneAndUpdate-hint-unacknowledged.json new file mode 100644 index 0000000000..d116a06d0d --- /dev/null +++ b/test/spec/crud/unified/findOneAndUpdate-hint-unacknowledged.json @@ -0,0 +1,253 @@ +{ + "description": "findOneAndUpdate-hint-unacknowledged", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "db0" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + } + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "db0", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "Unacknowledged findOneAndUpdate with hint string fails with client-side error on pre-4.4 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.2.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged findOneAndUpdate with hint document fails with client-side error on pre-4.4 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.2.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged findOneAndUpdate with hint string on 4.4+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.4.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + }, + "expectResult": { + "$$unsetOrMatches": null + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "findAndModify": "coll0", + "query": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "$$type": [ + "string", + "object" + ] + }, + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + }, + { + "description": "Unacknowledged findOneAndUpdate with hint document on 4.4+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.4.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "expectResult": { + "$$unsetOrMatches": null + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "findAndModify": "coll0", + "query": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "$$type": [ + "string", + "object" + ] + }, + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/findOneAndUpdate-hint-unacknowledged.yml b/test/spec/crud/unified/findOneAndUpdate-hint-unacknowledged.yml new file mode 100644 index 0000000000..ec576375a6 --- /dev/null +++ b/test/spec/crud/unified/findOneAndUpdate-hint-unacknowledged.yml @@ -0,0 +1,92 @@ +description: findOneAndUpdate-hint-unacknowledged + +schemaVersion: '1.0' + +createEntities: + - client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name db0 + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + collectionOptions: + writeConcern: { w: 0 } + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: &documents + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - description: "Unacknowledged findOneAndUpdate with hint string fails with client-side error on pre-4.4 server" + runOnRequirements: + - maxServerVersion: "4.2.99" + operations: + - object: *collection0 + name: findOneAndUpdate + arguments: + filter: &filter { _id: { $gt: 1 } } + update: &update { $inc: { x: 1 } } + hint: _id_ + expectError: + isClientError: true + expectEvents: &noEvents + - client: *client0 + events: [] + + - description: "Unacknowledged findOneAndUpdate with hint document fails with client-side error on pre-4.4 server" + runOnRequirements: + - maxServerVersion: "4.2.99" + operations: + - object: *collection0 + name: findOneAndUpdate + arguments: + filter: *filter + update: *update + hint: { _id: 1 } + expectError: + isClientError: true + expectEvents: *noEvents + + - description: "Unacknowledged findOneAndUpdate with hint string on 4.4+ server" + runOnRequirements: + - minServerVersion: "4.4.0" + operations: + - object: *collection0 + name: findOneAndUpdate + arguments: + filter: *filter + update: *update + hint: _id_ + expectResult: &unacknowledgedResult { $$unsetOrMatches: null } + expectEvents: &events + - client: *client0 + events: + - commandStartedEvent: + command: + findAndModify: *collection0Name + query: *filter + update: *update + hint: { $$type: [ string, object ]} + writeConcern: { w: 0 } + + - description: "Unacknowledged findOneAndUpdate with hint document on 4.4+ server" + runOnRequirements: + - minServerVersion: "4.4.0" + operations: + - object: *collection0 + name: findOneAndUpdate + arguments: + filter: *filter + update: *update + hint: { _id: 1 } + expectResult: *unacknowledgedResult + expectEvents: *events diff --git a/test/spec/crud/unified/findOneAndUpdate-hint.yml b/test/spec/crud/unified/findOneAndUpdate-hint.yml index 5e835faa9e..f7a3c33f08 100644 --- a/test/spec/crud/unified/findOneAndUpdate-hint.yml +++ b/test/spec/crud/unified/findOneAndUpdate-hint.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: findOneAndUpdate-hint schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/findOneAndUpdate.json b/test/spec/crud/unified/findOneAndUpdate.json new file mode 100644 index 0000000000..d79cf8ac5b --- /dev/null +++ b/test/spec/crud/unified/findOneAndUpdate.json @@ -0,0 +1,448 @@ +{ + "description": "findOneAndUpdate", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "FindOneAndUpdate when many documents match returning the document before modification", + "operations": [ + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "projection": { + "x": 1, + "_id": 0 + }, + "sort": { + "x": 1 + } + }, + "expectResult": { + "x": 22 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 23 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "FindOneAndUpdate when many documents match returning the document after modification", + "operations": [ + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "projection": { + "x": 1, + "_id": 0 + }, + "returnDocument": "After", + "sort": { + "x": 1 + } + }, + "expectResult": { + "x": 23 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 23 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "FindOneAndUpdate when one document matches returning the document before modification", + "operations": [ + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 2 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "projection": { + "x": 1, + "_id": 0 + }, + "sort": { + "x": 1 + } + }, + "expectResult": { + "x": 22 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 23 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "FindOneAndUpdate when one document matches returning the document after modification", + "operations": [ + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 2 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "projection": { + "x": 1, + "_id": 0 + }, + "returnDocument": "After", + "sort": { + "x": 1 + } + }, + "expectResult": { + "x": 23 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 23 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "FindOneAndUpdate when no documents match returning the document before modification", + "operations": [ + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 4 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "projection": { + "x": 1, + "_id": 0 + }, + "sort": { + "x": 1 + } + }, + "expectResult": null + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "FindOneAndUpdate when no documents match with upsert returning the document before modification", + "operations": [ + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 4 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "projection": { + "x": 1, + "_id": 0 + }, + "upsert": true + }, + "expectResult": null + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 1 + } + ] + } + ] + }, + { + "description": "FindOneAndUpdate when no documents match returning the document after modification", + "operations": [ + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 4 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "projection": { + "x": 1, + "_id": 0 + }, + "returnDocument": "After", + "sort": { + "x": 1 + } + }, + "expectResult": null + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "FindOneAndUpdate when no documents match with upsert returning the document after modification", + "operations": [ + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 4 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "projection": { + "x": 1, + "_id": 0 + }, + "returnDocument": "After", + "sort": { + "x": 1 + }, + "upsert": true + }, + "expectResult": { + "x": 1 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 1 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/findOneAndUpdate.yml b/test/spec/crud/unified/findOneAndUpdate.yml new file mode 100644 index 0000000000..181c6b8b54 --- /dev/null +++ b/test/spec/crud/unified/findOneAndUpdate.yml @@ -0,0 +1,199 @@ +description: findOneAndUpdate + +schemaVersion: '1.0' + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - + description: 'FindOneAndUpdate when many documents match returning the document before modification' + operations: + - + object: *collection0 + name: findOneAndUpdate + arguments: + filter: { _id: { $gt: 1 } } + update: { $inc: { x: 1 } } + projection: { x: 1, _id: 0 } + sort: { x: 1 } + expectResult: { x: 22 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 23 } + - { _id: 3, x: 33 } + - + description: 'FindOneAndUpdate when many documents match returning the document after modification' + operations: + - + object: *collection0 + name: findOneAndUpdate + arguments: + filter: { _id: { $gt: 1 } } + update: { $inc: { x: 1 } } + projection: { x: 1, _id: 0 } + returnDocument: After + sort: { x: 1 } + expectResult: { x: 23 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 23 } + - { _id: 3, x: 33 } + - + description: 'FindOneAndUpdate when one document matches returning the document before modification' + operations: + - + object: *collection0 + name: findOneAndUpdate + arguments: + filter: { _id: 2 } + update: { $inc: { x: 1 } } + projection: { x: 1, _id: 0 } + sort: { x: 1 } + expectResult: { x: 22 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 23 } + - { _id: 3, x: 33 } + - + description: 'FindOneAndUpdate when one document matches returning the document after modification' + operations: + - + object: *collection0 + name: findOneAndUpdate + arguments: + filter: { _id: 2 } + update: { $inc: { x: 1 } } + projection: { x: 1, _id: 0 } + returnDocument: After + sort: { x: 1 } + expectResult: { x: 23 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 23 } + - { _id: 3, x: 33 } + - + description: 'FindOneAndUpdate when no documents match returning the document before modification' + operations: + - + object: *collection0 + name: findOneAndUpdate + arguments: + filter: { _id: 4 } + update: { $inc: { x: 1 } } + projection: { x: 1, _id: 0 } + sort: { x: 1 } + expectResult: null + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'FindOneAndUpdate when no documents match with upsert returning the document before modification' + operations: + - + object: *collection0 + name: findOneAndUpdate + arguments: + filter: { _id: 4 } + update: { $inc: { x: 1 } } + projection: { x: 1, _id: 0 } + # Omit the sort option as it has no effect when no documents match and + # would only cause an inconsistent return value on pre-3.0 servers + # when combined with returnDocument "before" (see: SERVER-17650). + upsert: true + expectResult: null + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - { _id: 4, x: 1 } + - + description: 'FindOneAndUpdate when no documents match returning the document after modification' + operations: + - + object: *collection0 + name: findOneAndUpdate + arguments: + filter: { _id: 4 } + update: { $inc: { x: 1 } } + projection: { x: 1, _id: 0 } + returnDocument: After + sort: { x: 1 } + expectResult: null + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'FindOneAndUpdate when no documents match with upsert returning the document after modification' + operations: + - + object: *collection0 + name: findOneAndUpdate + arguments: + filter: { _id: 4 } + update: { $inc: { x: 1 } } + projection: { x: 1, _id: 0 } + returnDocument: After + sort: { x: 1 } + upsert: true + expectResult: { x: 1 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - { _id: 4, x: 1 } diff --git a/test/spec/crud/unified/insertMany-comment.json b/test/spec/crud/unified/insertMany-comment.json index 7e835e8011..2b4c80b3f0 100644 --- a/test/spec/crud/unified/insertMany-comment.json +++ b/test/spec/crud/unified/insertMany-comment.json @@ -166,6 +166,7 @@ "description": "insertMany with comment - pre 4.4", "runOnRequirements": [ { + "minServerVersion": "3.4.0", "maxServerVersion": "4.2.99" } ], diff --git a/test/spec/crud/unified/insertMany-comment.yml b/test/spec/crud/unified/insertMany-comment.yml index ff86029a4f..4b51584df2 100644 --- a/test/spec/crud/unified/insertMany-comment.yml +++ b/test/spec/crud/unified/insertMany-comment.yml @@ -70,7 +70,8 @@ tests: - description: "insertMany with comment - pre 4.4" runOnRequirements: - - maxServerVersion: "4.2.99" + - minServerVersion: "3.4.0" + maxServerVersion: "4.2.99" operations: - name: insertMany object: *collection0 diff --git a/test/spec/crud/unified/insertMany.json b/test/spec/crud/unified/insertMany.json new file mode 100644 index 0000000000..643b7f44de --- /dev/null +++ b/test/spec/crud/unified/insertMany.json @@ -0,0 +1,205 @@ +{ + "description": "insertMany", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ], + "tests": [ + { + "description": "InsertMany with non-existing documents", + "operations": [ + { + "object": "collection0", + "name": "insertMany", + "arguments": { + "documents": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "ordered": true + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedIds": { + "$$unsetOrMatches": { + "0": 2, + "1": 3 + } + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "InsertMany continue-on-error behavior with unordered (preexisting duplicate key)", + "operations": [ + { + "object": "collection0", + "name": "insertMany", + "arguments": { + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "ordered": false + }, + "expectError": { + "isError": true, + "expectResult": { + "deletedCount": 0, + "insertedCount": 2, + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 0, + "upsertedIds": {} + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "InsertMany continue-on-error behavior with unordered (duplicate key in requests)", + "operations": [ + { + "object": "collection0", + "name": "insertMany", + "arguments": { + "documents": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "ordered": false + }, + "expectError": { + "isError": true, + "expectResult": { + "deletedCount": 0, + "insertedCount": 2, + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 0, + "upsertedIds": {} + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/insertMany.yml b/test/spec/crud/unified/insertMany.yml new file mode 100644 index 0000000000..ac4e868cc1 --- /dev/null +++ b/test/spec/crud/unified/insertMany.yml @@ -0,0 +1,118 @@ +description: insertMany + +schemaVersion: '1.0' + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + +tests: + - + description: 'InsertMany with non-existing documents' + operations: + - + object: *collection0 + name: insertMany + arguments: + documents: + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + ordered: true + expectResult: + $$unsetOrMatches: + insertedIds: + $$unsetOrMatches: + '0': 2 + '1': 3 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'InsertMany continue-on-error behavior with unordered (preexisting duplicate key)' + operations: + - + object: *collection0 + name: insertMany + arguments: + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + ordered: false + expectError: + isError: true + expectResult: + deletedCount: 0 + insertedCount: 2 + # Since the map of insertedIds is generated before execution it + # could indicate inserts that did not actually succeed. We omit this + # field rather than expect drivers to provide an accurate map + # filtered by write errors. + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'InsertMany continue-on-error behavior with unordered (duplicate key in requests)' + operations: + - + object: *collection0 + name: insertMany + arguments: + documents: + - { _id: 2, x: 22 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + ordered: false + expectError: + isError: true + expectResult: + deletedCount: 0 + insertedCount: 2 + # Since the map of insertedIds is generated before execution it + # could indicate inserts that did not actually succeed. We omit this + # field rather than expect drivers to provide an accurate map + # filtered by write errors. + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } diff --git a/test/spec/crud/unified/insertOne-comment.json b/test/spec/crud/unified/insertOne-comment.json index a9f735ab6c..dbd83d9f64 100644 --- a/test/spec/crud/unified/insertOne-comment.json +++ b/test/spec/crud/unified/insertOne-comment.json @@ -162,6 +162,7 @@ "description": "insertOne with comment - pre 4.4", "runOnRequirements": [ { + "minServerVersion": "3.4.0", "maxServerVersion": "4.2.99" } ], diff --git a/test/spec/crud/unified/insertOne-comment.yml b/test/spec/crud/unified/insertOne-comment.yml index 729b038f2f..f8cb60ce85 100644 --- a/test/spec/crud/unified/insertOne-comment.yml +++ b/test/spec/crud/unified/insertOne-comment.yml @@ -69,7 +69,8 @@ tests: - description: "insertOne with comment - pre 4.4" runOnRequirements: - - maxServerVersion: "4.2.99" + - minServerVersion: "3.4.0" + maxServerVersion: "4.2.99" operations: - name: insertOne object: *collection0 diff --git a/test/spec/crud/unified/insertOne.json b/test/spec/crud/unified/insertOne.json new file mode 100644 index 0000000000..1a90913476 --- /dev/null +++ b/test/spec/crud/unified/insertOne.json @@ -0,0 +1,77 @@ +{ + "description": "insertOne", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ], + "tests": [ + { + "description": "InsertOne with a non-existing document", + "operations": [ + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 2, + "x": 22 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 2 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/insertOne.yml b/test/spec/crud/unified/insertOne.yml new file mode 100644 index 0000000000..85ab7fe9e0 --- /dev/null +++ b/test/spec/crud/unified/insertOne.yml @@ -0,0 +1,44 @@ +description: insertOne + +schemaVersion: '1.0' + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + +tests: + - + description: 'InsertOne with a non-existing document' + operations: + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 2, x: 22 } + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 2 } } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } diff --git a/test/spec/crud/unified/replaceOne-collation.json b/test/spec/crud/unified/replaceOne-collation.json new file mode 100644 index 0000000000..dd76b9d616 --- /dev/null +++ b/test/spec/crud/unified/replaceOne-collation.json @@ -0,0 +1,92 @@ +{ + "description": "replaceOne-collation", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "3.4", + "serverless": "forbid" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": "ping" + } + ] + } + ], + "tests": [ + { + "description": "ReplaceOne when one document matches with collation", + "operations": [ + { + "object": "collection0", + "name": "replaceOne", + "arguments": { + "filter": { + "x": "PING" + }, + "replacement": { + "_id": 2, + "x": "pong" + }, + "collation": { + "locale": "en_US", + "strength": 2 + } + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": "pong" + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/replaceOne-collation.yml b/test/spec/crud/unified/replaceOne-collation.yml new file mode 100644 index 0000000000..68eddcff91 --- /dev/null +++ b/test/spec/crud/unified/replaceOne-collation.yml @@ -0,0 +1,57 @@ +description: replaceOne-collation + +schemaVersion: '1.4' + +runOnRequirements: + - + minServerVersion: '3.4' + serverless: forbid + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: ping } + +tests: + - + description: 'ReplaceOne when one document matches with collation' + operations: + - + object: *collection0 + name: replaceOne + arguments: + filter: { x: PING } + replacement: { _id: 2, x: pong } + # https://www.mongodb.com/docs/manual/reference/collation/#collation-document + collation: + locale: en_US + strength: 2 + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: pong } diff --git a/test/spec/crud/unified/replaceOne-comment.json b/test/spec/crud/unified/replaceOne-comment.json index bcd8aca22f..88bee5d7b7 100644 --- a/test/spec/crud/unified/replaceOne-comment.json +++ b/test/spec/crud/unified/replaceOne-comment.json @@ -178,6 +178,7 @@ "description": "ReplaceOne with comment - pre 4.4", "runOnRequirements": [ { + "minServerVersion": "3.4.0", "maxServerVersion": "4.2.99" } ], diff --git a/test/spec/crud/unified/replaceOne-comment.yml b/test/spec/crud/unified/replaceOne-comment.yml index 5453c5977d..2c22b28757 100644 --- a/test/spec/crud/unified/replaceOne-comment.yml +++ b/test/spec/crud/unified/replaceOne-comment.yml @@ -78,7 +78,8 @@ tests: - description: "ReplaceOne with comment - pre 4.4" runOnRequirements: - - maxServerVersion: "4.2.99" + - minServerVersion: "3.4.0" + maxServerVersion: "4.2.99" operations: - name: replaceOne object: *collection0 diff --git a/test/spec/crud/unified/replaceOne-hint-unacknowledged.json b/test/spec/crud/unified/replaceOne-hint-unacknowledged.json new file mode 100644 index 0000000000..5c5dec64f6 --- /dev/null +++ b/test/spec/crud/unified/replaceOne-hint-unacknowledged.json @@ -0,0 +1,269 @@ +{ + "description": "replaceOne-hint-unacknowledged", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "db0" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + } + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "db0", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "Unacknowledged replaceOne with hint string fails with client-side error on pre-4.2 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.0.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "replaceOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 111 + }, + "hint": "_id_" + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged replaceOne with hint document fails with client-side error on pre-4.2 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.0.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "replaceOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 111 + }, + "hint": { + "_id": 1 + } + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged replaceOne with hint string on 4.2+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.2.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "replaceOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 111 + }, + "hint": "_id_" + }, + "expectResult": { + "$$unsetOrMatches": { + "acknowledged": { + "$$unsetOrMatches": false + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "update": "coll0", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "x": 111 + }, + "multi": { + "$$unsetOrMatches": false + }, + "upsert": { + "$$unsetOrMatches": false + }, + "hint": { + "$$type": [ + "string", + "object" + ] + } + } + ], + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + }, + { + "description": "Unacknowledged replaceOne with hint document on 4.2+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.2.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "replaceOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 111 + }, + "hint": { + "_id": 1 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "acknowledged": { + "$$unsetOrMatches": false + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "update": "coll0", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "x": 111 + }, + "multi": { + "$$unsetOrMatches": false + }, + "upsert": { + "$$unsetOrMatches": false + }, + "hint": { + "$$type": [ + "string", + "object" + ] + } + } + ], + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/replaceOne-hint-unacknowledged.yml b/test/spec/crud/unified/replaceOne-hint-unacknowledged.yml new file mode 100644 index 0000000000..debb99b22f --- /dev/null +++ b/test/spec/crud/unified/replaceOne-hint-unacknowledged.yml @@ -0,0 +1,95 @@ +description: replaceOne-hint-unacknowledged + +schemaVersion: '1.0' + +createEntities: + - client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name db0 + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + collectionOptions: + writeConcern: { w: 0 } + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: &documents + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - description: "Unacknowledged replaceOne with hint string fails with client-side error on pre-4.2 server" + runOnRequirements: + - maxServerVersion: "4.0.99" + operations: + - object: *collection0 + name: replaceOne + arguments: + filter: &filter { _id: { $gt: 1 } } + replacement: &replacement { x: 111 } + hint: _id_ + expectError: + isClientError: true + expectEvents: &noEvents + - client: *client0 + events: [] + + - description: "Unacknowledged replaceOne with hint document fails with client-side error on pre-4.2 server" + runOnRequirements: + - maxServerVersion: "4.0.99" + operations: + - object: *collection0 + name: replaceOne + arguments: + filter: *filter + replacement: *replacement + hint: { _id: 1 } + expectError: + isClientError: true + expectEvents: *noEvents + + - description: "Unacknowledged replaceOne with hint string on 4.2+ server" + runOnRequirements: + - minServerVersion: "4.2.0" + operations: + - object: *collection0 + name: replaceOne + arguments: + filter: *filter + replacement: *replacement + hint: _id_ + expectResult: &unacknowledgedResult { $$unsetOrMatches: { acknowledged: { $$unsetOrMatches: false } } } + expectEvents: &events + - client: *client0 + events: + - commandStartedEvent: + command: + update: *collection0Name + updates: + - q: *filter + u: *replacement + multi: { $$unsetOrMatches: false } + upsert: { $$unsetOrMatches: false } + hint: { $$type: [ string, object ]} + writeConcern: { w: 0 } + + - description: "Unacknowledged replaceOne with hint document on 4.2+ server" + runOnRequirements: + - minServerVersion: "4.2.0" + operations: + - object: *collection0 + name: replaceOne + arguments: + filter: *filter + replacement: *replacement + hint: { _id: 1 } + expectResult: *unacknowledgedResult + expectEvents: *events diff --git a/test/spec/crud/unified/replaceOne-hint.yml b/test/spec/crud/unified/replaceOne-hint.yml index 8a28be9825..263e372170 100644 --- a/test/spec/crud/unified/replaceOne-hint.yml +++ b/test/spec/crud/unified/replaceOne-hint.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: replaceOne-hint schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/replaceOne.json b/test/spec/crud/unified/replaceOne.json new file mode 100644 index 0000000000..bdb7556f2f --- /dev/null +++ b/test/spec/crud/unified/replaceOne.json @@ -0,0 +1,259 @@ +{ + "description": "replaceOne", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "2.6" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "ReplaceOne when many documents match", + "operations": [ + { + "object": "collection0", + "name": "replaceOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 111 + } + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ] + }, + { + "description": "ReplaceOne when one document matches", + "operations": [ + { + "object": "collection0", + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "_id": 1, + "x": 111 + } + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 111 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "ReplaceOne when no documents match", + "operations": [ + { + "object": "collection0", + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 4 + }, + "replacement": { + "_id": 4, + "x": 1 + } + }, + "expectResult": { + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "ReplaceOne with upsert when no documents match without an id specified", + "operations": [ + { + "object": "collection0", + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 4 + }, + "replacement": { + "x": 1 + }, + "upsert": true + }, + "expectResult": { + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 1, + "upsertedId": 4 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 1 + } + ] + } + ] + }, + { + "description": "ReplaceOne with upsert when no documents match with an id specified", + "operations": [ + { + "object": "collection0", + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 4 + }, + "replacement": { + "_id": 4, + "x": 1 + }, + "upsert": true + }, + "expectResult": { + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 1, + "upsertedId": 4 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 1 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/replaceOne.yml b/test/spec/crud/unified/replaceOne.yml new file mode 100644 index 0000000000..ebe0af933e --- /dev/null +++ b/test/spec/crud/unified/replaceOne.yml @@ -0,0 +1,138 @@ +description: replaceOne + +schemaVersion: '1.0' + +runOnRequirements: + - + minServerVersion: '2.6' + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - + # This test doesn't verify the output collection because we cannot assume + # which document gets replaced. + description: 'ReplaceOne when many documents match' + operations: + - + object: *collection0 + name: replaceOne + arguments: + filter: { _id: { $gt: 1 } } + replacement: { x: 111 } + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + - + description: 'ReplaceOne when one document matches' + operations: + - + object: *collection0 + name: replaceOne + arguments: + filter: { _id: 1 } + replacement: { _id: 1, x: 111 } + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 111 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'ReplaceOne when no documents match' + operations: + - + object: *collection0 + name: replaceOne + arguments: + filter: { _id: 4 } + replacement: { _id: 4, x: 1 } + expectResult: + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'ReplaceOne with upsert when no documents match without an id specified' + operations: + - + object: *collection0 + name: replaceOne + arguments: + filter: { _id: 4 } + replacement: { x: 1 } + upsert: true + expectResult: + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 1 + upsertedId: 4 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - { _id: 4, x: 1 } + - + description: 'ReplaceOne with upsert when no documents match with an id specified' + operations: + - + object: *collection0 + name: replaceOne + arguments: + filter: { _id: 4 } + replacement: { _id: 4, x: 1 } + upsert: true + expectResult: + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 1 + upsertedId: 4 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - { _id: 4, x: 1 } diff --git a/test/spec/crud/unified/unacknowledged-bulkWrite-delete-hint-clientError.yml b/test/spec/crud/unified/unacknowledged-bulkWrite-delete-hint-clientError.yml deleted file mode 100644 index 3aaa182436..0000000000 --- a/test/spec/crud/unified/unacknowledged-bulkWrite-delete-hint-clientError.yml +++ /dev/null @@ -1,112 +0,0 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - -description: unacknowledged-bulkWrite-delete-hint-clientError -schemaVersion: '1.0' -createEntities: - - - client: - id: &client0 client0 - observeEvents: - - commandStartedEvent - - - database: - id: &database0 database0 - client: client0 - databaseName: &database_name crud-v2 - - - collection: - id: &collection0 collection0 - database: database0 - collectionName: &collection_name BulkWrite_delete_hint - collectionOptions: - writeConcern: { w: 0 } -initialData: - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 - - - _id: 3 - x: 33 - - - _id: 4 - x: 44 -tests: - - - description: 'Unacknowledged bulkWrite deleteOne with hints fails with client-side error' - operations: - - - object: *collection0 - name: bulkWrite - arguments: - requests: - - - deleteOne: - filter: &deleteOne_filter1 - _id: 1 - hint: &hint_string _id_ - - - deleteOne: - filter: &deleteOne_filter2 - _id: 2 - hint: &hint_doc - _id: 1 - ordered: true - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: &outcome - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 - - - _id: 3 - x: 33 - - - _id: 4 - x: 44 - - - description: 'Unacknowledged bulkWrite deleteMany with hints fails with client-side error' - operations: - - - object: *collection0 - name: bulkWrite - arguments: - requests: - - - deleteMany: - filter: &deleteMany_filter1 - _id: - $lt: 3 - hint: *hint_string - - - deleteMany: - filter: &deleteMany_filter2 - _id: - $gte: 4 - hint: *hint_doc - ordered: true - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: *outcome diff --git a/test/spec/crud/unified/unacknowledged-bulkWrite-update-hint-clientError.json b/test/spec/crud/unified/unacknowledged-bulkWrite-update-hint-clientError.json deleted file mode 100644 index 858967b90c..0000000000 --- a/test/spec/crud/unified/unacknowledged-bulkWrite-update-hint-clientError.json +++ /dev/null @@ -1,284 +0,0 @@ -{ - "description": "unacknowledged-bulkWrite-update-hint-clientError", - "schemaVersion": "1.0", - "createEntities": [ - { - "client": { - "id": "client0", - "observeEvents": [ - "commandStartedEvent" - ] - } - }, - { - "database": { - "id": "database0", - "client": "client0", - "databaseName": "crud-v2" - } - }, - { - "collection": { - "id": "collection0", - "database": "database0", - "collectionName": "Bulkwrite_update_hint", - "collectionOptions": { - "writeConcern": { - "w": 0 - } - } - } - } - ], - "initialData": [ - { - "collectionName": "Bulkwrite_update_hint", - "databaseName": "crud-v2", - "documents": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - ], - "tests": [ - { - "description": "Unacknowledged bulkWrite updateOne with hints fails with client-side error", - "operations": [ - { - "object": "collection0", - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "updateOne": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "hint": "_id_" - } - }, - { - "updateOne": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "hint": { - "_id": 1 - } - } - } - ], - "ordered": true - }, - "expectError": { - "isError": true - } - } - ], - "expectEvents": [ - { - "client": "client0", - "events": [] - } - ], - "outcome": [ - { - "collectionName": "Bulkwrite_update_hint", - "databaseName": "crud-v2", - "documents": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - ] - }, - { - "description": "Unacknowledged bulkWrite updateMany with hints fails with client-side error", - "operations": [ - { - "object": "collection0", - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "updateMany": { - "filter": { - "_id": { - "$lt": 3 - } - }, - "update": { - "$inc": { - "x": 1 - } - }, - "hint": "_id_" - } - }, - { - "updateMany": { - "filter": { - "_id": { - "$lt": 3 - } - }, - "update": { - "$inc": { - "x": 1 - } - }, - "hint": { - "_id": 1 - } - } - } - ], - "ordered": true - }, - "expectError": { - "isError": true - } - } - ], - "expectEvents": [ - { - "client": "client0", - "events": [] - } - ], - "outcome": [ - { - "collectionName": "Bulkwrite_update_hint", - "databaseName": "crud-v2", - "documents": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - ] - }, - { - "description": "Unacknowledged bulkWrite replaceOne with hints fails with client-side error", - "operations": [ - { - "object": "collection0", - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "replaceOne": { - "filter": { - "_id": 3 - }, - "replacement": { - "x": 333 - }, - "hint": "_id_" - } - }, - { - "replaceOne": { - "filter": { - "_id": 4 - }, - "replacement": { - "x": 444 - }, - "hint": { - "_id": 1 - } - } - } - ], - "ordered": true - }, - "expectError": { - "isError": true - } - } - ], - "expectEvents": [ - { - "client": "client0", - "events": [] - } - ], - "outcome": [ - { - "collectionName": "Bulkwrite_update_hint", - "databaseName": "crud-v2", - "documents": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - ] - } - ] -} diff --git a/test/spec/crud/unified/unacknowledged-bulkWrite-update-hint-clientError.yml b/test/spec/crud/unified/unacknowledged-bulkWrite-update-hint-clientError.yml deleted file mode 100644 index 95620f097a..0000000000 --- a/test/spec/crud/unified/unacknowledged-bulkWrite-update-hint-clientError.yml +++ /dev/null @@ -1,147 +0,0 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - -description: unacknowledged-bulkWrite-update-hint-clientError -schemaVersion: '1.0' -createEntities: - - - client: - id: &client0 client0 - observeEvents: - - commandStartedEvent - - - database: - id: &database0 database0 - client: client0 - databaseName: &database_name crud-v2 - - - collection: - id: &collection0 collection0 - database: database0 - collectionName: &collection_name Bulkwrite_update_hint - collectionOptions: - writeConcern: { w: 0 } -initialData: - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 - - - _id: 3 - x: 33 - - - _id: 4 - x: 44 -tests: - - - description: 'Unacknowledged bulkWrite updateOne with hints fails with client-side error' - operations: - - - object: *collection0 - name: bulkWrite - arguments: - requests: - - - updateOne: - filter: &updateOne_filter - _id: 1 - update: &updateOne_update - $inc: - x: 1 - hint: &hint_string _id_ - - - updateOne: - filter: *updateOne_filter - update: *updateOne_update - hint: &hint_doc - _id: 1 - ordered: true - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: &outcome - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 - - - _id: 3 - x: 33 - - - _id: 4 - x: 44 - - - description: 'Unacknowledged bulkWrite updateMany with hints fails with client-side error' - operations: - - - object: *collection0 - name: bulkWrite - arguments: - requests: - - - updateMany: - filter: &updateMany_filter - _id: - $lt: 3 - update: &updateMany_update - $inc: - x: 1 - hint: *hint_string - - - updateMany: - filter: *updateMany_filter - update: *updateMany_update - hint: *hint_doc - ordered: true - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: *outcome - - - description: 'Unacknowledged bulkWrite replaceOne with hints fails with client-side error' - operations: - - - object: *collection0 - name: bulkWrite - arguments: - requests: - - - replaceOne: - filter: - _id: 3 - replacement: - x: 333 - hint: *hint_string - - - replaceOne: - filter: - _id: 4 - replacement: - x: 444 - hint: *hint_doc - ordered: true - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: *outcome diff --git a/test/spec/crud/unified/unacknowledged-deleteMany-hint-clientError.yml b/test/spec/crud/unified/unacknowledged-deleteMany-hint-clientError.yml deleted file mode 100644 index 7acbbc7ca8..0000000000 --- a/test/spec/crud/unified/unacknowledged-deleteMany-hint-clientError.yml +++ /dev/null @@ -1,86 +0,0 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - -description: unacknowledged-deleteMany-hint-clientError -schemaVersion: '1.0' -createEntities: - - - client: - id: &client0 client0 - observeEvents: - - commandStartedEvent - - - database: - id: &database0 database0 - client: client0 - databaseName: &database_name crud-v2 - - - collection: - id: &collection0 collection0 - database: database0 - collectionName: &collection_name DeleteMany_hint - collectionOptions: - writeConcern: { w: 0 } -initialData: - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 - - - _id: 3 - x: 33 -tests: - - - description: 'Unacknowledged deleteMany with hint string fails with client-side error' - operations: - - - object: *collection0 - name: deleteMany - arguments: - filter: &filter - _id: - $gt: 1 - hint: _id_ - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: &outcome - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 - - - _id: 3 - x: 33 - - - description: 'Unacknowledged deleteMany with hint document fails with client-side error' - operations: - - - object: *collection0 - name: deleteMany - arguments: - filter: *filter - hint: - _id: 1 - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: *outcome diff --git a/test/spec/crud/unified/unacknowledged-deleteOne-hint-clientError.yml b/test/spec/crud/unified/unacknowledged-deleteOne-hint-clientError.yml deleted file mode 100644 index 996dad6cac..0000000000 --- a/test/spec/crud/unified/unacknowledged-deleteOne-hint-clientError.yml +++ /dev/null @@ -1,79 +0,0 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - -description: unacknowledged-deleteOne-hint-clientError -schemaVersion: '1.0' -createEntities: - - - client: - id: &client0 client0 - observeEvents: - - commandStartedEvent - - - database: - id: &database0 database0 - client: client0 - databaseName: &database_name crud-v2 - - - collection: - id: &collection0 collection0 - database: database0 - collectionName: &collection_name DeleteOne_hint - collectionOptions: - writeConcern: { w: 0 } -initialData: - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 -tests: - - - description: 'Unacknowledged deleteOne with hint string fails with client-side error' - operations: - - - object: *collection0 - name: deleteOne - arguments: - filter: &filter - _id: 1 - hint: _id_ - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: &outcome - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 - - - description: 'Unacknowledged deleteOne with hint document fails with client-side error' - operations: - - - object: *collection0 - name: deleteOne - arguments: - filter: *filter - hint: - _id: 1 - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: *outcome diff --git a/test/spec/crud/unified/unacknowledged-findOneAndDelete-hint-clientError.json b/test/spec/crud/unified/unacknowledged-findOneAndDelete-hint-clientError.json deleted file mode 100644 index 6ee59cdf64..0000000000 --- a/test/spec/crud/unified/unacknowledged-findOneAndDelete-hint-clientError.json +++ /dev/null @@ -1,133 +0,0 @@ -{ - "description": "unacknowledged-findOneAndDelete-hint-clientError", - "schemaVersion": "1.0", - "createEntities": [ - { - "client": { - "id": "client0", - "observeEvents": [ - "commandStartedEvent" - ] - } - }, - { - "database": { - "id": "database0", - "client": "client0", - "databaseName": "crud-v2" - } - }, - { - "collection": { - "id": "collection0", - "database": "database0", - "collectionName": "findOneAndDelete_hint", - "collectionOptions": { - "writeConcern": { - "w": 0 - } - } - } - } - ], - "initialData": [ - { - "collectionName": "findOneAndDelete_hint", - "databaseName": "crud-v2", - "documents": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - ], - "tests": [ - { - "description": "Unacknowledged findOneAndDelete with hint string fails with client-side error", - "operations": [ - { - "object": "collection0", - "name": "findOneAndDelete", - "arguments": { - "filter": { - "_id": 1 - }, - "hint": "_id_" - }, - "expectError": { - "isError": true - } - } - ], - "expectEvents": [ - { - "client": "client0", - "events": [] - } - ], - "outcome": [ - { - "collectionName": "findOneAndDelete_hint", - "databaseName": "crud-v2", - "documents": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - ] - }, - { - "description": "Unacknowledged findOneAndDelete with hint document fails with client-side error", - "operations": [ - { - "object": "collection0", - "name": "findOneAndDelete", - "arguments": { - "filter": { - "_id": 1 - }, - "hint": { - "_id": 1 - } - }, - "expectError": { - "isError": true - } - } - ], - "expectEvents": [ - { - "client": "client0", - "events": [] - } - ], - "outcome": [ - { - "collectionName": "findOneAndDelete_hint", - "databaseName": "crud-v2", - "documents": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - ] - } - ] -} diff --git a/test/spec/crud/unified/unacknowledged-findOneAndDelete-hint-clientError.yml b/test/spec/crud/unified/unacknowledged-findOneAndDelete-hint-clientError.yml deleted file mode 100644 index 7a619d30a0..0000000000 --- a/test/spec/crud/unified/unacknowledged-findOneAndDelete-hint-clientError.yml +++ /dev/null @@ -1,90 +0,0 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - -description: unacknowledged-findOneAndDelete-hint-clientError -schemaVersion: '1.0' -createEntities: - - - client: - id: &client0 client0 - observeEvents: - - commandStartedEvent - - - database: - id: &database0 database0 - client: client0 - databaseName: &database_name crud-v2 - - - collection: - id: &collection0 collection0 - database: database0 - collectionName: &collection_name findOneAndDelete_hint - collectionOptions: - writeConcern: { w: 0 } -initialData: - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 -tests: - - - description: 'Unacknowledged findOneAndDelete with hint string fails with client-side error' - operations: - - - object: *collection0 - name: findOneAndDelete - arguments: - filter: &filter - _id: 1 - hint: _id_ - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: &outcome - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 - - - description: 'Unacknowledged findOneAndDelete with hint document fails with client-side error' - operations: - - - object: *collection0 - name: findOneAndDelete - arguments: - filter: &filter - _id: 1 - hint: - _id: 1 - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: &outcome - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 diff --git a/test/spec/crud/unified/unacknowledged-findOneAndReplace-hint-clientError.json b/test/spec/crud/unified/unacknowledged-findOneAndReplace-hint-clientError.json deleted file mode 100644 index 15ca773228..0000000000 --- a/test/spec/crud/unified/unacknowledged-findOneAndReplace-hint-clientError.json +++ /dev/null @@ -1,139 +0,0 @@ -{ - "description": "unacknowledged-findOneAndReplace-hint-clientError", - "schemaVersion": "1.0", - "createEntities": [ - { - "client": { - "id": "client0", - "observeEvents": [ - "commandStartedEvent" - ] - } - }, - { - "database": { - "id": "database0", - "client": "client0", - "databaseName": "crud-v2" - } - }, - { - "collection": { - "id": "collection0", - "database": "database0", - "collectionName": "FindOneAndReplace_hint", - "collectionOptions": { - "writeConcern": { - "w": 0 - } - } - } - } - ], - "initialData": [ - { - "collectionName": "FindOneAndReplace_hint", - "databaseName": "crud-v2", - "documents": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - ], - "tests": [ - { - "description": "Unacknowledged findOneAndReplace with hint string fails with client-side error", - "operations": [ - { - "object": "collection0", - "name": "findOneAndReplace", - "arguments": { - "filter": { - "_id": 1 - }, - "replacement": { - "x": 33 - }, - "hint": "_id_" - }, - "expectError": { - "isError": true - } - } - ], - "expectEvents": [ - { - "client": "client0", - "events": [] - } - ], - "outcome": [ - { - "collectionName": "FindOneAndReplace_hint", - "databaseName": "crud-v2", - "documents": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - ] - }, - { - "description": "Unacknowledged findOneAndReplace with hint document fails with client-side error", - "operations": [ - { - "object": "collection0", - "name": "findOneAndReplace", - "arguments": { - "filter": { - "_id": 1 - }, - "replacement": { - "x": 33 - }, - "hint": { - "_id": 1 - } - }, - "expectError": { - "isError": true - } - } - ], - "expectEvents": [ - { - "client": "client0", - "events": [] - } - ], - "outcome": [ - { - "collectionName": "FindOneAndReplace_hint", - "databaseName": "crud-v2", - "documents": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - ] - } - ] -} diff --git a/test/spec/crud/unified/unacknowledged-findOneAndReplace-hint-clientError.yml b/test/spec/crud/unified/unacknowledged-findOneAndReplace-hint-clientError.yml deleted file mode 100644 index cbd12dac98..0000000000 --- a/test/spec/crud/unified/unacknowledged-findOneAndReplace-hint-clientError.yml +++ /dev/null @@ -1,82 +0,0 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - -description: unacknowledged-findOneAndReplace-hint-clientError -schemaVersion: '1.0' -createEntities: - - - client: - id: &client0 client0 - observeEvents: - - commandStartedEvent - - - database: - id: &database0 database0 - client: client0 - databaseName: &database_name crud-v2 - - - collection: - id: &collection0 collection0 - database: database0 - collectionName: &collection_name FindOneAndReplace_hint - collectionOptions: - writeConcern: { w: 0 } -initialData: - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 -tests: - - - description: 'Unacknowledged findOneAndReplace with hint string fails with client-side error' - operations: - - - object: *collection0 - name: findOneAndReplace - arguments: - filter: &filter - _id: 1 - replacement: &replacement - x: 33 - hint: _id_ - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: &outcome - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 - - - description: 'Unacknowledged findOneAndReplace with hint document fails with client-side error' - operations: - - - object: *collection0 - name: findOneAndReplace - arguments: - filter: *filter - replacement: *replacement - hint: - _id: 1 - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: *outcome diff --git a/test/spec/crud/unified/unacknowledged-findOneAndUpdate-hint-clientError.json b/test/spec/crud/unified/unacknowledged-findOneAndUpdate-hint-clientError.json deleted file mode 100644 index e18767f8b2..0000000000 --- a/test/spec/crud/unified/unacknowledged-findOneAndUpdate-hint-clientError.json +++ /dev/null @@ -1,143 +0,0 @@ -{ - "description": "unacknowledged-findOneAndUpdate-hint-clientError", - "schemaVersion": "1.0", - "createEntities": [ - { - "client": { - "id": "client0", - "observeEvents": [ - "commandStartedEvent" - ] - } - }, - { - "database": { - "id": "database0", - "client": "client0", - "databaseName": "crud-v2" - } - }, - { - "collection": { - "id": "collection0", - "database": "database0", - "collectionName": "FindOneAndUpdate_hint", - "collectionOptions": { - "writeConcern": { - "w": 0 - } - } - } - } - ], - "initialData": [ - { - "collectionName": "FindOneAndUpdate_hint", - "databaseName": "crud-v2", - "documents": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - ], - "tests": [ - { - "description": "Unacknowledged findOneAndUpdate with hint string fails with client-side error", - "operations": [ - { - "object": "collection0", - "name": "findOneAndUpdate", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "hint": "_id_" - }, - "expectError": { - "isError": true - } - } - ], - "expectEvents": [ - { - "client": "client0", - "events": [] - } - ], - "outcome": [ - { - "collectionName": "FindOneAndUpdate_hint", - "databaseName": "crud-v2", - "documents": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - ] - }, - { - "description": "Unacknowledged findOneAndUpdate with hint document fails with client-side error", - "operations": [ - { - "object": "collection0", - "name": "findOneAndUpdate", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "hint": { - "_id": 1 - } - }, - "expectError": { - "isError": true - } - } - ], - "expectEvents": [ - { - "client": "client0", - "events": [] - } - ], - "outcome": [ - { - "collectionName": "FindOneAndUpdate_hint", - "databaseName": "crud-v2", - "documents": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - ] - } - ] -} diff --git a/test/spec/crud/unified/unacknowledged-findOneAndUpdate-hint-clientError.yml b/test/spec/crud/unified/unacknowledged-findOneAndUpdate-hint-clientError.yml deleted file mode 100644 index b9cd0229cb..0000000000 --- a/test/spec/crud/unified/unacknowledged-findOneAndUpdate-hint-clientError.yml +++ /dev/null @@ -1,83 +0,0 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - -description: unacknowledged-findOneAndUpdate-hint-clientError -schemaVersion: '1.0' -createEntities: - - - client: - id: &client0 client0 - observeEvents: - - commandStartedEvent - - - database: - id: &database0 database0 - client: client0 - databaseName: &database_name crud-v2 - - - collection: - id: &collection0 collection0 - database: database0 - collectionName: &collection_name FindOneAndUpdate_hint - collectionOptions: - writeConcern: { w: 0 } -initialData: - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 -tests: - - - description: 'Unacknowledged findOneAndUpdate with hint string fails with client-side error' - operations: - - - object: *collection0 - name: findOneAndUpdate - arguments: - filter: &filter - _id: 1 - update: &update - $inc: - x: 1 - hint: _id_ - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: &outcome - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 - - - description: 'Unacknowledged findOneAndUpdate with hint document fails with client-side error' - operations: - - - object: *collection0 - name: findOneAndUpdate - arguments: - filter: *filter - update: *update - hint: - _id: 1 - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: *outcome diff --git a/test/spec/crud/unified/unacknowledged-replaceOne-hint-clientError.json b/test/spec/crud/unified/unacknowledged-replaceOne-hint-clientError.json deleted file mode 100644 index 52ec59d0c0..0000000000 --- a/test/spec/crud/unified/unacknowledged-replaceOne-hint-clientError.json +++ /dev/null @@ -1,143 +0,0 @@ -{ - "description": "unacknowledged-replaceOne-hint-clientError", - "schemaVersion": "1.0", - "createEntities": [ - { - "client": { - "id": "client0", - "observeEvents": [ - "commandStartedEvent" - ] - } - }, - { - "database": { - "id": "database0", - "client": "client0", - "databaseName": "crud-v2" - } - }, - { - "collection": { - "id": "collection0", - "database": "database0", - "collectionName": "ReplaceOne_hint", - "collectionOptions": { - "writeConcern": { - "w": 0 - } - } - } - } - ], - "initialData": [ - { - "collectionName": "ReplaceOne_hint", - "databaseName": "crud-v2", - "documents": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - ], - "tests": [ - { - "description": "Unacknowledged ReplaceOne with hint string fails with client-side error", - "operations": [ - { - "object": "collection0", - "name": "replaceOne", - "arguments": { - "filter": { - "_id": { - "$gt": 1 - } - }, - "replacement": { - "x": 111 - }, - "hint": "_id_" - }, - "expectError": { - "isError": true - } - } - ], - "expectEvents": [ - { - "client": "client0", - "events": [] - } - ], - "outcome": [ - { - "collectionName": "ReplaceOne_hint", - "databaseName": "crud-v2", - "documents": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - ] - }, - { - "description": "Unacknowledged ReplaceOne with hint document fails with client-side error", - "operations": [ - { - "object": "collection0", - "name": "replaceOne", - "arguments": { - "filter": { - "_id": { - "$gt": 1 - } - }, - "replacement": { - "x": 111 - }, - "hint": { - "_id": 1 - } - }, - "expectError": { - "isError": true - } - } - ], - "expectEvents": [ - { - "client": "client0", - "events": [] - } - ], - "outcome": [ - { - "collectionName": "ReplaceOne_hint", - "databaseName": "crud-v2", - "documents": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - ] - } - ] -} diff --git a/test/spec/crud/unified/unacknowledged-replaceOne-hint-clientError.yml b/test/spec/crud/unified/unacknowledged-replaceOne-hint-clientError.yml deleted file mode 100644 index 710cd424b1..0000000000 --- a/test/spec/crud/unified/unacknowledged-replaceOne-hint-clientError.yml +++ /dev/null @@ -1,83 +0,0 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - -description: unacknowledged-replaceOne-hint-clientError -schemaVersion: '1.0' -createEntities: - - - client: - id: &client0 client0 - observeEvents: - - commandStartedEvent - - - database: - id: &database0 database0 - client: client0 - databaseName: &database_name crud-v2 - - - collection: - id: &collection0 collection0 - database: database0 - collectionName: &collection_name ReplaceOne_hint - collectionOptions: - writeConcern: { w: 0 } -initialData: - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 -tests: - - - description: 'Unacknowledged ReplaceOne with hint string fails with client-side error' - operations: - - - object: *collection0 - name: replaceOne - arguments: - filter: &filter - _id: - $gt: 1 - replacement: &replacement - x: 111 - hint: _id_ - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: &outcome - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 - - - description: 'Unacknowledged ReplaceOne with hint document fails with client-side error' - operations: - - - object: *collection0 - name: replaceOne - arguments: - filter: *filter - replacement: *replacement - hint: - _id: 1 - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: *outcome diff --git a/test/spec/crud/unified/unacknowledged-updateMany-hint-clientError.yml b/test/spec/crud/unified/unacknowledged-updateMany-hint-clientError.yml deleted file mode 100644 index 1594c7cd44..0000000000 --- a/test/spec/crud/unified/unacknowledged-updateMany-hint-clientError.yml +++ /dev/null @@ -1,90 +0,0 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - -description: unacknowledged-updateMany-hint-clientError -schemaVersion: '1.0' -createEntities: - - - client: - id: &client0 client0 - observeEvents: - - commandStartedEvent - - - database: - id: &database0 database0 - client: client0 - databaseName: &database_name crud-v2 - - - collection: - id: &collection0 collection0 - database: database0 - collectionName: &collection_name Updatemany_hint - collectionOptions: - writeConcern: { w: 0 } -initialData: - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 - - - _id: 3 - x: 33 -tests: - - - description: 'Unacknowledged updateMany with hint string fails with client-side error' - operations: - - - object: *collection0 - name: updateMany - arguments: - filter: &filter - _id: - $gt: 1 - update: &update - $inc: - x: 1 - hint: _id_ - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: &outcome - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 - - - _id: 3 - x: 33 - - - description: 'Unacknowledged updateMany with hint document fails with client-side error' - operations: - - - object: *collection0 - name: updateMany - arguments: - filter: *filter - update: *update - hint: - _id: 1 - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: *outcome diff --git a/test/spec/crud/unified/unacknowledged-updateOne-hint-clientError.json b/test/spec/crud/unified/unacknowledged-updateOne-hint-clientError.json deleted file mode 100644 index 3828a9e8df..0000000000 --- a/test/spec/crud/unified/unacknowledged-updateOne-hint-clientError.json +++ /dev/null @@ -1,147 +0,0 @@ -{ - "description": "unacknowledged-updateOne-hint-clientError", - "schemaVersion": "1.0", - "createEntities": [ - { - "client": { - "id": "client0", - "observeEvents": [ - "commandStartedEvent" - ] - } - }, - { - "database": { - "id": "database0", - "client": "client0", - "databaseName": "crud-v2" - } - }, - { - "collection": { - "id": "collection0", - "database": "database0", - "collectionName": "UpdateOne_hint", - "collectionOptions": { - "writeConcern": { - "w": 0 - } - } - } - } - ], - "initialData": [ - { - "collectionName": "UpdateOne_hint", - "databaseName": "crud-v2", - "documents": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - ], - "tests": [ - { - "description": "Unacknowledged updateOne with hint string fails with client-side error", - "operations": [ - { - "object": "collection0", - "name": "updateOne", - "arguments": { - "filter": { - "_id": { - "$gt": 1 - } - }, - "update": { - "$inc": { - "x": 1 - } - }, - "hint": "_id_" - }, - "expectError": { - "isError": true - } - } - ], - "expectEvents": [ - { - "client": "client0", - "events": [] - } - ], - "outcome": [ - { - "collectionName": "UpdateOne_hint", - "databaseName": "crud-v2", - "documents": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - ] - }, - { - "description": "Unacknowledged updateOne with hint document fails with client-side error", - "operations": [ - { - "object": "collection0", - "name": "updateOne", - "arguments": { - "filter": { - "_id": { - "$gt": 1 - } - }, - "update": { - "$inc": { - "x": 1 - } - }, - "hint": { - "_id": 1 - } - }, - "expectError": { - "isError": true - } - } - ], - "expectEvents": [ - { - "client": "client0", - "events": [] - } - ], - "outcome": [ - { - "collectionName": "UpdateOne_hint", - "databaseName": "crud-v2", - "documents": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - ] - } - ] -} diff --git a/test/spec/crud/unified/unacknowledged-updateOne-hint-clientError.yml b/test/spec/crud/unified/unacknowledged-updateOne-hint-clientError.yml deleted file mode 100644 index 49126ea006..0000000000 --- a/test/spec/crud/unified/unacknowledged-updateOne-hint-clientError.yml +++ /dev/null @@ -1,84 +0,0 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - -description: unacknowledged-updateOne-hint-clientError -schemaVersion: '1.0' -createEntities: - - - client: - id: &client0 client0 - observeEvents: - - commandStartedEvent - - - database: - id: &database0 database0 - client: client0 - databaseName: &database_name crud-v2 - - - collection: - id: &collection0 collection0 - database: database0 - collectionName: &collection_name UpdateOne_hint - collectionOptions: - writeConcern: { w: 0 } -initialData: - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 -tests: - - - description: 'Unacknowledged updateOne with hint string fails with client-side error' - operations: - - - object: *collection0 - name: updateOne - arguments: - filter: &filter - _id: - $gt: 1 - update: &update - $inc: - x: 1 - hint: _id_ - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: &outcome - - - collectionName: *collection_name - databaseName: *database_name - documents: - - - _id: 1 - x: 11 - - - _id: 2 - x: 22 - - - description: 'Unacknowledged updateOne with hint document fails with client-side error' - operations: - - - object: *collection0 - name: updateOne - arguments: - filter: *filter - update: *update - hint: - _id: 1 - expectError: - isError: true - expectEvents: - - - client: *client0 - events: [] - outcome: *outcome diff --git a/test/spec/crud/unified/updateMany-arrayFilters.json b/test/spec/crud/unified/updateMany-arrayFilters.json new file mode 100644 index 0000000000..8730caeb42 --- /dev/null +++ b/test/spec/crud/unified/updateMany-arrayFilters.json @@ -0,0 +1,233 @@ +{ + "description": "updateMany-arrayFilters", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "3.5.6" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 1 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + } + ] + } + ], + "tests": [ + { + "description": "UpdateMany when no documents match arrayFilters", + "operations": [ + { + "object": "collection0", + "name": "updateMany", + "arguments": { + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 4 + } + ] + }, + "expectResult": { + "matchedCount": 2, + "modifiedCount": 0, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 1 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + } + ] + } + ] + }, + { + "description": "UpdateMany when one document matches arrayFilters", + "operations": [ + { + "object": "collection0", + "name": "updateMany", + "arguments": { + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 3 + } + ] + }, + "expectResult": { + "matchedCount": 2, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "y": [ + { + "b": 2 + }, + { + "b": 1 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + } + ] + } + ] + }, + { + "description": "UpdateMany when multiple documents match arrayFilters", + "operations": [ + { + "object": "collection0", + "name": "updateMany", + "arguments": { + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 1 + } + ] + }, + "expectResult": { + "matchedCount": 2, + "modifiedCount": 2, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 2 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 2 + } + ] + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/updateMany-arrayFilters.yml b/test/spec/crud/unified/updateMany-arrayFilters.yml new file mode 100644 index 0000000000..db5ec29c88 --- /dev/null +++ b/test/spec/crud/unified/updateMany-arrayFilters.yml @@ -0,0 +1,98 @@ +description: updateMany-arrayFilters + +schemaVersion: '1.0' + +runOnRequirements: + - + minServerVersion: 3.5.6 + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, y: [ { b: 3 }, { b: 1 } ] } + - { _id: 2, y: [ { b: 0 }, { b: 1 } ] } + +tests: + - + description: 'UpdateMany when no documents match arrayFilters' + operations: + - + object: *collection0 + name: updateMany + arguments: + filter: { } + update: { $set: { 'y.$[i].b': 2 } } + arrayFilters: + - { i.b: 4 } + expectResult: + matchedCount: 2 + modifiedCount: 0 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, y: [ { b: 3 }, { b: 1 } ] } + - { _id: 2, y: [ { b: 0 }, { b: 1 } ] } + - + description: 'UpdateMany when one document matches arrayFilters' + operations: + - + object: *collection0 + name: updateMany + arguments: + filter: { } + update: { $set: { 'y.$[i].b': 2 } } + arrayFilters: + - { i.b: 3 } + expectResult: + matchedCount: 2 + modifiedCount: 1 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, y: [ { b: 2 }, { b: 1 } ] } + - { _id: 2, y: [ { b: 0 }, { b: 1 } ] } + - + description: 'UpdateMany when multiple documents match arrayFilters' + operations: + - + object: *collection0 + name: updateMany + arguments: + filter: { } + update: { $set: { 'y.$[i].b': 2 } } + arrayFilters: + - { i.b: 1 } + expectResult: + matchedCount: 2 + modifiedCount: 2 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, y: [ { b: 3 }, { b: 2 } ] } + - { _id: 2, y: [ { b: 0 }, { b: 2 } ] } diff --git a/test/spec/crud/unified/updateMany-collation.json b/test/spec/crud/unified/updateMany-collation.json new file mode 100644 index 0000000000..0c780a3c2d --- /dev/null +++ b/test/spec/crud/unified/updateMany-collation.json @@ -0,0 +1,101 @@ +{ + "description": "updateMany-collation", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "3.4", + "serverless": "forbid" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": "ping" + }, + { + "_id": 3, + "x": "pINg" + } + ] + } + ], + "tests": [ + { + "description": "UpdateMany when many documents match with collation", + "operations": [ + { + "object": "collection0", + "name": "updateMany", + "arguments": { + "filter": { + "x": "ping" + }, + "update": { + "$set": { + "x": "pong" + } + }, + "collation": { + "locale": "en_US", + "strength": 2 + } + }, + "expectResult": { + "matchedCount": 2, + "modifiedCount": 2, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": "pong" + }, + { + "_id": 3, + "x": "pong" + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/updateMany-collation.yml b/test/spec/crud/unified/updateMany-collation.yml new file mode 100644 index 0000000000..af5221c02e --- /dev/null +++ b/test/spec/crud/unified/updateMany-collation.yml @@ -0,0 +1,59 @@ +description: updateMany-collation + +schemaVersion: '1.4' + +runOnRequirements: + - + minServerVersion: '3.4' + serverless: forbid + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: ping } + - { _id: 3, x: pINg } + +tests: + - + description: 'UpdateMany when many documents match with collation' + operations: + - + object: *collection0 + name: updateMany + arguments: + filter: { x: ping } + update: { $set: { x: pong } } + # https://www.mongodb.com/docs/manual/reference/collation/#collation-document + collation: + locale: en_US + strength: 2 + expectResult: + matchedCount: 2 + modifiedCount: 2 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: pong } + - { _id: 3, x: pong } diff --git a/test/spec/crud/unified/updateMany-comment.json b/test/spec/crud/unified/updateMany-comment.json index 6411084527..88b8b67f5a 100644 --- a/test/spec/crud/unified/updateMany-comment.json +++ b/test/spec/crud/unified/updateMany-comment.json @@ -182,6 +182,7 @@ "description": "UpdateMany with comment - pre 4.4", "runOnRequirements": [ { + "minServerVersion": "3.4.0", "maxServerVersion": "4.2.99" } ], diff --git a/test/spec/crud/unified/updateMany-comment.yml b/test/spec/crud/unified/updateMany-comment.yml index 7ec8059adf..4c6fbacd77 100644 --- a/test/spec/crud/unified/updateMany-comment.yml +++ b/test/spec/crud/unified/updateMany-comment.yml @@ -77,7 +77,8 @@ tests: - description: "UpdateMany with comment - pre 4.4" runOnRequirements: - - maxServerVersion: "4.2.99" + - minServerVersion: "3.4.0" + maxServerVersion: "4.2.99" operations: - name: updateMany object: *collection0 diff --git a/test/spec/crud/unified/updateMany-hint-clientError.yml b/test/spec/crud/unified/updateMany-hint-clientError.yml index 9734078ce3..163168ecfa 100644 --- a/test/spec/crud/unified/updateMany-hint-clientError.yml +++ b/test/spec/crud/unified/updateMany-hint-clientError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: updateMany-hint-clientError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/updateMany-hint-serverError.yml b/test/spec/crud/unified/updateMany-hint-serverError.yml index 03b803bdde..61d7179fc0 100644 --- a/test/spec/crud/unified/updateMany-hint-serverError.yml +++ b/test/spec/crud/unified/updateMany-hint-serverError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: updateMany-hint-serverError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/updateMany-hint-unacknowledged.json b/test/spec/crud/unified/updateMany-hint-unacknowledged.json new file mode 100644 index 0000000000..e83838aac2 --- /dev/null +++ b/test/spec/crud/unified/updateMany-hint-unacknowledged.json @@ -0,0 +1,281 @@ +{ + "description": "updateMany-hint-unacknowledged", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "db0" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + } + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "db0", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "Unacknowledged updateMany with hint string fails with client-side error on pre-4.2 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.0.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged updateMany with hint document fails with client-side error on pre-4.2 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.0.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged updateMany with hint string on 4.2+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.2.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + }, + "expectResult": { + "$$unsetOrMatches": { + "acknowledged": { + "$$unsetOrMatches": false + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "update": "coll0", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": true, + "upsert": { + "$$unsetOrMatches": false + }, + "hint": { + "$$type": [ + "string", + "object" + ] + } + } + ], + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + }, + { + "description": "Unacknowledged updateMany with hint document on 4.2+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.2.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "acknowledged": { + "$$unsetOrMatches": false + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "update": "coll0", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": true, + "upsert": { + "$$unsetOrMatches": false + }, + "hint": { + "$$type": [ + "string", + "object" + ] + } + } + ], + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/updateMany-hint-unacknowledged.yml b/test/spec/crud/unified/updateMany-hint-unacknowledged.yml new file mode 100644 index 0000000000..9f15297385 --- /dev/null +++ b/test/spec/crud/unified/updateMany-hint-unacknowledged.yml @@ -0,0 +1,96 @@ +description: updateMany-hint-unacknowledged + +schemaVersion: '1.0' + +createEntities: + - client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name db0 + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + collectionOptions: + writeConcern: { w: 0 } + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: &documents + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - description: "Unacknowledged updateMany with hint string fails with client-side error on pre-4.2 server" + runOnRequirements: + - maxServerVersion: "4.0.99" + operations: + - object: *collection0 + name: updateMany + arguments: + filter: &filter { _id: { $gt: 1 } } + update: &update { $inc: { x: 1 } } + hint: _id_ + expectError: + isClientError: true + expectEvents: &noEvents + - client: *client0 + events: [] + + - description: "Unacknowledged updateMany with hint document fails with client-side error on pre-4.2 server" + runOnRequirements: + - maxServerVersion: "4.0.99" + operations: + - object: *collection0 + name: updateMany + arguments: + filter: *filter + update: *update + hint: { _id: 1 } + expectError: + isClientError: true + expectEvents: *noEvents + + - description: "Unacknowledged updateMany with hint string on 4.2+ server" + runOnRequirements: + - minServerVersion: "4.2.0" + operations: + - object: *collection0 + name: updateMany + arguments: + filter: *filter + update: *update + hint: _id_ + expectResult: &unacknowledgedResult { $$unsetOrMatches: { acknowledged: { $$unsetOrMatches: false } } } + expectEvents: &events + - client: *client0 + events: + - commandStartedEvent: + command: + update: *collection0Name + updates: + - q: *filter + u: *update + multi: true + upsert: { $$unsetOrMatches: false } + hint: { $$type: [ string, object ]} + writeConcern: { w: 0 } + + - description: "Unacknowledged updateMany with hint document on 4.2+ server" + runOnRequirements: + - minServerVersion: "4.2.0" + operations: + - object: *collection0 + name: updateMany + arguments: + filter: *filter + update: *update + hint: { _id: 1 } + expectResult: *unacknowledgedResult + expectEvents: *events diff --git a/test/spec/crud/unified/updateMany-hint.yml b/test/spec/crud/unified/updateMany-hint.yml index 8b6c228f4d..e595030923 100644 --- a/test/spec/crud/unified/updateMany-hint.yml +++ b/test/spec/crud/unified/updateMany-hint.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: updateMany-hint schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/updateMany.json b/test/spec/crud/unified/updateMany.json new file mode 100644 index 0000000000..19b890592b --- /dev/null +++ b/test/spec/crud/unified/updateMany.json @@ -0,0 +1,236 @@ +{ + "description": "updateMany", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "2.6" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "UpdateMany when many documents match", + "operations": [ + { + "object": "collection0", + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + } + }, + "expectResult": { + "matchedCount": 2, + "modifiedCount": 2, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 23 + }, + { + "_id": 3, + "x": 34 + } + ] + } + ] + }, + { + "description": "UpdateMany when one document matches", + "operations": [ + { + "object": "collection0", + "name": "updateMany", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "UpdateMany when no documents match", + "operations": [ + { + "object": "collection0", + "name": "updateMany", + "arguments": { + "filter": { + "_id": 4 + }, + "update": { + "$inc": { + "x": 1 + } + } + }, + "expectResult": { + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "UpdateMany with upsert when no documents match", + "operations": [ + { + "object": "collection0", + "name": "updateMany", + "arguments": { + "filter": { + "_id": 4 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "upsert": true + }, + "expectResult": { + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 1, + "upsertedId": 4 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 1 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/updateMany.yml b/test/spec/crud/unified/updateMany.yml new file mode 100644 index 0000000000..98f29d45e8 --- /dev/null +++ b/test/spec/crud/unified/updateMany.yml @@ -0,0 +1,120 @@ +description: updateMany + +schemaVersion: '1.0' + +runOnRequirements: + - + minServerVersion: '2.6' + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - + description: 'UpdateMany when many documents match' + operations: + - + object: *collection0 + name: updateMany + arguments: + filter: { _id: { $gt: 1 } } + update: { $inc: { x: 1 } } + expectResult: + matchedCount: 2 + modifiedCount: 2 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 23 } + - { _id: 3, x: 34 } + - + description: 'UpdateMany when one document matches' + operations: + - + object: *collection0 + name: updateMany + arguments: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'UpdateMany when no documents match' + operations: + - + object: *collection0 + name: updateMany + arguments: + filter: { _id: 4 } + update: { $inc: { x: 1 } } + expectResult: + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'UpdateMany with upsert when no documents match' + operations: + - + object: *collection0 + name: updateMany + arguments: + filter: { _id: 4 } + update: { $inc: { x: 1 } } + upsert: true + expectResult: + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 1 + upsertedId: 4 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - { _id: 4, x: 1 } diff --git a/test/spec/crud/v1/write/updateOne-arrayFilters.json b/test/spec/crud/unified/updateOne-arrayFilters.json similarity index 53% rename from test/spec/crud/v1/write/updateOne-arrayFilters.json rename to test/spec/crud/unified/updateOne-arrayFilters.json index 087ed4b82f..be5d05b01e 100644 --- a/test/spec/crud/v1/write/updateOne-arrayFilters.json +++ b/test/spec/crud/unified/updateOne-arrayFilters.json @@ -1,72 +1,110 @@ { - "data": [ + "description": "updateOne-arrayFilters", + "schemaVersion": "1.0", + "runOnRequirements": [ { - "_id": 1, - "y": [ - { - "b": 3 - }, - { - "b": 1 - } - ] + "minServerVersion": "3.5.6" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } }, { - "_id": 2, - "y": [ - { - "b": 0 - }, - { - "b": 1 - } - ] + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } }, { - "_id": 3, - "y": [ + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ { - "b": 5, - "c": [ + "_id": 1, + "y": [ { - "d": 2 + "b": 3 }, { - "d": 1 + "b": 1 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + }, + { + "_id": 3, + "y": [ + { + "b": 5, + "c": [ + { + "d": 2 + }, + { + "d": 1 + } + ] } ] } ] } ], - "minServerVersion": "3.5.6", "tests": [ { "description": "UpdateOne when no document matches arrayFilters", - "operation": { - "name": "updateOne", - "arguments": { - "filter": {}, - "update": { - "$set": { - "y.$[i].b": 2 - } + "operations": [ + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 4 + } + ] }, - "arrayFilters": [ - { - "i.b": 4 - } - ] + "expectResult": { + "matchedCount": 1, + "modifiedCount": 0, + "upsertedCount": 0 + } } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 0, - "upsertedCount": 0 - }, - "collection": { - "data": [ + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ { "_id": 1, "y": [ @@ -107,34 +145,39 @@ } ] } - } + ] }, { "description": "UpdateOne when one document matches arrayFilters", - "operation": { - "name": "updateOne", - "arguments": { - "filter": {}, - "update": { - "$set": { - "y.$[i].b": 2 - } + "operations": [ + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 3 + } + ] }, - "arrayFilters": [ - { - "i.b": 3 - } - ] + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0 - }, - "collection": { - "data": [ + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ { "_id": 1, "y": [ @@ -175,34 +218,39 @@ } ] } - } + ] }, { "description": "UpdateOne when multiple documents match arrayFilters", - "operation": { - "name": "updateOne", - "arguments": { - "filter": {}, - "update": { - "$set": { - "y.$[i].b": 2 - } + "operations": [ + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 1 + } + ] }, - "arrayFilters": [ - { - "i.b": 1 - } - ] + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0 - }, - "collection": { - "data": [ + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ { "_id": 1, "y": [ @@ -243,39 +291,44 @@ } ] } - } + ] }, { "description": "UpdateOne when no documents match multiple arrayFilters", - "operation": { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 3 - }, - "update": { - "$set": { - "y.$[i].c.$[j].d": 0 - } - }, - "arrayFilters": [ - { - "i.b": 5 + "operations": [ + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": 3 }, - { - "j.d": 3 - } - ] + "update": { + "$set": { + "y.$[i].c.$[j].d": 0 + } + }, + "arrayFilters": [ + { + "i.b": 5 + }, + { + "j.d": 3 + } + ] + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 0, + "upsertedCount": 0 + } } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 0, - "upsertedCount": 0 - }, - "collection": { - "data": [ + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ { "_id": 1, "y": [ @@ -316,39 +369,44 @@ } ] } - } + ] }, { "description": "UpdateOne when one document matches multiple arrayFilters", - "operation": { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 3 - }, - "update": { - "$set": { - "y.$[i].c.$[j].d": 0 - } - }, - "arrayFilters": [ - { - "i.b": 5 + "operations": [ + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": 3 }, - { - "j.d": 1 - } - ] + "update": { + "$set": { + "y.$[i].c.$[j].d": 0 + } + }, + "arrayFilters": [ + { + "i.b": 5 + }, + { + "j.d": 1 + } + ] + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0 - }, - "collection": { - "data": [ + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ { "_id": 1, "y": [ @@ -389,7 +447,7 @@ } ] } - } + ] } ] } diff --git a/test/spec/crud/unified/updateOne-arrayFilters.yml b/test/spec/crud/unified/updateOne-arrayFilters.yml new file mode 100644 index 0000000000..8d5b238bef --- /dev/null +++ b/test/spec/crud/unified/updateOne-arrayFilters.yml @@ -0,0 +1,150 @@ +description: updateOne-arrayFilters + +schemaVersion: '1.0' + +runOnRequirements: + - + minServerVersion: 3.5.6 + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, y: [ { b: 3 }, { b: 1 } ] } + - { _id: 2, y: [ { b: 0 }, { b: 1 } ] } + - { _id: 3, y: [ { b: 5, c: [ { d: 2 }, { d: 1 } ] } ] } + +tests: + - + description: 'UpdateOne when no document matches arrayFilters' + operations: + - + object: *collection0 + name: updateOne + arguments: + filter: { } + update: { $set: { 'y.$[i].b': 2 } } + arrayFilters: + - { i.b: 4 } + expectResult: + matchedCount: 1 + modifiedCount: 0 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, y: [ { b: 3 }, { b: 1 } ] } + - { _id: 2, y: [ { b: 0 }, { b: 1 } ] } + - { _id: 3, y: [ { b: 5, c: [ { d: 2 }, { d: 1 } ] } ] } + - + description: 'UpdateOne when one document matches arrayFilters' + operations: + - + object: *collection0 + name: updateOne + arguments: + filter: { } + update: { $set: { 'y.$[i].b': 2 } } + arrayFilters: + - { i.b: 3 } + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, y: [ { b: 2 }, { b: 1 } ] } + - { _id: 2, y: [ { b: 0 }, { b: 1 } ] } + - { _id: 3, y: [ { b: 5, c: [ { d: 2 }, { d: 1 } ] } ] } + - + description: 'UpdateOne when multiple documents match arrayFilters' + operations: + - + object: *collection0 + name: updateOne + arguments: + filter: { } + update: { $set: { 'y.$[i].b': 2 } } + arrayFilters: + - { i.b: 1 } + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, y: [ { b: 3 }, { b: 2 } ] } + - { _id: 2, y: [ { b: 0 }, { b: 1 } ] } + - { _id: 3, y: [ { b: 5, c: [ { d: 2 }, { d: 1 } ] } ] } + - + description: 'UpdateOne when no documents match multiple arrayFilters' + operations: + - + object: *collection0 + name: updateOne + arguments: + filter: { _id: 3 } + update: { $set: { 'y.$[i].c.$[j].d': 0 } } + arrayFilters: + - { i.b: 5 } + - { j.d: 3 } + expectResult: + matchedCount: 1 + modifiedCount: 0 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, y: [ { b: 3 }, { b: 1 } ] } + - { _id: 2, y: [ { b: 0 }, { b: 1 } ] } + - { _id: 3, y: [ { b: 5, c: [ { d: 2 }, { d: 1 } ] } ] } + - + description: 'UpdateOne when one document matches multiple arrayFilters' + operations: + - + object: *collection0 + name: updateOne + arguments: + filter: { _id: 3 } + update: { $set: { 'y.$[i].c.$[j].d': 0 } } + arrayFilters: + - { i.b: 5 } + - { j.d: 1 } + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, y: [ { b: 3 }, { b: 1 } ] } + - { _id: 2, y: [ { b: 0 }, { b: 1 } ] } + - { _id: 3, y: [ { b: 5, c: [ { d: 2 }, { d: 0 } ] } ] } diff --git a/test/spec/crud/unified/updateOne-collation.json b/test/spec/crud/unified/updateOne-collation.json new file mode 100644 index 0000000000..a39be46054 --- /dev/null +++ b/test/spec/crud/unified/updateOne-collation.json @@ -0,0 +1,93 @@ +{ + "description": "updateOne-collation", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "3.4", + "serverless": "forbid" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": "ping" + } + ] + } + ], + "tests": [ + { + "description": "UpdateOne when one document matches with collation", + "operations": [ + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "x": "PING" + }, + "update": { + "$set": { + "x": "pong" + } + }, + "collation": { + "locale": "en_US", + "strength": 2 + } + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": "pong" + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/updateOne-collation.yml b/test/spec/crud/unified/updateOne-collation.yml new file mode 100644 index 0000000000..85c2b55295 --- /dev/null +++ b/test/spec/crud/unified/updateOne-collation.yml @@ -0,0 +1,57 @@ +description: updateOne-collation + +schemaVersion: '1.4' + +runOnRequirements: + - + minServerVersion: '3.4' + serverless: forbid + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: ping } + +tests: + - + description: 'UpdateOne when one document matches with collation' + operations: + - + object: *collection0 + name: updateOne + arguments: + filter: { x: PING } + update: { $set: { x: pong } } + # https://www.mongodb.com/docs/manual/reference/collation/#collation-document + collation: + locale: en_US + strength: 2 + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: pong } diff --git a/test/spec/crud/unified/updateOne-comment.json b/test/spec/crud/unified/updateOne-comment.json index c18f59cfb9..f4ee74db38 100644 --- a/test/spec/crud/unified/updateOne-comment.json +++ b/test/spec/crud/unified/updateOne-comment.json @@ -186,6 +186,7 @@ "description": "UpdateOne with comment - pre 4.4", "runOnRequirements": [ { + "minServerVersion": "3.4.0", "maxServerVersion": "4.2.99" } ], diff --git a/test/spec/crud/unified/updateOne-comment.yml b/test/spec/crud/unified/updateOne-comment.yml index c8f56389d2..a176d620eb 100644 --- a/test/spec/crud/unified/updateOne-comment.yml +++ b/test/spec/crud/unified/updateOne-comment.yml @@ -77,7 +77,8 @@ tests: - description: "UpdateOne with comment - pre 4.4" runOnRequirements: - - maxServerVersion: "4.2.99" + - minServerVersion: "3.4.0" + maxServerVersion: "4.2.99" operations: - name: updateOne object: *collection0 diff --git a/test/spec/crud/unified/updateOne-hint-clientError.yml b/test/spec/crud/unified/updateOne-hint-clientError.yml index 87b4444c3a..5107b5f4b5 100644 --- a/test/spec/crud/unified/updateOne-hint-clientError.yml +++ b/test/spec/crud/unified/updateOne-hint-clientError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: updateOne-hint-clientError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/updateOne-hint-serverError.yml b/test/spec/crud/unified/updateOne-hint-serverError.yml index 0b804d05a7..f9681ab825 100644 --- a/test/spec/crud/unified/updateOne-hint-serverError.yml +++ b/test/spec/crud/unified/updateOne-hint-serverError.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: updateOne-hint-serverError schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/updateOne-hint-unacknowledged.json b/test/spec/crud/unified/updateOne-hint-unacknowledged.json new file mode 100644 index 0000000000..859b0f92f9 --- /dev/null +++ b/test/spec/crud/unified/updateOne-hint-unacknowledged.json @@ -0,0 +1,281 @@ +{ + "description": "updateOne-hint-unacknowledged", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "db0" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + } + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "db0", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "Unacknowledged updateOne with hint string fails with client-side error on pre-4.2 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.0.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged updateOne with hint document fails with client-side error on pre-4.2 server", + "runOnRequirements": [ + { + "maxServerVersion": "4.0.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ] + }, + { + "description": "Unacknowledged updateOne with hint string on 4.2+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.2.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + }, + "expectResult": { + "$$unsetOrMatches": { + "acknowledged": { + "$$unsetOrMatches": false + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "update": "coll0", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": { + "$$unsetOrMatches": false + }, + "upsert": { + "$$unsetOrMatches": false + }, + "hint": { + "$$type": [ + "string", + "object" + ] + } + } + ], + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + }, + { + "description": "Unacknowledged updateOne with hint document on 4.2+ server", + "runOnRequirements": [ + { + "minServerVersion": "4.2.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "acknowledged": { + "$$unsetOrMatches": false + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "update": "coll0", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": { + "$$unsetOrMatches": false + }, + "upsert": { + "$$unsetOrMatches": false + }, + "hint": { + "$$type": [ + "string", + "object" + ] + } + } + ], + "writeConcern": { + "w": 0 + } + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/updateOne-hint-unacknowledged.yml b/test/spec/crud/unified/updateOne-hint-unacknowledged.yml new file mode 100644 index 0000000000..77802db001 --- /dev/null +++ b/test/spec/crud/unified/updateOne-hint-unacknowledged.yml @@ -0,0 +1,95 @@ +description: updateOne-hint-unacknowledged + +schemaVersion: '1.0' + +createEntities: + - client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name db0 + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + collectionOptions: + writeConcern: { w: 0 } + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: &documents + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - description: "Unacknowledged updateOne with hint string fails with client-side error on pre-4.2 server" + runOnRequirements: + - maxServerVersion: "4.0.99" + operations: + - object: *collection0 + name: updateOne + arguments: + filter: &filter { _id: { $gt: 1 } } + update: &update { $inc: { x: 1 } } + hint: _id_ + expectError: + isClientError: true + expectEvents: &noEvents + - client: *client0 + events: [] + + - description: "Unacknowledged updateOne with hint document fails with client-side error on pre-4.2 server" + runOnRequirements: + - maxServerVersion: "4.0.99" + operations: + - object: *collection0 + name: updateOne + arguments: + filter: *filter + update: *update + hint: { _id: 1 } + expectError: + isClientError: true + expectEvents: *noEvents + + - description: "Unacknowledged updateOne with hint string on 4.2+ server" + runOnRequirements: + - minServerVersion: "4.2.0" + operations: + - object: *collection0 + name: updateOne + arguments: + filter: *filter + update: *update + hint: _id_ + expectResult: &unacknowledgedResult { $$unsetOrMatches: { acknowledged: { $$unsetOrMatches: false } } } + expectEvents: &events + - client: *client0 + events: + - commandStartedEvent: + command: + update: *collection0Name + updates: + - q: *filter + u: *update + multi: { $$unsetOrMatches: false } + upsert: { $$unsetOrMatches: false } + hint: { $$type: [ string, object ]} + writeConcern: { w: 0 } + + - description: "Unacknowledged updateOne with hint document on 4.2+ server" + runOnRequirements: + - minServerVersion: "4.2.0" + operations: + - object: *collection0 + name: updateOne + arguments: + filter: *filter + update: *update + hint: { _id: 1 } + expectResult: *unacknowledgedResult + expectEvents: *events diff --git a/test/spec/crud/unified/updateOne-hint.yml b/test/spec/crud/unified/updateOne-hint.yml index 8f5d1460a2..bd60cd7a19 100644 --- a/test/spec/crud/unified/updateOne-hint.yml +++ b/test/spec/crud/unified/updateOne-hint.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: updateOne-hint schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/unified/updateOne.json b/test/spec/crud/unified/updateOne.json new file mode 100644 index 0000000000..a3f559673e --- /dev/null +++ b/test/spec/crud/unified/updateOne.json @@ -0,0 +1,216 @@ +{ + "description": "updateOne", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "2.6" + } + ], + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-v1" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "UpdateOne when many documents match", + "operations": [ + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + } + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ] + }, + { + "description": "UpdateOne when one document matches", + "operations": [ + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "UpdateOne when no documents match", + "operations": [ + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": 4 + }, + "update": { + "$inc": { + "x": 1 + } + } + }, + "expectResult": { + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "UpdateOne with upsert when no documents match", + "operations": [ + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": 4 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "upsert": true + }, + "expectResult": { + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 1, + "upsertedId": 4 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "crud-v1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 1 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/updateOne.yml b/test/spec/crud/unified/updateOne.yml new file mode 100644 index 0000000000..2f8f6a9181 --- /dev/null +++ b/test/spec/crud/unified/updateOne.yml @@ -0,0 +1,114 @@ +description: updateOne + +schemaVersion: '1.0' + +runOnRequirements: + - + minServerVersion: '2.6' + +createEntities: + - + client: + id: &client0 client0 + - + database: + id: &database0 database0 + client: client0 + databaseName: &database_name crud-v1 + - + collection: + id: &collection0 collection0 + database: database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - + # This test doesn't verify the output collection because we cannot assume + # which document gets updated. + description: 'UpdateOne when many documents match' + operations: + - + object: *collection0 + name: updateOne + arguments: + filter: { _id: { $gt: 1 } } + update: { $inc: { x: 1 } } + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + - + description: 'UpdateOne when one document matches' + operations: + - + object: *collection0 + name: updateOne + arguments: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'UpdateOne when no documents match' + operations: + - + object: *collection0 + name: updateOne + arguments: + filter: { _id: 4 } + update: { $inc: { x: 1 } } + expectResult: + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'UpdateOne with upsert when no documents match' + operations: + - + object: *collection0 + name: updateOne + arguments: + filter: { _id: 4 } + update: { $inc: { x: 1 } } + upsert: true + expectResult: + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 1 + upsertedId: 4 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - { _id: 4, x: 1 } diff --git a/test/spec/crud/unified/updateWithPipelines.yml b/test/spec/crud/unified/updateWithPipelines.yml index 30666e31dd..e0b580c0ef 100644 --- a/test/spec/crud/unified/updateWithPipelines.yml +++ b/test/spec/crud/unified/updateWithPipelines.yml @@ -1,6 +1,3 @@ -# This file was created automatically using mongodb-spec-converter. -# Please review the generated file, then remove this notice. - description: updateWithPipelines schemaVersion: '1.0' runOnRequirements: diff --git a/test/spec/crud/v1/read/aggregate-collation.json b/test/spec/crud/v1/read/aggregate-collation.json deleted file mode 100644 index d958e447bf..0000000000 --- a/test/spec/crud/v1/read/aggregate-collation.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": "ping" - } - ], - "minServerVersion": "3.4", - "serverless": "forbid", - "tests": [ - { - "description": "Aggregate with collation", - "operation": { - "name": "aggregate", - "arguments": { - "pipeline": [ - { - "$match": { - "x": "PING" - } - } - ], - "collation": { - "locale": "en_US", - "strength": 2 - } - } - }, - "outcome": { - "result": [ - { - "_id": 1, - "x": "ping" - } - ] - } - } - ] -} diff --git a/test/spec/crud/v1/read/aggregate-collation.yml b/test/spec/crud/v1/read/aggregate-collation.yml deleted file mode 100644 index 924192a6e5..0000000000 --- a/test/spec/crud/v1/read/aggregate-collation.yml +++ /dev/null @@ -1,18 +0,0 @@ -data: - - {_id: 1, x: 'ping'} -minServerVersion: '3.4' -serverless: 'forbid' - -tests: - - - description: "Aggregate with collation" - operation: - name: aggregate - arguments: - pipeline: - - $match: - x: 'PING' - collation: { locale: 'en_US', strength: 2 } # https://www.mongodb.com/docs/manual/reference/collation/#collation-document - outcome: - result: - - {_id: 1, x: 'ping'} diff --git a/test/spec/crud/v1/read/aggregate-out.json b/test/spec/crud/v1/read/aggregate-out.json deleted file mode 100644 index c195e163e0..0000000000 --- a/test/spec/crud/v1/read/aggregate-out.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "minServerVersion": "2.6", - "serverless": "forbid", - "tests": [ - { - "description": "Aggregate with $out", - "operation": { - "name": "aggregate", - "arguments": { - "pipeline": [ - { - "$sort": { - "x": 1 - } - }, - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$out": "other_test_collection" - } - ], - "batchSize": 2 - } - }, - "outcome": { - "collection": { - "name": "other_test_collection", - "data": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "Aggregate with $out and batch size of 0", - "operation": { - "name": "aggregate", - "arguments": { - "pipeline": [ - { - "$sort": { - "x": 1 - } - }, - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$out": "other_test_collection" - } - ], - "batchSize": 0 - } - }, - "outcome": { - "collection": { - "name": "other_test_collection", - "data": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/read/aggregate-out.yml b/test/spec/crud/v1/read/aggregate-out.yml deleted file mode 100644 index d6688dd08d..0000000000 --- a/test/spec/crud/v1/read/aggregate-out.yml +++ /dev/null @@ -1,44 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} -minServerVersion: '2.6' -serverless: 'forbid' - -tests: - - - description: "Aggregate with $out" - operation: - name: aggregate - arguments: - pipeline: - - $sort: {x: 1} - - $match: - _id: {$gt: 1} - - $out: "other_test_collection" - batchSize: 2 - - outcome: - collection: - name: "other_test_collection" - data: - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - - description: "Aggregate with $out and batch size of 0" - operation: - name: aggregate - arguments: - pipeline: - - $sort: {x: 1} - - $match: - _id: {$gt: 1} - - $out: "other_test_collection" - batchSize: 0 - - outcome: - collection: - name: "other_test_collection" - data: - - {_id: 2, x: 22} - - {_id: 3, x: 33} diff --git a/test/spec/crud/v1/read/aggregate.json b/test/spec/crud/v1/read/aggregate.json deleted file mode 100644 index 797a922395..0000000000 --- a/test/spec/crud/v1/read/aggregate.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "tests": [ - { - "description": "Aggregate with multiple stages", - "operation": { - "name": "aggregate", - "arguments": { - "pipeline": [ - { - "$sort": { - "x": 1 - } - }, - { - "$match": { - "_id": { - "$gt": 1 - } - } - } - ], - "batchSize": 2 - } - }, - "outcome": { - "result": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - ] -} diff --git a/test/spec/crud/v1/read/aggregate.yml b/test/spec/crud/v1/read/aggregate.yml deleted file mode 100644 index 98b69445c2..0000000000 --- a/test/spec/crud/v1/read/aggregate.yml +++ /dev/null @@ -1,21 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - -tests: - - - description: "Aggregate with multiple stages" - operation: - name: aggregate - arguments: - pipeline: - - $sort: {x: 1} - - $match: - _id: {$gt: 1} - batchSize: 2 - - outcome: - result: - - {_id: 2, x: 22} - - {_id: 3, x: 33} diff --git a/test/spec/crud/v1/read/count-collation.json b/test/spec/crud/v1/read/count-collation.json deleted file mode 100644 index 7d61508493..0000000000 --- a/test/spec/crud/v1/read/count-collation.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": "PING" - } - ], - "minServerVersion": "3.4", - "serverless": "forbid", - "tests": [ - { - "description": "Count documents with collation", - "operation": { - "name": "countDocuments", - "arguments": { - "filter": { - "x": "ping" - }, - "collation": { - "locale": "en_US", - "strength": 2 - } - } - }, - "outcome": { - "result": 1 - } - }, - { - "description": "Deprecated count with collation", - "operation": { - "name": "count", - "arguments": { - "filter": { - "x": "ping" - }, - "collation": { - "locale": "en_US", - "strength": 2 - } - } - }, - "outcome": { - "result": 1 - } - } - ] -} diff --git a/test/spec/crud/v1/read/count-collation.yml b/test/spec/crud/v1/read/count-collation.yml deleted file mode 100644 index fd1c29a07e..0000000000 --- a/test/spec/crud/v1/read/count-collation.yml +++ /dev/null @@ -1,26 +0,0 @@ -data: - - {_id: 1, x: 'PING'} -minServerVersion: '3.4' -serverless: 'forbid' - -tests: - - - description: "Count documents with collation" - operation: - name: countDocuments - arguments: - filter: { x: 'ping' } - collation: { locale: 'en_US', strength: 2 } # https://www.mongodb.com/docs/manual/reference/collation/#collation-document - - outcome: - result: 1 - - - description: "Deprecated count with collation" - operation: - name: count - arguments: - filter: { x: 'ping' } - collation: { locale: 'en_US', strength: 2 } - - outcome: - result: 1 diff --git a/test/spec/crud/v1/read/count-empty.json b/test/spec/crud/v1/read/count-empty.json deleted file mode 100644 index 2b8627e0c6..0000000000 --- a/test/spec/crud/v1/read/count-empty.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "data": [], - "tests": [ - { - "description": "Estimated document count with empty collection", - "operation": { - "name": "estimatedDocumentCount", - "arguments": {} - }, - "outcome": { - "result": 0 - } - }, - { - "description": "Count documents with empty collection", - "operation": { - "name": "countDocuments", - "arguments": { - "filter": {} - } - }, - "outcome": { - "result": 0 - } - }, - { - "description": "Deprecated count with empty collection", - "operation": { - "name": "count", - "arguments": { - "filter": {} - } - }, - "outcome": { - "result": 0 - } - } - ] -} diff --git a/test/spec/crud/v1/read/count-empty.yml b/test/spec/crud/v1/read/count-empty.yml deleted file mode 100644 index 83098ec18f..0000000000 --- a/test/spec/crud/v1/read/count-empty.yml +++ /dev/null @@ -1,29 +0,0 @@ -data: [] - -tests: - - - description: "Estimated document count with empty collection" - operation: - name: estimatedDocumentCount - arguments: { } - - outcome: - result: 0 - - - description: "Count documents with empty collection" - operation: - name: countDocuments - arguments: - filter: { } - - outcome: - result: 0 - - - description: "Deprecated count with empty collection" - operation: - name: count - arguments: - filter: { } - - outcome: - result: 0 diff --git a/test/spec/crud/v1/read/count.json b/test/spec/crud/v1/read/count.json deleted file mode 100644 index 9642b2fbd0..0000000000 --- a/test/spec/crud/v1/read/count.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "tests": [ - { - "description": "Estimated document count", - "operation": { - "name": "estimatedDocumentCount", - "arguments": {} - }, - "outcome": { - "result": 3 - } - }, - { - "description": "Count documents without a filter", - "operation": { - "name": "countDocuments", - "arguments": { - "filter": {} - } - }, - "outcome": { - "result": 3 - } - }, - { - "description": "Count documents with a filter", - "operation": { - "name": "countDocuments", - "arguments": { - "filter": { - "_id": { - "$gt": 1 - } - } - } - }, - "outcome": { - "result": 2 - } - }, - { - "description": "Count documents with skip and limit", - "operation": { - "name": "countDocuments", - "arguments": { - "filter": {}, - "skip": 1, - "limit": 3 - } - }, - "outcome": { - "result": 2 - } - }, - { - "description": "Deprecated count without a filter", - "operation": { - "name": "count", - "arguments": { - "filter": {} - } - }, - "outcome": { - "result": 3 - } - }, - { - "description": "Deprecated count with a filter", - "operation": { - "name": "count", - "arguments": { - "filter": { - "_id": { - "$gt": 1 - } - } - } - }, - "outcome": { - "result": 2 - } - }, - { - "description": "Deprecated count with skip and limit", - "operation": { - "name": "count", - "arguments": { - "filter": {}, - "skip": 1, - "limit": 3 - } - }, - "outcome": { - "result": 2 - } - } - ] -} diff --git a/test/spec/crud/v1/read/count.yml b/test/spec/crud/v1/read/count.yml deleted file mode 100644 index 33d380b7d5..0000000000 --- a/test/spec/crud/v1/read/count.yml +++ /dev/null @@ -1,74 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - -tests: - - - description: "Estimated document count" - operation: - name: estimatedDocumentCount - arguments: { } - - outcome: - result: 3 - - - description: "Count documents without a filter" - operation: - name: countDocuments - arguments: - filter: { } - - outcome: - result: 3 - - - description: "Count documents with a filter" - operation: - name: countDocuments - arguments: - filter: - _id: {$gt: 1} - - outcome: - result: 2 - - - description: "Count documents with skip and limit" - operation: - name: countDocuments - arguments: - filter: {} - skip: 1 - limit: 3 - - outcome: - result: 2 - - - description: "Deprecated count without a filter" - operation: - name: count - arguments: - filter: { } - - outcome: - result: 3 - - - description: "Deprecated count with a filter" - operation: - name: count - arguments: - filter: - _id: {$gt: 1} - - outcome: - result: 2 - - - description: "Deprecated count with skip and limit" - operation: - name: count - arguments: - filter: {} - skip: 1 - limit: 3 - - outcome: - result: 2 diff --git a/test/spec/crud/v1/read/distinct-collation.json b/test/spec/crud/v1/read/distinct-collation.json deleted file mode 100644 index 984991a43b..0000000000 --- a/test/spec/crud/v1/read/distinct-collation.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "string": "PING" - }, - { - "_id": 2, - "string": "ping" - } - ], - "minServerVersion": "3.4", - "serverless": "forbid", - "tests": [ - { - "description": "Distinct with a collation", - "operation": { - "name": "distinct", - "arguments": { - "fieldName": "string", - "collation": { - "locale": "en_US", - "strength": 2 - } - } - }, - "outcome": { - "result": [ - "PING" - ] - } - } - ] -} diff --git a/test/spec/crud/v1/read/distinct-collation.yml b/test/spec/crud/v1/read/distinct-collation.yml deleted file mode 100644 index 8785f29d4b..0000000000 --- a/test/spec/crud/v1/read/distinct-collation.yml +++ /dev/null @@ -1,18 +0,0 @@ -data: - - {_id: 1, string: 'PING'} - - {_id: 2, string: 'ping'} -minServerVersion: '3.4' -serverless: 'forbid' - -tests: - - - description: "Distinct with a collation" - operation: - name: distinct - arguments: - fieldName: "string" - collation: { locale: 'en_US', strength: 2 } # https://www.mongodb.com/docs/manual/reference/collation/#collation-document - - outcome: - result: - - 'PING' diff --git a/test/spec/crud/v1/read/distinct.json b/test/spec/crud/v1/read/distinct.json deleted file mode 100644 index a57ee36a83..0000000000 --- a/test/spec/crud/v1/read/distinct.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "tests": [ - { - "description": "Distinct without a filter", - "operation": { - "name": "distinct", - "arguments": { - "fieldName": "x", - "filter": {} - } - }, - "outcome": { - "result": [ - 11, - 22, - 33 - ] - } - }, - { - "description": "Distinct with a filter", - "operation": { - "name": "distinct", - "arguments": { - "fieldName": "x", - "filter": { - "_id": { - "$gt": 1 - } - } - } - }, - "outcome": { - "result": [ - 22, - 33 - ] - } - } - ] -} diff --git a/test/spec/crud/v1/read/distinct.yml b/test/spec/crud/v1/read/distinct.yml deleted file mode 100644 index aefc7e0fdf..0000000000 --- a/test/spec/crud/v1/read/distinct.yml +++ /dev/null @@ -1,32 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - -tests: - - - description: "Distinct without a filter" - operation: - name: distinct - arguments: - fieldName: "x" - filter: {} - - outcome: - result: - - 11 - - 22 - - 33 - - - description: "Distinct with a filter" - operation: - name: distinct - arguments: - fieldName: "x" - filter: - _id: {$gt: 1} - - outcome: - result: - - 22 - - 33 \ No newline at end of file diff --git a/test/spec/crud/v1/read/find-collation.json b/test/spec/crud/v1/read/find-collation.json deleted file mode 100644 index 4e56c05253..0000000000 --- a/test/spec/crud/v1/read/find-collation.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": "ping" - } - ], - "minServerVersion": "3.4", - "serverless": "forbid", - "tests": [ - { - "description": "Find with a collation", - "operation": { - "name": "find", - "arguments": { - "filter": { - "x": "PING" - }, - "collation": { - "locale": "en_US", - "strength": 2 - } - } - }, - "outcome": { - "result": [ - { - "_id": 1, - "x": "ping" - } - ] - } - } - ] -} diff --git a/test/spec/crud/v1/read/find-collation.yml b/test/spec/crud/v1/read/find-collation.yml deleted file mode 100644 index 1ecc491546..0000000000 --- a/test/spec/crud/v1/read/find-collation.yml +++ /dev/null @@ -1,16 +0,0 @@ -data: - - {_id: 1, x: 'ping'} -minServerVersion: '3.4' -serverless: 'forbid' - -tests: - - - description: "Find with a collation" - operation: - name: "find" - arguments: - filter: {x: 'PING'} - collation: { locale: 'en_US', strength: 2 } # https://www.mongodb.com/docs/manual/reference/collation/#collation-document - outcome: - result: - - {_id: 1, x: 'ping'} diff --git a/test/spec/crud/v1/read/find.json b/test/spec/crud/v1/read/find.json deleted file mode 100644 index 3597e37be6..0000000000 --- a/test/spec/crud/v1/read/find.json +++ /dev/null @@ -1,105 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - }, - { - "_id": 5, - "x": 55 - } - ], - "tests": [ - { - "description": "Find with filter", - "operation": { - "name": "find", - "arguments": { - "filter": { - "_id": 1 - } - } - }, - "outcome": { - "result": [ - { - "_id": 1, - "x": 11 - } - ] - } - }, - { - "description": "Find with filter, sort, skip, and limit", - "operation": { - "name": "find", - "arguments": { - "filter": { - "_id": { - "$gt": 2 - } - }, - "sort": { - "_id": 1 - }, - "skip": 2, - "limit": 2 - } - }, - "outcome": { - "result": [ - { - "_id": 5, - "x": 55 - } - ] - } - }, - { - "description": "Find with limit, sort, and batchsize", - "operation": { - "name": "find", - "arguments": { - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4, - "batchSize": 2 - } - }, - "outcome": { - "result": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - } - ] -} diff --git a/test/spec/crud/v1/read/find.yml b/test/spec/crud/v1/read/find.yml deleted file mode 100644 index 25099df7f1..0000000000 --- a/test/spec/crud/v1/read/find.yml +++ /dev/null @@ -1,49 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - {_id: 4, x: 44} - - {_id: 5, x: 55} - -tests: - - - description: "Find with filter" - operation: - name: "find" - arguments: - filter: {_id: 1} - - outcome: - result: - - {_id: 1, x: 11} - - - - description: "Find with filter, sort, skip, and limit" - operation: - name: "find" - arguments: - filter: - _id: {$gt: 2} - sort: {_id: 1} - skip: 2 - limit: 2 - - outcome: - result: - - {_id: 5, x: 55} - - - description: "Find with limit, sort, and batchsize" - operation: - name: "find" - arguments: - filter: {} - sort: {_id: 1} - limit: 4 - batchSize: 2 - - outcome: - result: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - {_id: 4, x: 44} diff --git a/test/spec/crud/v1/write/bulkWrite-arrayFilters.json b/test/spec/crud/v1/write/bulkWrite-arrayFilters.json deleted file mode 100644 index 99e73f5d75..0000000000 --- a/test/spec/crud/v1/write/bulkWrite-arrayFilters.json +++ /dev/null @@ -1,111 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "y": [ - { - "b": 3 - }, - { - "b": 1 - } - ] - }, - { - "_id": 2, - "y": [ - { - "b": 0 - }, - { - "b": 1 - } - ] - } - ], - "minServerVersion": "3.5.6", - "tests": [ - { - "description": "BulkWrite with arrayFilters", - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "updateOne", - "arguments": { - "filter": {}, - "update": { - "$set": { - "y.$[i].b": 2 - } - }, - "arrayFilters": [ - { - "i.b": 3 - } - ] - } - }, - { - "name": "updateMany", - "arguments": { - "filter": {}, - "update": { - "$set": { - "y.$[i].b": 2 - } - }, - "arrayFilters": [ - { - "i.b": 1 - } - ] - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "deletedCount": 0, - "insertedCount": 0, - "insertedIds": {}, - "matchedCount": 3, - "modifiedCount": 3, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [ - { - "_id": 1, - "y": [ - { - "b": 2 - }, - { - "b": 2 - } - ] - }, - { - "_id": 2, - "y": [ - { - "b": 0 - }, - { - "b": 2 - } - ] - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/bulkWrite-arrayFilters.yml b/test/spec/crud/v1/write/bulkWrite-arrayFilters.yml deleted file mode 100644 index 1089f08c09..0000000000 --- a/test/spec/crud/v1/write/bulkWrite-arrayFilters.yml +++ /dev/null @@ -1,45 +0,0 @@ -data: - - {_id: 1, y: [{b: 3}, {b: 1}]} - - {_id: 2, y: [{b: 0}, {b: 1}]} - -minServerVersion: '3.5.6' - -tests: - - - description: "BulkWrite with arrayFilters" - operation: - name: "bulkWrite" - arguments: - requests: - - - # UpdateOne when one document matches arrayFilters - name: "updateOne" - arguments: - filter: {} - update: - $set: {"y.$[i].b": 2} - arrayFilters: - - {i.b: 3} - - - # UpdateMany when multiple documents match arrayFilters - name: "updateMany" - arguments: - filter: {} - update: - $set: {"y.$[i].b": 2} - arrayFilters: - - {i.b: 1} - options: { ordered: true } - outcome: - result: - deletedCount: 0 - insertedCount: 0 - insertedIds: {} - matchedCount: 3 - modifiedCount: 3 - upsertedCount: 0 - upsertedIds: {} - collection: - data: - - {_id: 1, y: [{b: 2}, {b: 2}]} - - {_id: 2, y: [{b: 0}, {b: 2}]} diff --git a/test/spec/crud/v1/write/bulkWrite-collation.json b/test/spec/crud/v1/write/bulkWrite-collation.json deleted file mode 100644 index bc90aa8172..0000000000 --- a/test/spec/crud/v1/write/bulkWrite-collation.json +++ /dev/null @@ -1,218 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": "ping" - }, - { - "_id": 3, - "x": "pINg" - }, - { - "_id": 4, - "x": "pong" - }, - { - "_id": 5, - "x": "pONg" - } - ], - "minServerVersion": "3.4", - "serverless": "forbid", - "tests": [ - { - "description": "BulkWrite with delete operations and collation", - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "deleteOne", - "arguments": { - "filter": { - "x": "PING" - }, - "collation": { - "locale": "en_US", - "strength": 2 - } - } - }, - { - "name": "deleteOne", - "arguments": { - "filter": { - "x": "PING" - }, - "collation": { - "locale": "en_US", - "strength": 2 - } - } - }, - { - "name": "deleteMany", - "arguments": { - "filter": { - "x": "PONG" - }, - "collation": { - "locale": "en_US", - "strength": 2 - } - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "deletedCount": 4, - "insertedCount": 0, - "insertedIds": {}, - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - } - ] - } - } - }, - { - "description": "BulkWrite with update operations and collation", - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "updateMany", - "arguments": { - "filter": { - "x": "ping" - }, - "update": { - "$set": { - "x": "PONG" - } - }, - "collation": { - "locale": "en_US", - "strength": 3 - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "x": "ping" - }, - "update": { - "$set": { - "x": "PONG" - } - }, - "collation": { - "locale": "en_US", - "strength": 2 - } - } - }, - { - "name": "replaceOne", - "arguments": { - "filter": { - "x": "ping" - }, - "replacement": { - "_id": 6, - "x": "ping" - }, - "upsert": true, - "collation": { - "locale": "en_US", - "strength": 3 - } - } - }, - { - "name": "updateMany", - "arguments": { - "filter": { - "x": "pong" - }, - "update": { - "$set": { - "x": "PONG" - } - }, - "collation": { - "locale": "en_US", - "strength": 2 - } - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "deletedCount": 0, - "insertedCount": 0, - "insertedIds": {}, - "matchedCount": 6, - "modifiedCount": 4, - "upsertedCount": 1, - "upsertedIds": { - "2": 6 - } - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": "PONG" - }, - { - "_id": 3, - "x": "PONG" - }, - { - "_id": 4, - "x": "PONG" - }, - { - "_id": 5, - "x": "PONG" - }, - { - "_id": 6, - "x": "ping" - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/bulkWrite-collation.yml b/test/spec/crud/v1/write/bulkWrite-collation.yml deleted file mode 100644 index 75ab468a5e..0000000000 --- a/test/spec/crud/v1/write/bulkWrite-collation.yml +++ /dev/null @@ -1,102 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 'ping'} - - {_id: 3, x: 'pINg'} - - {_id: 4, x: 'pong'} - - {_id: 5, x: 'pONg'} - -minServerVersion: '3.4' -serverless: 'forbid' - -# See: https://www.mongodb.com/docs/manual/reference/collation/#collation-document -tests: - - - description: "BulkWrite with delete operations and collation" - operation: - name: "bulkWrite" - arguments: - requests: - - - # matches two documents but deletes one - name: "deleteOne" - arguments: - filter: { x: "PING" } - collation: { locale: "en_US", strength: 2 } - - - # matches the remaining document and deletes it - name: "deleteOne" - arguments: - filter: { x: "PING" } - collation: { locale: "en_US", strength: 2 } - - - # matches two documents and deletes them - name: "deleteMany" - arguments: - filter: { x: "PONG" } - collation: { locale: "en_US", strength: 2 } - options: { ordered: true } - outcome: - result: - deletedCount: 4 - insertedCount: 0 - insertedIds: {} - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 0 - upsertedIds: {} - collection: - data: - - {_id: 1, x: 11 } - - - description: "BulkWrite with update operations and collation" - operation: - name: "bulkWrite" - arguments: - requests: - - - # matches only one document due to strength and updates - name: "updateMany" - arguments: - filter: { x: "ping" } - update: { $set: { x: "PONG" } } - collation: { locale: "en_US", strength: 3 } - - - # matches one document and updates - name: "updateOne" - arguments: - filter: { x: "ping" } - update: { $set: { x: "PONG" } } - collation: { locale: "en_US", strength: 2 } - - - # matches no document due to strength and upserts - name: "replaceOne" - arguments: - filter: { x: "ping" } - replacement: { _id: 6, x: "ping" } - upsert: true - collation: { locale: "en_US", strength: 3 } - - - # matches two documents and updates - name: "updateMany" - arguments: - filter: { x: "pong" } - update: { $set: { x: "PONG" } } - collation: { locale: "en_US", strength: 2 } - options: { ordered: true } - outcome: - result: - deletedCount: 0 - insertedCount: 0 - insertedIds: {} - matchedCount: 6 - modifiedCount: 4 - upsertedCount: 1 - upsertedIds: { 2: 6 } - collection: - data: - - {_id: 1, x: 11 } - - {_id: 2, x: "PONG" } - - {_id: 3, x: "PONG" } - - {_id: 4, x: "PONG" } - - {_id: 5, x: "PONG" } - - {_id: 6, x: "ping" } diff --git a/test/spec/crud/v1/write/bulkWrite.json b/test/spec/crud/v1/write/bulkWrite.json deleted file mode 100644 index dc00da28ad..0000000000 --- a/test/spec/crud/v1/write/bulkWrite.json +++ /dev/null @@ -1,778 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "minServerVersion": "2.6", - "tests": [ - { - "description": "BulkWrite with deleteOne operations", - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 3 - } - } - }, - { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 2 - } - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "deletedCount": 1, - "insertedCount": 0, - "insertedIds": {}, - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - } - ] - } - } - }, - { - "description": "BulkWrite with deleteMany operations", - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "deleteMany", - "arguments": { - "filter": { - "x": { - "$lt": 11 - } - } - } - }, - { - "name": "deleteMany", - "arguments": { - "filter": { - "x": { - "$lte": 22 - } - } - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "deletedCount": 2, - "insertedCount": 0, - "insertedIds": {}, - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [] - } - } - }, - { - "description": "BulkWrite with insertOne operations", - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 4, - "x": 44 - } - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "deletedCount": 0, - "insertedCount": 2, - "insertedIds": { - "0": 3, - "1": 4 - }, - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - } - }, - { - "description": "BulkWrite with replaceOne operations", - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "replaceOne", - "arguments": { - "filter": { - "_id": 3 - }, - "replacement": { - "x": 33 - } - } - }, - { - "name": "replaceOne", - "arguments": { - "filter": { - "_id": 1 - }, - "replacement": { - "x": 12 - } - } - }, - { - "name": "replaceOne", - "arguments": { - "filter": { - "_id": 3 - }, - "replacement": { - "x": 33 - }, - "upsert": true - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "deletedCount": 0, - "insertedCount": 0, - "insertedIds": {}, - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 1, - "upsertedIds": { - "2": 3 - } - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 12 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "BulkWrite with updateOne operations", - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 0 - }, - "update": { - "$set": { - "x": 0 - } - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$set": { - "x": 11 - } - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 2 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 3 - }, - "update": { - "$set": { - "x": 33 - } - }, - "upsert": true - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "deletedCount": 0, - "insertedCount": 0, - "insertedIds": {}, - "matchedCount": 2, - "modifiedCount": 1, - "upsertedCount": 1, - "upsertedIds": { - "3": 3 - } - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 23 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "BulkWrite with updateMany operations", - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "updateMany", - "arguments": { - "filter": { - "x": { - "$lt": 11 - } - }, - "update": { - "$set": { - "x": 0 - } - } - } - }, - { - "name": "updateMany", - "arguments": { - "filter": { - "x": { - "$lte": 22 - } - }, - "update": { - "$unset": { - "y": 1 - } - } - } - }, - { - "name": "updateMany", - "arguments": { - "filter": { - "x": { - "$lte": 22 - } - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - { - "name": "updateMany", - "arguments": { - "filter": { - "_id": 3 - }, - "update": { - "$set": { - "x": 33 - } - }, - "upsert": true - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "deletedCount": 0, - "insertedCount": 0, - "insertedIds": {}, - "matchedCount": 4, - "modifiedCount": 2, - "upsertedCount": 1, - "upsertedIds": { - "3": 3 - } - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 12 - }, - { - "_id": 2, - "x": 23 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "BulkWrite with mixed ordered operations", - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 2 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - { - "name": "updateMany", - "arguments": { - "filter": { - "_id": { - "$gt": 1 - } - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 4, - "x": 44 - } - } - }, - { - "name": "deleteMany", - "arguments": { - "filter": { - "x": { - "$nin": [ - 24, - 34 - ] - } - } - } - }, - { - "name": "replaceOne", - "arguments": { - "filter": { - "_id": 4 - }, - "replacement": { - "_id": 4, - "x": 44 - }, - "upsert": true - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "deletedCount": 2, - "insertedCount": 2, - "insertedIds": { - "0": 3, - "3": 4 - }, - "matchedCount": 3, - "modifiedCount": 3, - "upsertedCount": 1, - "upsertedIds": { - "5": 4 - } - }, - "collection": { - "data": [ - { - "_id": 2, - "x": 24 - }, - { - "_id": 3, - "x": 34 - }, - { - "_id": 4, - "x": 44 - } - ] - } - } - }, - { - "description": "BulkWrite with mixed unordered operations", - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "replaceOne", - "arguments": { - "filter": { - "_id": 3 - }, - "replacement": { - "_id": 3, - "x": 33 - }, - "upsert": true - } - }, - { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 1 - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 2 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - } - ], - "options": { - "ordered": false - } - } - }, - "outcome": { - "result": { - "deletedCount": 1, - "insertedCount": 0, - "insertedIds": {}, - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 1, - "upsertedIds": { - "0": 3 - } - }, - "collection": { - "data": [ - { - "_id": 2, - "x": 23 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "BulkWrite continue-on-error behavior with unordered (preexisting duplicate key)", - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 2, - "x": 22 - } - } - }, - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 4, - "x": 44 - } - } - } - ], - "options": { - "ordered": false - } - } - }, - "outcome": { - "error": true, - "result": { - "deletedCount": 0, - "insertedCount": 2, - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - } - }, - { - "description": "BulkWrite continue-on-error behavior with unordered (duplicate key in requests)", - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 4, - "x": 44 - } - } - } - ], - "options": { - "ordered": false - } - } - }, - "outcome": { - "error": true, - "result": { - "deletedCount": 0, - "insertedCount": 2, - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/bulkWrite.yml b/test/spec/crud/v1/write/bulkWrite.yml deleted file mode 100644 index 988bdf4d45..0000000000 --- a/test/spec/crud/v1/write/bulkWrite.yml +++ /dev/null @@ -1,401 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - -minServerVersion: '2.6' - -tests: - - - description: "BulkWrite with deleteOne operations" - operation: - name: "bulkWrite" - arguments: - # Note: as in the "DeleteOne when many documents match" test in - # deleteOne.yml, we omit a deleteOne operation that might match - # multiple documents as that would hinder our ability to assert - # the final state of the collection under test. - requests: - - - # does not match an existing document - name: "deleteOne" - arguments: - filter: { _id: 3 } - - - # deletes the matched document - name: "deleteOne" - arguments: - filter: { _id: 2 } - options: { ordered: true } - outcome: - result: - deletedCount: 1 - insertedCount: 0 - insertedIds: {} - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 0 - upsertedIds: {} - collection: - data: - - {_id: 1, x: 11 } - - - description: "BulkWrite with deleteMany operations" - operation: - name: "bulkWrite" - arguments: - requests: - - - # does not match any existing documents - name: "deleteMany" - arguments: - filter: { x: { $lt: 11 } } - - - # deletes the matched documents - name: "deleteMany" - arguments: - filter: { x: { $lte: 22 } } - options: { ordered: true } - outcome: - result: - deletedCount: 2 - insertedCount: 0 - insertedIds: {} - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 0 - upsertedIds: {} - collection: - data: [] - - - description: "BulkWrite with insertOne operations" - operation: - name: "bulkWrite" - arguments: - requests: - - - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - - - name: "insertOne" - arguments: - document: { _id: 4, x: 44 } - options: { ordered: true } - outcome: - result: - deletedCount: 0 - insertedCount: 2 - insertedIds: { 0: 3, 1: 4 } - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 0 - upsertedIds: {} - collection: - data: - - {_id: 1, x: 11 } - - {_id: 2, x: 22 } - - {_id: 3, x: 33 } - - {_id: 4, x: 44 } - - - description: "BulkWrite with replaceOne operations" - operation: - name: "bulkWrite" - arguments: - # Note: as in the "ReplaceOne when many documents match" test in - # replaceOne.yml, we omit a replaceOne operation that might - # match multiple documents as that would hinder our ability to - # assert the final state of the collection under test. - requests: - - - # does not match an existing document - name: "replaceOne" - arguments: - filter: { _id: 3 } - replacement: { x: 33 } - - - # modifies the matched document - name: "replaceOne" - arguments: - filter: { _id: 1 } - replacement: { x: 12 } - - - # does not match an existing document and upserts - name: "replaceOne" - arguments: - filter: { _id: 3 } - replacement: { x: 33 } - upsert: true - options: { ordered: true } - outcome: - result: - deletedCount: 0 - insertedCount: 0 - insertedIds: {} - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 1 - upsertedIds: { 2: 3 } - collection: - data: - - {_id: 1, x: 12 } - - {_id: 2, x: 22 } - - {_id: 3, x: 33 } - - - description: "BulkWrite with updateOne operations" - operation: - name: "bulkWrite" - arguments: - # Note: as in the "UpdateOne when many documents match" test in - # updateOne.yml, we omit an updateOne operation that might match - # multiple documents as that would hinder our ability to assert - # the final state of the collection under test. - requests: - - - # does not match an existing document - name: "updateOne" - arguments: - filter: { _id: 0 } - update: { $set: { x: 0 } } - - - # does not modify the matched document - name: "updateOne" - arguments: - filter: { _id: 1 } - update: { $set: { x: 11 } } - - - # modifies the matched document - name: "updateOne" - arguments: - filter: { _id: 2 } - update: { $inc: { x: 1 } } - - - # does not match an existing document and upserts - name: "updateOne" - arguments: - filter: { _id: 3 } - update: { $set: { x: 33 } } - upsert: true - options: { ordered: true } - outcome: - result: - deletedCount: 0 - insertedCount: 0 - insertedIds: {} - matchedCount: 2 - modifiedCount: 1 - upsertedCount: 1 - upsertedIds: { 3: 3 } - collection: - data: - - {_id: 1, x: 11 } - - {_id: 2, x: 23 } - - {_id: 3, x: 33 } - - - description: "BulkWrite with updateMany operations" - operation: - name: "bulkWrite" - arguments: - requests: - - - # does not match any existing documents - name: "updateMany" - arguments: - filter: { x: { $lt: 11 } } - update: { $set: { x: 0 } } - - - # does not modify the matched documents - name: "updateMany" - arguments: - filter: { x: { $lte: 22 } } - update: { $unset: { y: 1 } } - - - # modifies the matched documents - name: "updateMany" - arguments: - filter: { x: { $lte: 22 } } - update: { $inc: { x: 1 } } - - - # does not match any existing documents and upserts - name: "updateMany" - arguments: - filter: { _id: 3 } - update: { $set: { x: 33 } } - upsert: true - options: { ordered: true } - outcome: - result: - deletedCount: 0 - insertedCount: 0 - insertedIds: {} - matchedCount: 4 - modifiedCount: 2 - upsertedCount: 1 - upsertedIds: { 3: 3 } - collection: - data: - - {_id: 1, x: 12 } - - {_id: 2, x: 23 } - - {_id: 3, x: 33 } - - - description: "BulkWrite with mixed ordered operations" - operation: - name: "bulkWrite" - arguments: - requests: - - - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - - - name: "updateOne" - arguments: - filter: { _id: 2 } - update: { $inc: { x: 1 } } - - - name: "updateMany" - arguments: - filter: { _id: { $gt: 1 } } - update: { $inc: { x: 1 } } - - - name: "insertOne" - arguments: - document: { _id: 4, x: 44 } - - - name: "deleteMany" - arguments: - filter: { x: { $nin: [ 24, 34 ] } } - - - name: "replaceOne" - arguments: - filter: { _id: 4 } - replacement: { _id: 4, x: 44 } - upsert: true - options: { ordered: true } - outcome: - result: - deletedCount: 2 - insertedCount: 2 - insertedIds: { 0: 3, 3: 4 } - matchedCount: 3 - modifiedCount: 3 - upsertedCount: 1 - upsertedIds: { 5: 4 } - collection: - data: - - {_id: 2, x: 24 } - - {_id: 3, x: 34 } - - {_id: 4, x: 44 } - - - description: "BulkWrite with mixed unordered operations" - operation: - name: "bulkWrite" - arguments: - # We omit inserting multiple documents and updating documents - # that may not exist at the start of this test as we cannot - # assume the order in which the operations will execute. - requests: - - - name: "replaceOne" - arguments: - filter: { _id: 3 } - replacement: { _id: 3, x: 33 } - upsert: true - - - name: "deleteOne" - arguments: - filter: { _id: 1 } - - - name: "updateOne" - arguments: - filter: { _id: 2 } - update: { $inc: { x: 1 } } - options: { ordered: false } - outcome: - result: - deletedCount: 1 - insertedCount: 0 - insertedIds: {} - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 1 - upsertedIds: { 0: 3 } - collection: - data: - - {_id: 2, x: 23 } - - {_id: 3, x: 33 } - - - description: "BulkWrite continue-on-error behavior with unordered (preexisting duplicate key)" - operation: - name: "bulkWrite" - arguments: - requests: - - - name: "insertOne" - arguments: - document: { _id: 2, x: 22 } - - - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - - - name: "insertOne" - arguments: - document: { _id: 4, x: 44 } - options: { ordered: false } - outcome: - error: true - result: - deletedCount: 0 - insertedCount: 2 - # Since the map of insertedIds is generated before execution it - # could indicate inserts that did not actually succeed. We omit - # this field rather than expect drivers to provide an accurate - # map filtered by write errors. - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 0 - upsertedIds: { } - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - { _id: 4, x: 44 } - - - description: "BulkWrite continue-on-error behavior with unordered (duplicate key in requests)" - operation: - name: "bulkWrite" - arguments: - requests: - - - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - - - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - - - name: "insertOne" - arguments: - document: { _id: 4, x: 44 } - options: { ordered: false } - outcome: - error: true - result: - deletedCount: 0 - insertedCount: 2 - # Since the map of insertedIds is generated before execution it - # could indicate inserts that did not actually succeed. We omit - # this field rather than expect drivers to provide an accurate - # map filtered by write errors. - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 0 - upsertedIds: { } - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - { _id: 4, x: 44 } diff --git a/test/spec/crud/v1/write/deleteMany-collation.json b/test/spec/crud/v1/write/deleteMany-collation.json deleted file mode 100644 index fce75e488a..0000000000 --- a/test/spec/crud/v1/write/deleteMany-collation.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": "ping" - }, - { - "_id": 3, - "x": "pINg" - } - ], - "minServerVersion": "3.4", - "serverless": "forbid", - "tests": [ - { - "description": "DeleteMany when many documents match with collation", - "operation": { - "name": "deleteMany", - "arguments": { - "filter": { - "x": "PING" - }, - "collation": { - "locale": "en_US", - "strength": 2 - } - } - }, - "outcome": { - "result": { - "deletedCount": 2 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/deleteMany-collation.yml b/test/spec/crud/v1/write/deleteMany-collation.yml deleted file mode 100644 index 65a49b7fda..0000000000 --- a/test/spec/crud/v1/write/deleteMany-collation.yml +++ /dev/null @@ -1,23 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 'ping'} - - {_id: 3, x: 'pINg'} -minServerVersion: '3.4' -serverless: 'forbid' - -tests: - - - description: "DeleteMany when many documents match with collation" - operation: - name: "deleteMany" - arguments: - filter: - x: 'PING' - collation: { locale: 'en_US', strength: 2 } # https://www.mongodb.com/docs/manual/reference/collation/#collation-document - - outcome: - result: - deletedCount: 2 - collection: - data: - - {_id: 1, x: 11} diff --git a/test/spec/crud/v1/write/deleteMany.json b/test/spec/crud/v1/write/deleteMany.json deleted file mode 100644 index 7eee85e77f..0000000000 --- a/test/spec/crud/v1/write/deleteMany.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "tests": [ - { - "description": "DeleteMany when many documents match", - "operation": { - "name": "deleteMany", - "arguments": { - "filter": { - "_id": { - "$gt": 1 - } - } - } - }, - "outcome": { - "result": { - "deletedCount": 2 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - } - ] - } - } - }, - { - "description": "DeleteMany when no document matches", - "operation": { - "name": "deleteMany", - "arguments": { - "filter": { - "_id": 4 - } - } - }, - "outcome": { - "result": { - "deletedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/deleteMany.yml b/test/spec/crud/v1/write/deleteMany.yml deleted file mode 100644 index e776c82f9a..0000000000 --- a/test/spec/crud/v1/write/deleteMany.yml +++ /dev/null @@ -1,35 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - -tests: - - - description: "DeleteMany when many documents match" - operation: - name: "deleteMany" - arguments: - filter: - _id: {$gt: 1} - - outcome: - result: - deletedCount: 2 - collection: - data: - - {_id: 1, x: 11} - - - description: "DeleteMany when no document matches" - operation: - name: "deleteMany" - arguments: - filter: {_id: 4} - - outcome: - result: - deletedCount: 0 - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} diff --git a/test/spec/crud/v1/write/deleteOne-collation.json b/test/spec/crud/v1/write/deleteOne-collation.json deleted file mode 100644 index 9bcef411ef..0000000000 --- a/test/spec/crud/v1/write/deleteOne-collation.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": "ping" - }, - { - "_id": 3, - "x": "pINg" - } - ], - "minServerVersion": "3.4", - "serverless": "forbid", - "tests": [ - { - "description": "DeleteOne when many documents matches with collation", - "operation": { - "name": "deleteOne", - "arguments": { - "filter": { - "x": "PING" - }, - "collation": { - "locale": "en_US", - "strength": 2 - } - } - }, - "outcome": { - "result": { - "deletedCount": 1 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 3, - "x": "pINg" - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/deleteOne-collation.yml b/test/spec/crud/v1/write/deleteOne-collation.yml deleted file mode 100644 index ce335bf3de..0000000000 --- a/test/spec/crud/v1/write/deleteOne-collation.yml +++ /dev/null @@ -1,23 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 'ping'} - - {_id: 3, x: 'pINg'} -minServerVersion: '3.4' -serverless: 'forbid' - -tests: - - - description: "DeleteOne when many documents matches with collation" - operation: - name: "deleteOne" - arguments: - filter: {x: 'PING'} - collation: { locale: 'en_US', strength: 2 } # https://www.mongodb.com/docs/manual/reference/collation/#collation-document - - outcome: - result: - deletedCount: 1 - collection: - data: - - {_id: 1, x: 11} - - {_id: 3, x: 'pINg'} diff --git a/test/spec/crud/v1/write/deleteOne.json b/test/spec/crud/v1/write/deleteOne.json deleted file mode 100644 index a1106deae3..0000000000 --- a/test/spec/crud/v1/write/deleteOne.json +++ /dev/null @@ -1,96 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "tests": [ - { - "description": "DeleteOne when many documents match", - "operation": { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": { - "$gt": 1 - } - } - } - }, - "outcome": { - "result": { - "deletedCount": 1 - } - } - }, - { - "description": "DeleteOne when one document matches", - "operation": { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 2 - } - } - }, - "outcome": { - "result": { - "deletedCount": 1 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "DeleteOne when no documents match", - "operation": { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 4 - } - } - }, - "outcome": { - "result": { - "deletedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/deleteOne.yml b/test/spec/crud/v1/write/deleteOne.yml deleted file mode 100644 index 2d8a90779f..0000000000 --- a/test/spec/crud/v1/write/deleteOne.yml +++ /dev/null @@ -1,48 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - -tests: - - - description: "DeleteOne when many documents match" - operation: - name: "deleteOne" - arguments: - filter: - _id: {$gt: 1} - - outcome: - result: - deletedCount: 1 - # can't verify collection because we don't have a way - # of knowing which document gets deleted. - - - description: "DeleteOne when one document matches" - operation: - name: "deleteOne" - arguments: - filter: {_id: 2} - - outcome: - result: - deletedCount: 1 - collection: - data: - - {_id: 1, x: 11} - - {_id: 3, x: 33} - - - description: "DeleteOne when no documents match" - operation: - name: "deleteOne" - arguments: - filter: {_id: 4} - - outcome: - result: - deletedCount: 0 - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} diff --git a/test/spec/crud/v1/write/findOneAndDelete-collation.json b/test/spec/crud/v1/write/findOneAndDelete-collation.json deleted file mode 100644 index 32480da842..0000000000 --- a/test/spec/crud/v1/write/findOneAndDelete-collation.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": "ping" - }, - { - "_id": 3, - "x": "pINg" - } - ], - "minServerVersion": "3.4", - "serverless": "forbid", - "tests": [ - { - "description": "FindOneAndDelete when one document matches with collation", - "operation": { - "name": "findOneAndDelete", - "arguments": { - "filter": { - "_id": 2, - "x": "PING" - }, - "projection": { - "x": 1, - "_id": 0 - }, - "sort": { - "x": 1 - }, - "collation": { - "locale": "en_US", - "strength": 2 - } - } - }, - "outcome": { - "result": { - "x": "ping" - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 3, - "x": "pINg" - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/findOneAndDelete-collation.yml b/test/spec/crud/v1/write/findOneAndDelete-collation.yml deleted file mode 100644 index 720ecb2f81..0000000000 --- a/test/spec/crud/v1/write/findOneAndDelete-collation.yml +++ /dev/null @@ -1,24 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 'ping'} - - {_id: 3, x: 'pINg'} -minServerVersion: '3.4' -serverless: 'forbid' - -tests: - - - description: "FindOneAndDelete when one document matches with collation" - operation: - name: findOneAndDelete - arguments: - filter: {_id: 2, x: 'PING'} - projection: {x: 1, _id: 0} - sort: {x: 1} - collation: { locale: 'en_US', strength: 2 } # https://www.mongodb.com/docs/manual/reference/collation/#collation-document - - outcome: - result: {x: 'ping'} - collection: - data: - - {_id: 1, x: 11} - - {_id: 3, x: 'pINg'} diff --git a/test/spec/crud/v1/write/findOneAndDelete.json b/test/spec/crud/v1/write/findOneAndDelete.json deleted file mode 100644 index e424e2aad1..0000000000 --- a/test/spec/crud/v1/write/findOneAndDelete.json +++ /dev/null @@ -1,127 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "tests": [ - { - "description": "FindOneAndDelete when many documents match", - "operation": { - "name": "findOneAndDelete", - "arguments": { - "filter": { - "_id": { - "$gt": 1 - } - }, - "projection": { - "x": 1, - "_id": 0 - }, - "sort": { - "x": 1 - } - } - }, - "outcome": { - "result": { - "x": 22 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "FindOneAndDelete when one document matches", - "operation": { - "name": "findOneAndDelete", - "arguments": { - "filter": { - "_id": 2 - }, - "projection": { - "x": 1, - "_id": 0 - }, - "sort": { - "x": 1 - } - } - }, - "outcome": { - "result": { - "x": 22 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "FindOneAndDelete when no documents match", - "operation": { - "name": "findOneAndDelete", - "arguments": { - "filter": { - "_id": 4 - }, - "projection": { - "x": 1, - "_id": 0 - }, - "sort": { - "x": 1 - } - } - }, - "outcome": { - "result": null, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/findOneAndDelete.yml b/test/spec/crud/v1/write/findOneAndDelete.yml deleted file mode 100644 index a485ee46a5..0000000000 --- a/test/spec/crud/v1/write/findOneAndDelete.yml +++ /dev/null @@ -1,53 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - -tests: - - - description: "FindOneAndDelete when many documents match" - operation: - name: findOneAndDelete - arguments: - filter: - _id: {$gt: 1} - projection: {x: 1, _id: 0} - sort: {x: 1} - - outcome: - result: {x: 22} - collection: - data: - - {_id: 1, x: 11} - - {_id: 3, x: 33} - - - description: "FindOneAndDelete when one document matches" - operation: - name: findOneAndDelete - arguments: - filter: {_id: 2} - projection: {x: 1, _id: 0} - sort: {x: 1} - - outcome: - result: {x: 22} - collection: - data: - - {_id: 1, x: 11} - - {_id: 3, x: 33} - - - description: "FindOneAndDelete when no documents match" - operation: - name: findOneAndDelete - arguments: - filter: {_id: 4} - projection: {x: 1, _id: 0} - sort: {x: 1} - - outcome: - result: null - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} \ No newline at end of file diff --git a/test/spec/crud/v1/write/findOneAndReplace-collation.json b/test/spec/crud/v1/write/findOneAndReplace-collation.json deleted file mode 100644 index 9b3c25005b..0000000000 --- a/test/spec/crud/v1/write/findOneAndReplace-collation.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": "ping" - } - ], - "minServerVersion": "3.4", - "serverless": "forbid", - "tests": [ - { - "description": "FindOneAndReplace when one document matches with collation returning the document after modification", - "operation": { - "name": "findOneAndReplace", - "arguments": { - "filter": { - "x": "PING" - }, - "replacement": { - "x": "pong" - }, - "projection": { - "x": 1, - "_id": 0 - }, - "returnDocument": "After", - "sort": { - "x": 1 - }, - "collation": { - "locale": "en_US", - "strength": 2 - } - } - }, - "outcome": { - "result": { - "x": "pong" - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": "pong" - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/findOneAndReplace-collation.yml b/test/spec/crud/v1/write/findOneAndReplace-collation.yml deleted file mode 100644 index f132b1211d..0000000000 --- a/test/spec/crud/v1/write/findOneAndReplace-collation.yml +++ /dev/null @@ -1,25 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 'ping'} -minServerVersion: '3.4' -serverless: 'forbid' - -tests: - - - description: "FindOneAndReplace when one document matches with collation returning the document after modification" - operation: - name: findOneAndReplace - arguments: - filter: {x: 'PING'} - replacement: {x: 'pong'} - projection: {x: 1, _id: 0} - returnDocument: After - sort: {x: 1} - collation: { locale: 'en_US', strength: 2 } # https://www.mongodb.com/docs/manual/reference/collation/#collation-document - - outcome: - result: {x: 'pong'} - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 'pong'} diff --git a/test/spec/crud/v1/write/findOneAndReplace-upsert.json b/test/spec/crud/v1/write/findOneAndReplace-upsert.json deleted file mode 100644 index 0f07bf9c18..0000000000 --- a/test/spec/crud/v1/write/findOneAndReplace-upsert.json +++ /dev/null @@ -1,201 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "minServerVersion": "2.6", - "tests": [ - { - "description": "FindOneAndReplace when no documents match without id specified with upsert returning the document before modification", - "operation": { - "name": "findOneAndReplace", - "arguments": { - "filter": { - "_id": 4 - }, - "replacement": { - "x": 44 - }, - "projection": { - "x": 1, - "_id": 0 - }, - "upsert": true - } - }, - "outcome": { - "result": null, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - } - }, - { - "description": "FindOneAndReplace when no documents match without id specified with upsert returning the document after modification", - "operation": { - "name": "findOneAndReplace", - "arguments": { - "filter": { - "_id": 4 - }, - "replacement": { - "x": 44 - }, - "projection": { - "x": 1, - "_id": 0 - }, - "returnDocument": "After", - "sort": { - "x": 1 - }, - "upsert": true - } - }, - "outcome": { - "result": { - "x": 44 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - } - }, - { - "description": "FindOneAndReplace when no documents match with id specified with upsert returning the document before modification", - "operation": { - "name": "findOneAndReplace", - "arguments": { - "filter": { - "_id": 4 - }, - "replacement": { - "_id": 4, - "x": 44 - }, - "projection": { - "x": 1, - "_id": 0 - }, - "upsert": true - } - }, - "outcome": { - "result": null, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - } - }, - { - "description": "FindOneAndReplace when no documents match with id specified with upsert returning the document after modification", - "operation": { - "name": "findOneAndReplace", - "arguments": { - "filter": { - "_id": 4 - }, - "replacement": { - "_id": 4, - "x": 44 - }, - "projection": { - "x": 1, - "_id": 0 - }, - "returnDocument": "After", - "sort": { - "x": 1 - }, - "upsert": true - } - }, - "outcome": { - "result": { - "x": 44 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/findOneAndReplace-upsert.yml b/test/spec/crud/v1/write/findOneAndReplace-upsert.yml deleted file mode 100644 index 2bd64c94ec..0000000000 --- a/test/spec/crud/v1/write/findOneAndReplace-upsert.yml +++ /dev/null @@ -1,91 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} -minServerVersion: '2.6' - -tests: - - - description: "FindOneAndReplace when no documents match without id specified with upsert returning the document before modification" - operation: - name: findOneAndReplace - arguments: - filter: {_id: 4} - replacement: {x: 44} - projection: {x: 1, _id: 0} - # Omit the sort option as it has no effect when no documents - # match and would only cause an inconsistent return value on - # pre-3.0 servers when combined with returnDocument "before" - # (see: SERVER-17650). - upsert: true - - outcome: - result: null - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - {_id: 4, x: 44} - - - description: "FindOneAndReplace when no documents match without id specified with upsert returning the document after modification" - operation: - name: findOneAndReplace - arguments: - filter: {_id: 4} - replacement: {x: 44} - projection: {x: 1, _id: 0} - returnDocument: After - sort: {x: 1} - upsert: true - - outcome: - result: {x: 44} - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - {_id: 4, x: 44} - - - description: "FindOneAndReplace when no documents match with id specified with upsert returning the document before modification" - operation: - name: findOneAndReplace - arguments: - filter: {_id: 4} - replacement: {_id: 4, x: 44} - projection: {x: 1, _id: 0} - # Omit the sort option as it has no effect when no documents - # match and would only cause an inconsistent return value on - # pre-3.0 servers when combined with returnDocument "before" - # (see: SERVER-17650). - upsert: true - - outcome: - result: null - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - {_id: 4, x: 44} - - - description: "FindOneAndReplace when no documents match with id specified with upsert returning the document after modification" - operation: - name: findOneAndReplace - arguments: - filter: {_id: 4} - replacement: {_id: 4, x: 44} - projection: {x: 1, _id: 0} - returnDocument: After - sort: {x: 1} - upsert: true - - outcome: - result: {x: 44} - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - {_id: 4, x: 44} diff --git a/test/spec/crud/v1/write/findOneAndReplace.json b/test/spec/crud/v1/write/findOneAndReplace.json deleted file mode 100644 index 70e5c3df4e..0000000000 --- a/test/spec/crud/v1/write/findOneAndReplace.json +++ /dev/null @@ -1,273 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "tests": [ - { - "description": "FindOneAndReplace when many documents match returning the document before modification", - "operation": { - "name": "findOneAndReplace", - "arguments": { - "filter": { - "_id": { - "$gt": 1 - } - }, - "replacement": { - "x": 32 - }, - "projection": { - "x": 1, - "_id": 0 - }, - "sort": { - "x": 1 - } - } - }, - "outcome": { - "result": { - "x": 22 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 32 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "FindOneAndReplace when many documents match returning the document after modification", - "operation": { - "name": "findOneAndReplace", - "arguments": { - "filter": { - "_id": { - "$gt": 1 - } - }, - "replacement": { - "x": 32 - }, - "projection": { - "x": 1, - "_id": 0 - }, - "returnDocument": "After", - "sort": { - "x": 1 - } - } - }, - "outcome": { - "result": { - "x": 32 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 32 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "FindOneAndReplace when one document matches returning the document before modification", - "operation": { - "name": "findOneAndReplace", - "arguments": { - "filter": { - "_id": 2 - }, - "replacement": { - "x": 32 - }, - "projection": { - "x": 1, - "_id": 0 - }, - "sort": { - "x": 1 - } - } - }, - "outcome": { - "result": { - "x": 22 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 32 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "FindOneAndReplace when one document matches returning the document after modification", - "operation": { - "name": "findOneAndReplace", - "arguments": { - "filter": { - "_id": 2 - }, - "replacement": { - "x": 32 - }, - "projection": { - "x": 1, - "_id": 0 - }, - "returnDocument": "After", - "sort": { - "x": 1 - } - } - }, - "outcome": { - "result": { - "x": 32 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 32 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "FindOneAndReplace when no documents match returning the document before modification", - "operation": { - "name": "findOneAndReplace", - "arguments": { - "filter": { - "_id": 4 - }, - "replacement": { - "x": 44 - }, - "projection": { - "x": 1, - "_id": 0 - }, - "sort": { - "x": 1 - } - } - }, - "outcome": { - "result": null, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "FindOneAndReplace when no documents match returning the document after modification", - "operation": { - "name": "findOneAndReplace", - "arguments": { - "filter": { - "_id": 4 - }, - "replacement": { - "x": 44 - }, - "projection": { - "x": 1, - "_id": 0 - }, - "returnDocument": "After", - "sort": { - "x": 1 - } - } - }, - "outcome": { - "result": null, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/findOneAndReplace.yml b/test/spec/crud/v1/write/findOneAndReplace.yml deleted file mode 100644 index c121418b78..0000000000 --- a/test/spec/crud/v1/write/findOneAndReplace.yml +++ /dev/null @@ -1,113 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - -tests: - - - description: "FindOneAndReplace when many documents match returning the document before modification" - operation: - name: findOneAndReplace - arguments: - filter: - _id: {$gt: 1} - replacement: {x: 32} - projection: {x: 1, _id: 0} - sort: {x: 1} - - outcome: - result: {x: 22} - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 32} - - {_id: 3, x: 33} - - - description: "FindOneAndReplace when many documents match returning the document after modification" - operation: - name: findOneAndReplace - arguments: - filter: - _id: {$gt: 1} - replacement: {x: 32} - projection: {x: 1, _id: 0} - returnDocument: After - sort: {x: 1} - - outcome: - result: {x: 32} - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 32} - - {_id: 3, x: 33} - - - description: "FindOneAndReplace when one document matches returning the document before modification" - operation: - name: findOneAndReplace - arguments: - filter: {_id: 2} - replacement: {x: 32} - projection: {x: 1, _id: 0} - sort: {x: 1} - - outcome: - result: {x: 22} - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 32} - - {_id: 3, x: 33} - - - description: "FindOneAndReplace when one document matches returning the document after modification" - operation: - name: findOneAndReplace - arguments: - filter: {_id: 2} - replacement: {x: 32} - projection: {x: 1, _id: 0} - returnDocument: After - sort: {x: 1} - - outcome: - result: {x: 32} - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 32} - - {_id: 3, x: 33} - - - description: "FindOneAndReplace when no documents match returning the document before modification" - operation: - name: findOneAndReplace - arguments: - filter: {_id: 4} - replacement: {x: 44} - projection: {x: 1, _id: 0} - sort: {x: 1} - - outcome: - result: null - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - - description: "FindOneAndReplace when no documents match returning the document after modification" - operation: - name: findOneAndReplace - arguments: - filter: {_id: 4} - replacement: {x: 44} - projection: {x: 1, _id: 0} - returnDocument: After - sort: {x: 1} - - outcome: - result: null - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} diff --git a/test/spec/crud/v1/write/findOneAndUpdate-arrayFilters.json b/test/spec/crud/v1/write/findOneAndUpdate-arrayFilters.json deleted file mode 100644 index 1aa13b863e..0000000000 --- a/test/spec/crud/v1/write/findOneAndUpdate-arrayFilters.json +++ /dev/null @@ -1,203 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "y": [ - { - "b": 3 - }, - { - "b": 1 - } - ] - }, - { - "_id": 2, - "y": [ - { - "b": 0 - }, - { - "b": 1 - } - ] - } - ], - "minServerVersion": "3.5.6", - "tests": [ - { - "description": "FindOneAndUpdate when no document matches arrayFilters", - "operation": { - "name": "findOneAndUpdate", - "arguments": { - "filter": {}, - "update": { - "$set": { - "y.$[i].b": 2 - } - }, - "arrayFilters": [ - { - "i.b": 4 - } - ] - } - }, - "outcome": { - "result": { - "_id": 1, - "y": [ - { - "b": 3 - }, - { - "b": 1 - } - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "y": [ - { - "b": 3 - }, - { - "b": 1 - } - ] - }, - { - "_id": 2, - "y": [ - { - "b": 0 - }, - { - "b": 1 - } - ] - } - ] - } - } - }, - { - "description": "FindOneAndUpdate when one document matches arrayFilters", - "operation": { - "name": "findOneAndUpdate", - "arguments": { - "filter": {}, - "update": { - "$set": { - "y.$[i].b": 2 - } - }, - "arrayFilters": [ - { - "i.b": 3 - } - ] - } - }, - "outcome": { - "result": { - "_id": 1, - "y": [ - { - "b": 3 - }, - { - "b": 1 - } - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "y": [ - { - "b": 2 - }, - { - "b": 1 - } - ] - }, - { - "_id": 2, - "y": [ - { - "b": 0 - }, - { - "b": 1 - } - ] - } - ] - } - } - }, - { - "description": "FindOneAndUpdate when multiple documents match arrayFilters", - "operation": { - "name": "findOneAndUpdate", - "arguments": { - "filter": {}, - "update": { - "$set": { - "y.$[i].b": 2 - } - }, - "arrayFilters": [ - { - "i.b": 1 - } - ] - } - }, - "outcome": { - "result": { - "_id": 1, - "y": [ - { - "b": 3 - }, - { - "b": 1 - } - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "y": [ - { - "b": 3 - }, - { - "b": 2 - } - ] - }, - { - "_id": 2, - "y": [ - { - "b": 0 - }, - { - "b": 1 - } - ] - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/findOneAndUpdate-arrayFilters.yml b/test/spec/crud/v1/write/findOneAndUpdate-arrayFilters.yml deleted file mode 100644 index 7665ad0c59..0000000000 --- a/test/spec/crud/v1/write/findOneAndUpdate-arrayFilters.yml +++ /dev/null @@ -1,69 +0,0 @@ -data: - - {_id: 1, y: [{b: 3}, {b: 1}]} - - {_id: 2, y: [{b: 0}, {b: 1}]} -minServerVersion: '3.5.6' - -tests: - - - description: "FindOneAndUpdate when no document matches arrayFilters" - operation: - name: findOneAndUpdate - arguments: - filter: {} - update: - $set: {"y.$[i].b": 2} - arrayFilters: - - {i.b: 4} - - outcome: - result: - _id: 1 - y: - - {b: 3} - - {b: 1} - collection: - data: - - {_id: 1, y: [{b: 3}, {b: 1}]} - - {_id: 2, y: [{b: 0}, {b: 1}]} - - - description: "FindOneAndUpdate when one document matches arrayFilters" - operation: - name: findOneAndUpdate - arguments: - filter: {} - update: - $set: {"y.$[i].b": 2} - arrayFilters: - - {i.b: 3} - - outcome: - result: - _id: 1 - y: - - {b: 3} - - {b: 1} - collection: - data: - - {_id: 1, y: [{b: 2}, {b: 1}]} - - {_id: 2, y: [{b: 0}, {b: 1}]} - - - description: "FindOneAndUpdate when multiple documents match arrayFilters" - operation: - name: findOneAndUpdate - arguments: - filter: {} - update: - $set: {"y.$[i].b": 2} - arrayFilters: - - {i.b: 1} - - outcome: - result: - _id: 1 - y: - - {b: 3} - - {b: 1} - collection: - data: - - {_id: 1, y: [{b: 3}, {b: 2}]} - - {_id: 2, y: [{b: 0}, {b: 1}]} diff --git a/test/spec/crud/v1/write/findOneAndUpdate-collation.json b/test/spec/crud/v1/write/findOneAndUpdate-collation.json deleted file mode 100644 index 8abab7bd6b..0000000000 --- a/test/spec/crud/v1/write/findOneAndUpdate-collation.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": "ping" - }, - { - "_id": 3, - "x": "pINg" - } - ], - "minServerVersion": "3.4", - "serverless": "forbid", - "tests": [ - { - "description": "FindOneAndUpdate when many documents match with collation returning the document before modification", - "operation": { - "name": "findOneAndUpdate", - "arguments": { - "filter": { - "x": "PING" - }, - "update": { - "$set": { - "x": "pong" - } - }, - "projection": { - "x": 1, - "_id": 0 - }, - "sort": { - "_id": 1 - }, - "collation": { - "locale": "en_US", - "strength": 2 - } - } - }, - "outcome": { - "result": { - "x": "ping" - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": "pong" - }, - { - "_id": 3, - "x": "pINg" - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/findOneAndUpdate-collation.yml b/test/spec/crud/v1/write/findOneAndUpdate-collation.yml deleted file mode 100644 index 5a110b01bf..0000000000 --- a/test/spec/crud/v1/write/findOneAndUpdate-collation.yml +++ /dev/null @@ -1,28 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 'ping'} - - {_id: 3, x: 'pINg'} -minServerVersion: '3.4' -serverless: 'forbid' - -tests: - - - description: "FindOneAndUpdate when many documents match with collation returning the document before modification" - operation: - name: findOneAndUpdate - arguments: - filter: - x: 'PING' - update: - $set: {x: 'pong'} - projection: {x: 1, _id: 0} - sort: {_id: 1} - collation: { locale: 'en_US', strength: 2 } # https://www.mongodb.com/docs/manual/reference/collation/#collation-document - - outcome: - result: {x: 'ping'} - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 'pong'} - - {_id: 3, x: 'pINg'} diff --git a/test/spec/crud/v1/write/findOneAndUpdate.json b/test/spec/crud/v1/write/findOneAndUpdate.json deleted file mode 100644 index 6da8325273..0000000000 --- a/test/spec/crud/v1/write/findOneAndUpdate.json +++ /dev/null @@ -1,379 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "tests": [ - { - "description": "FindOneAndUpdate when many documents match returning the document before modification", - "operation": { - "name": "findOneAndUpdate", - "arguments": { - "filter": { - "_id": { - "$gt": 1 - } - }, - "update": { - "$inc": { - "x": 1 - } - }, - "projection": { - "x": 1, - "_id": 0 - }, - "sort": { - "x": 1 - } - } - }, - "outcome": { - "result": { - "x": 22 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 23 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "FindOneAndUpdate when many documents match returning the document after modification", - "operation": { - "name": "findOneAndUpdate", - "arguments": { - "filter": { - "_id": { - "$gt": 1 - } - }, - "update": { - "$inc": { - "x": 1 - } - }, - "projection": { - "x": 1, - "_id": 0 - }, - "returnDocument": "After", - "sort": { - "x": 1 - } - } - }, - "outcome": { - "result": { - "x": 23 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 23 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "FindOneAndUpdate when one document matches returning the document before modification", - "operation": { - "name": "findOneAndUpdate", - "arguments": { - "filter": { - "_id": 2 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "projection": { - "x": 1, - "_id": 0 - }, - "sort": { - "x": 1 - } - } - }, - "outcome": { - "result": { - "x": 22 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 23 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "FindOneAndUpdate when one document matches returning the document after modification", - "operation": { - "name": "findOneAndUpdate", - "arguments": { - "filter": { - "_id": 2 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "projection": { - "x": 1, - "_id": 0 - }, - "returnDocument": "After", - "sort": { - "x": 1 - } - } - }, - "outcome": { - "result": { - "x": 23 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 23 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "FindOneAndUpdate when no documents match returning the document before modification", - "operation": { - "name": "findOneAndUpdate", - "arguments": { - "filter": { - "_id": 4 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "projection": { - "x": 1, - "_id": 0 - }, - "sort": { - "x": 1 - } - } - }, - "outcome": { - "result": null, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "FindOneAndUpdate when no documents match with upsert returning the document before modification", - "operation": { - "name": "findOneAndUpdate", - "arguments": { - "filter": { - "_id": 4 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "projection": { - "x": 1, - "_id": 0 - }, - "upsert": true - } - }, - "outcome": { - "result": null, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 1 - } - ] - } - } - }, - { - "description": "FindOneAndUpdate when no documents match returning the document after modification", - "operation": { - "name": "findOneAndUpdate", - "arguments": { - "filter": { - "_id": 4 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "projection": { - "x": 1, - "_id": 0 - }, - "returnDocument": "After", - "sort": { - "x": 1 - } - } - }, - "outcome": { - "result": null, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "FindOneAndUpdate when no documents match with upsert returning the document after modification", - "operation": { - "name": "findOneAndUpdate", - "arguments": { - "filter": { - "_id": 4 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "projection": { - "x": 1, - "_id": 0 - }, - "returnDocument": "After", - "sort": { - "x": 1 - }, - "upsert": true - } - }, - "outcome": { - "result": { - "x": 1 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 1 - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/findOneAndUpdate.yml b/test/spec/crud/v1/write/findOneAndUpdate.yml deleted file mode 100644 index bed02f146a..0000000000 --- a/test/spec/crud/v1/write/findOneAndUpdate.yml +++ /dev/null @@ -1,163 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - -tests: - - - description: "FindOneAndUpdate when many documents match returning the document before modification" - operation: - name: findOneAndUpdate - arguments: - filter: - _id: {$gt: 1} - update: - $inc: {x: 1} - projection: {x: 1, _id: 0} - sort: {x: 1} - - outcome: - result: {x: 22} - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 23} - - {_id: 3, x: 33} - - - description: "FindOneAndUpdate when many documents match returning the document after modification" - operation: - name: findOneAndUpdate - arguments: - filter: - _id: {$gt: 1} - update: - $inc: {x: 1} - projection: {x: 1, _id: 0} - returnDocument: After - sort: {x: 1} - - outcome: - result: {x: 23} - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 23} - - {_id: 3, x: 33} - - - description: "FindOneAndUpdate when one document matches returning the document before modification" - operation: - name: findOneAndUpdate - arguments: - filter: {_id: 2} - update: - $inc: {x: 1} - projection: {x: 1, _id: 0} - sort: {x: 1} - - outcome: - result: {x: 22} - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 23} - - {_id: 3, x: 33} - - - description: "FindOneAndUpdate when one document matches returning the document after modification" - operation: - name: findOneAndUpdate - arguments: - filter: {_id: 2} - update: - $inc: {x: 1} - projection: {x: 1, _id: 0} - returnDocument: After - sort: {x: 1} - - outcome: - result: {x: 23} - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 23} - - {_id: 3, x: 33} - - - description: "FindOneAndUpdate when no documents match returning the document before modification" - operation: - name: findOneAndUpdate - arguments: - filter: {_id: 4} - update: - $inc: {x: 1} - projection: {x: 1, _id: 0} - sort: {x: 1} - - outcome: - result: null - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - - description: "FindOneAndUpdate when no documents match with upsert returning the document before modification" - operation: - name: findOneAndUpdate - arguments: - filter: {_id: 4} - update: - $inc: {x: 1} - projection: {x: 1, _id: 0} - # Omit the sort option as it has no effect when no documents - # match and would only cause an inconsistent return value on - # pre-3.0 servers when combined with returnDocument "before" - # (see: SERVER-17650). - upsert: true - - outcome: - result: null - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - {_id: 4, x: 1} - - - description: "FindOneAndUpdate when no documents match returning the document after modification" - operation: - name: findOneAndUpdate - arguments: - filter: {_id: 4} - update: - $inc: {x: 1} - projection: {x: 1, _id: 0} - returnDocument: After - sort: {x: 1} - - outcome: - result: null - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - - description: "FindOneAndUpdate when no documents match with upsert returning the document after modification" - operation: - name: findOneAndUpdate - arguments: - filter: {_id: 4} - update: - $inc: {x: 1} - projection: {x: 1, _id: 0} - returnDocument: After - sort: {x: 1} - upsert: true - - outcome: - result: {x: 1} - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - {_id: 4, x: 1} \ No newline at end of file diff --git a/test/spec/crud/v1/write/insertMany.json b/test/spec/crud/v1/write/insertMany.json deleted file mode 100644 index 6a2e5261b7..0000000000 --- a/test/spec/crud/v1/write/insertMany.json +++ /dev/null @@ -1,159 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - } - ], - "tests": [ - { - "description": "InsertMany with non-existing documents", - "operation": { - "name": "insertMany", - "arguments": { - "documents": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "insertedIds": { - "0": 2, - "1": 3 - } - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertMany continue-on-error behavior with unordered (preexisting duplicate key)", - "operation": { - "name": "insertMany", - "arguments": { - "documents": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "options": { - "ordered": false - } - } - }, - "outcome": { - "error": true, - "result": { - "deletedCount": 0, - "insertedCount": 2, - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertMany continue-on-error behavior with unordered (duplicate key in requests)", - "operation": { - "name": "insertMany", - "arguments": { - "documents": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "options": { - "ordered": false - } - } - }, - "outcome": { - "error": true, - "result": { - "deletedCount": 0, - "insertedCount": 2, - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/insertMany.yml b/test/spec/crud/v1/write/insertMany.yml deleted file mode 100644 index f76e4af68d..0000000000 --- a/test/spec/crud/v1/write/insertMany.yml +++ /dev/null @@ -1,77 +0,0 @@ -data: - - {_id: 1, x: 11} - -tests: - - - description: "InsertMany with non-existing documents" - operation: - name: "insertMany" - arguments: - documents: - - {_id: 2, x: 22} - - {_id: 3, x: 33} - options: { ordered: true } - outcome: - result: - insertedIds: { 0: 2, 1: 3 } - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - - description: "InsertMany continue-on-error behavior with unordered (preexisting duplicate key)" - operation: - name: "insertMany" - arguments: - documents: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - options: { ordered: false } - outcome: - error: true - result: - deletedCount: 0 - insertedCount: 2 - # Since the map of insertedIds is generated before execution it - # could indicate inserts that did not actually succeed. We omit - # this field rather than expect drivers to provide an accurate - # map filtered by write errors. - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 0 - upsertedIds: { } - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertMany continue-on-error behavior with unordered (duplicate key in requests)" - operation: - name: "insertMany" - arguments: - documents: - - { _id: 2, x: 22 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - options: { ordered: false } - outcome: - error: true - result: - deletedCount: 0 - insertedCount: 2 - # Since the map of insertedIds is generated before execution it - # could indicate inserts that did not actually succeed. We omit - # this field rather than expect drivers to provide an accurate - # map filtered by write errors. - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 0 - upsertedIds: { } - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } diff --git a/test/spec/crud/v1/write/insertOne.json b/test/spec/crud/v1/write/insertOne.json deleted file mode 100644 index 525de75e07..0000000000 --- a/test/spec/crud/v1/write/insertOne.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - } - ], - "tests": [ - { - "description": "InsertOne with a non-existing document", - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 2, - "x": 22 - } - } - }, - "outcome": { - "result": { - "insertedId": 2 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/insertOne.yml b/test/spec/crud/v1/write/insertOne.yml deleted file mode 100644 index 8d65499d9b..0000000000 --- a/test/spec/crud/v1/write/insertOne.yml +++ /dev/null @@ -1,18 +0,0 @@ -data: - - {_id: 1, x: 11} - -tests: - - - description: "InsertOne with a non-existing document" - operation: - name: "insertOne" - arguments: - document: {_id: 2, x: 22} - - outcome: - result: - insertedId: 2 - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} \ No newline at end of file diff --git a/test/spec/crud/v1/write/replaceOne-collation.json b/test/spec/crud/v1/write/replaceOne-collation.json deleted file mode 100644 index fa4cbe9970..0000000000 --- a/test/spec/crud/v1/write/replaceOne-collation.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": "ping" - } - ], - "minServerVersion": "3.4", - "serverless": "forbid", - "tests": [ - { - "description": "ReplaceOne when one document matches with collation", - "operation": { - "name": "replaceOne", - "arguments": { - "filter": { - "x": "PING" - }, - "replacement": { - "_id": 2, - "x": "pong" - }, - "collation": { - "locale": "en_US", - "strength": 2 - } - } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": "pong" - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/replaceOne-collation.yml b/test/spec/crud/v1/write/replaceOne-collation.yml deleted file mode 100644 index cad343caa1..0000000000 --- a/test/spec/crud/v1/write/replaceOne-collation.yml +++ /dev/null @@ -1,25 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 'ping'} -minServerVersion: '3.4' -serverless: 'forbid' - -tests: - - - description: "ReplaceOne when one document matches with collation" - operation: - name: "replaceOne" - arguments: - filter: {x: 'PING'} - replacement: {_id: 2, x: 'pong'} - collation: {locale: 'en_US', strength: 2} # https://www.mongodb.com/docs/manual/reference/collation/#collation-document - - outcome: - result: - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 'pong'} diff --git a/test/spec/crud/v1/write/replaceOne.json b/test/spec/crud/v1/write/replaceOne.json deleted file mode 100644 index 101af25c7c..0000000000 --- a/test/spec/crud/v1/write/replaceOne.json +++ /dev/null @@ -1,205 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "minServerVersion": "2.6", - "tests": [ - { - "description": "ReplaceOne when many documents match", - "operation": { - "name": "replaceOne", - "arguments": { - "filter": { - "_id": { - "$gt": 1 - } - }, - "replacement": { - "x": 111 - } - } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0 - } - } - }, - { - "description": "ReplaceOne when one document matches", - "operation": { - "name": "replaceOne", - "arguments": { - "filter": { - "_id": 1 - }, - "replacement": { - "_id": 1, - "x": 111 - } - } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 111 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "ReplaceOne when no documents match", - "operation": { - "name": "replaceOne", - "arguments": { - "filter": { - "_id": 4 - }, - "replacement": { - "_id": 4, - "x": 1 - } - } - }, - "outcome": { - "result": { - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "ReplaceOne with upsert when no documents match without an id specified", - "operation": { - "name": "replaceOne", - "arguments": { - "filter": { - "_id": 4 - }, - "replacement": { - "x": 1 - }, - "upsert": true - } - }, - "outcome": { - "result": { - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 1, - "upsertedId": 4 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 1 - } - ] - } - } - }, - { - "description": "ReplaceOne with upsert when no documents match with an id specified", - "operation": { - "name": "replaceOne", - "arguments": { - "filter": { - "_id": 4 - }, - "replacement": { - "_id": 4, - "x": 1 - }, - "upsert": true - } - }, - "outcome": { - "result": { - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 1, - "upsertedId": 4 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 1 - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/replaceOne.yml b/test/spec/crud/v1/write/replaceOne.yml deleted file mode 100644 index 4bccd36008..0000000000 --- a/test/spec/crud/v1/write/replaceOne.yml +++ /dev/null @@ -1,102 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} -minServerVersion: '2.6' - -tests: - - - description: "ReplaceOne when many documents match" - operation: - name: "replaceOne" - arguments: - filter: - _id: {$gt: 1} - replacement: {x: 111} - - outcome: - result: - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - # Can't verify collection data because we don't have a way of - # knowing which document gets updated. - - - description: "ReplaceOne when one document matches" - operation: - name: "replaceOne" - arguments: - filter: {_id: 1} - replacement: {_id: 1, x: 111} - - outcome: - result: - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - collection: - data: - - {_id: 1, x: 111} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - - description: "ReplaceOne when no documents match" - operation: - name: "replaceOne" - arguments: - filter: {_id: 4} - replacement: {_id: 4, x: 1} - - outcome: - result: - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 0 - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - - description: "ReplaceOne with upsert when no documents match without an id specified" - operation: - name: "replaceOne" - arguments: - filter: {_id: 4} - replacement: {x: 1} - upsert: true - - outcome: - result: - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 1 - upsertedId: 4 - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - {_id: 4, x: 1} - - - - description: "ReplaceOne with upsert when no documents match with an id specified" - operation: - name: "replaceOne" - arguments: - filter: {_id: 4} - replacement: {_id: 4, x: 1} - upsert: true - - outcome: - result: - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 1 - upsertedId: 4 - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - {_id: 4, x: 1} diff --git a/test/spec/crud/v1/write/updateMany-arrayFilters.json b/test/spec/crud/v1/write/updateMany-arrayFilters.json deleted file mode 100644 index ae4c123ea5..0000000000 --- a/test/spec/crud/v1/write/updateMany-arrayFilters.json +++ /dev/null @@ -1,185 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "y": [ - { - "b": 3 - }, - { - "b": 1 - } - ] - }, - { - "_id": 2, - "y": [ - { - "b": 0 - }, - { - "b": 1 - } - ] - } - ], - "minServerVersion": "3.5.6", - "tests": [ - { - "description": "UpdateMany when no documents match arrayFilters", - "operation": { - "name": "updateMany", - "arguments": { - "filter": {}, - "update": { - "$set": { - "y.$[i].b": 2 - } - }, - "arrayFilters": [ - { - "i.b": 4 - } - ] - } - }, - "outcome": { - "result": { - "matchedCount": 2, - "modifiedCount": 0, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "y": [ - { - "b": 3 - }, - { - "b": 1 - } - ] - }, - { - "_id": 2, - "y": [ - { - "b": 0 - }, - { - "b": 1 - } - ] - } - ] - } - } - }, - { - "description": "UpdateMany when one document matches arrayFilters", - "operation": { - "name": "updateMany", - "arguments": { - "filter": {}, - "update": { - "$set": { - "y.$[i].b": 2 - } - }, - "arrayFilters": [ - { - "i.b": 3 - } - ] - } - }, - "outcome": { - "result": { - "matchedCount": 2, - "modifiedCount": 1, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "y": [ - { - "b": 2 - }, - { - "b": 1 - } - ] - }, - { - "_id": 2, - "y": [ - { - "b": 0 - }, - { - "b": 1 - } - ] - } - ] - } - } - }, - { - "description": "UpdateMany when multiple documents match arrayFilters", - "operation": { - "name": "updateMany", - "arguments": { - "filter": {}, - "update": { - "$set": { - "y.$[i].b": 2 - } - }, - "arrayFilters": [ - { - "i.b": 1 - } - ] - } - }, - "outcome": { - "result": { - "matchedCount": 2, - "modifiedCount": 2, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "y": [ - { - "b": 3 - }, - { - "b": 2 - } - ] - }, - { - "_id": 2, - "y": [ - { - "b": 0 - }, - { - "b": 2 - } - ] - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/updateMany-arrayFilters.yml b/test/spec/crud/v1/write/updateMany-arrayFilters.yml deleted file mode 100644 index 3cfee56924..0000000000 --- a/test/spec/crud/v1/write/updateMany-arrayFilters.yml +++ /dev/null @@ -1,66 +0,0 @@ -data: - - {_id: 1, y: [{b: 3}, {b: 1}]} - - {_id: 2, y: [{b: 0}, {b: 1}]} -minServerVersion: '3.5.6' - -tests: - - - description: "UpdateMany when no documents match arrayFilters" - operation: - name: "updateMany" - arguments: - filter: {} - update: - $set: {"y.$[i].b": 2} - arrayFilters: - - {i.b: 4} - - outcome: - result: - matchedCount: 2 - modifiedCount: 0 - upsertedCount: 0 - collection: - data: - - {_id: 1, y: [{b: 3}, {b: 1}]} - - {_id: 2, y: [{b: 0}, {b: 1}]} - - - description: "UpdateMany when one document matches arrayFilters" - operation: - name: "updateMany" - arguments: - filter: {} - update: - $set: {"y.$[i].b": 2} - arrayFilters: - - {i.b: 3} - - outcome: - result: - matchedCount: 2 - modifiedCount: 1 - upsertedCount: 0 - collection: - data: - - {_id: 1, y: [{b: 2}, {b: 1}]} - - {_id: 2, y: [{b: 0}, {b: 1}]} - - - description: "UpdateMany when multiple documents match arrayFilters" - operation: - name: "updateMany" - arguments: - filter: {} - update: - $set: {"y.$[i].b": 2} - arrayFilters: - - {i.b: 1} - - outcome: - result: - matchedCount: 2 - modifiedCount: 2 - upsertedCount: 0 - collection: - data: - - {_id: 1, y: [{b: 3}, {b: 2}]} - - {_id: 2, y: [{b: 0}, {b: 2}]} diff --git a/test/spec/crud/v1/write/updateMany-collation.json b/test/spec/crud/v1/write/updateMany-collation.json deleted file mode 100644 index 8becfd806b..0000000000 --- a/test/spec/crud/v1/write/updateMany-collation.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": "ping" - }, - { - "_id": 3, - "x": "pINg" - } - ], - "minServerVersion": "3.4", - "serverless": "forbid", - "tests": [ - { - "description": "UpdateMany when many documents match with collation", - "operation": { - "name": "updateMany", - "arguments": { - "filter": { - "x": "ping" - }, - "update": { - "$set": { - "x": "pong" - } - }, - "collation": { - "locale": "en_US", - "strength": 2 - } - } - }, - "outcome": { - "result": { - "matchedCount": 2, - "modifiedCount": 2, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": "pong" - }, - { - "_id": 3, - "x": "pong" - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/updateMany-collation.yml b/test/spec/crud/v1/write/updateMany-collation.yml deleted file mode 100644 index b373789649..0000000000 --- a/test/spec/crud/v1/write/updateMany-collation.yml +++ /dev/null @@ -1,29 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 'ping'} - - {_id: 3, x: 'pINg'} -minServerVersion: '3.4' -serverless: 'forbid' - -tests: - - - description: "UpdateMany when many documents match with collation" - operation: - name: "updateMany" - arguments: - filter: - x: 'ping' - update: - $set: {x: 'pong'} - collation: { locale: 'en_US', strength: 2 } # https://www.mongodb.com/docs/manual/reference/collation/#collation-document - - outcome: - result: - matchedCount: 2 - modifiedCount: 2 - upsertedCount: 0 - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 'pong'} - - {_id: 3, x: 'pong'} diff --git a/test/spec/crud/v1/write/updateMany.json b/test/spec/crud/v1/write/updateMany.json deleted file mode 100644 index a3c339987d..0000000000 --- a/test/spec/crud/v1/write/updateMany.json +++ /dev/null @@ -1,183 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "minServerVersion": "2.6", - "tests": [ - { - "description": "UpdateMany when many documents match", - "operation": { - "name": "updateMany", - "arguments": { - "filter": { - "_id": { - "$gt": 1 - } - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - "outcome": { - "result": { - "matchedCount": 2, - "modifiedCount": 2, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 23 - }, - { - "_id": 3, - "x": 34 - } - ] - } - } - }, - { - "description": "UpdateMany when one document matches", - "operation": { - "name": "updateMany", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 12 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "UpdateMany when no documents match", - "operation": { - "name": "updateMany", - "arguments": { - "filter": { - "_id": 4 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - "outcome": { - "result": { - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "UpdateMany with upsert when no documents match", - "operation": { - "name": "updateMany", - "arguments": { - "filter": { - "_id": 4 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "upsert": true - } - }, - "outcome": { - "result": { - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 1, - "upsertedId": 4 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 1 - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/updateMany.yml b/test/spec/crud/v1/write/updateMany.yml deleted file mode 100644 index a0eb62ba83..0000000000 --- a/test/spec/crud/v1/write/updateMany.yml +++ /dev/null @@ -1,87 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} -minServerVersion: '2.6' - -tests: - - - description: "UpdateMany when many documents match" - operation: - name: "updateMany" - arguments: - filter: - _id: {$gt: 1} - update: - $inc: {x: 1} - - outcome: - result: - matchedCount: 2 - modifiedCount: 2 - upsertedCount: 0 - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 23} - - {_id: 3, x: 34} - - - description: "UpdateMany when one document matches" - operation: - name: "updateMany" - arguments: - filter: {_id: 1} - update: - $inc: {x: 1} - - outcome: - result: - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - collection: - data: - - {_id: 1, x: 12} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - - description: "UpdateMany when no documents match" - operation: - name: "updateMany" - arguments: - filter: {_id: 4} - update: - $inc: {x: 1} - - outcome: - result: - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 0 - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - - description: "UpdateMany with upsert when no documents match" - operation: - name: "updateMany" - arguments: - filter: {_id: 4} - update: - $inc: {x: 1} - upsert: true - - outcome: - result: - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 1 - upsertedId: 4 - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - {_id: 4, x: 1} diff --git a/test/spec/crud/v1/write/updateOne-arrayFilters.yml b/test/spec/crud/v1/write/updateOne-arrayFilters.yml deleted file mode 100644 index a35e15c687..0000000000 --- a/test/spec/crud/v1/write/updateOne-arrayFilters.yml +++ /dev/null @@ -1,114 +0,0 @@ -data: - - {_id: 1, y: [{b: 3}, {b: 1}]} - - {_id: 2, y: [{b: 0}, {b: 1}]} - - {_id: 3, y: [{b: 5, c: [{d: 2}, {d: 1}] }]} -minServerVersion: '3.5.6' - -tests: - - - description: "UpdateOne when no document matches arrayFilters" - operation: - name: "updateOne" - arguments: - filter: {} - update: - $set: {"y.$[i].b": 2} - arrayFilters: - - {i.b: 4} - - outcome: - result: - matchedCount: 1 - modifiedCount: 0 - upsertedCount: 0 - collection: - data: - - {_id: 1, y: [{b: 3}, {b: 1}]} - - {_id: 2, y: [{b: 0}, {b: 1}]} - - {_id: 3, y: [{b: 5, c: [{d: 2}, {d: 1}] }]} - - - description: "UpdateOne when one document matches arrayFilters" - operation: - name: "updateOne" - arguments: - filter: {} - update: - $set: {"y.$[i].b": 2} - arrayFilters: - - {i.b: 3} - - outcome: - result: - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - collection: - data: - - {_id: 1, y: [{b: 2}, {b: 1}]} - - {_id: 2, y: [{b: 0}, {b: 1}]} - - {_id: 3, y: [{b: 5, c: [{d: 2}, {d: 1}] }]} - - - description: "UpdateOne when multiple documents match arrayFilters" - operation: - name: "updateOne" - arguments: - filter: {} - update: - $set: {"y.$[i].b": 2} - arrayFilters: - - {i.b: 1} - - outcome: - result: - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - collection: - data: - - {_id: 1, y: [{b: 3}, {b: 2}]} - - {_id: 2, y: [{b: 0}, {b: 1}]} - - {_id: 3, y: [{b: 5, c: [{d: 2}, {d: 1}] }]} - - - description: "UpdateOne when no documents match multiple arrayFilters" - operation: - name: "updateOne" - arguments: - filter: {_id: 3} - update: - $set: {"y.$[i].c.$[j].d": 0} - arrayFilters: - - {i.b: 5} - - {j.d: 3} - - outcome: - result: - matchedCount: 1 - modifiedCount: 0 - upsertedCount: 0 - collection: - data: - - {_id: 1, y: [{b: 3}, {b: 1}]} - - {_id: 2, y: [{b: 0}, {b: 1}]} - - {_id: 3, y: [{b: 5, c: [{d: 2}, {d: 1}] }]} - - - description: "UpdateOne when one document matches multiple arrayFilters" - operation: - name: "updateOne" - arguments: - filter: {_id: 3} - update: - $set: {"y.$[i].c.$[j].d": 0} - arrayFilters: - - {i.b: 5} - - {j.d: 1} - - outcome: - result: - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - collection: - data: - - {_id: 1, y: [{b: 3}, {b: 1}]} - - {_id: 2, y: [{b: 0}, {b: 1}]} - - {_id: 3, y: [{b: 5, c: [{d: 2}, {d: 0}] }]} diff --git a/test/spec/crud/v1/write/updateOne-collation.json b/test/spec/crud/v1/write/updateOne-collation.json deleted file mode 100644 index 3afdb83e0f..0000000000 --- a/test/spec/crud/v1/write/updateOne-collation.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": "ping" - } - ], - "minServerVersion": "3.4", - "serverless": "forbid", - "tests": [ - { - "description": "UpdateOne when one document matches with collation", - "operation": { - "name": "updateOne", - "arguments": { - "filter": { - "x": "PING" - }, - "update": { - "$set": { - "x": "pong" - } - }, - "collation": { - "locale": "en_US", - "strength": 2 - } - } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": "pong" - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/updateOne-collation.yml b/test/spec/crud/v1/write/updateOne-collation.yml deleted file mode 100644 index c20087176e..0000000000 --- a/test/spec/crud/v1/write/updateOne-collation.yml +++ /dev/null @@ -1,26 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 'ping'} -minServerVersion: '3.4' -serverless: 'forbid' - -tests: - - - description: "UpdateOne when one document matches with collation" - operation: - name: "updateOne" - arguments: - filter: {x: 'PING'} - update: - $set: {x: 'pong'} - collation: { locale: 'en_US', strength: 2} # https://www.mongodb.com/docs/manual/reference/collation/#collation-document - - outcome: - result: - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 'pong'} diff --git a/test/spec/crud/v1/write/updateOne.json b/test/spec/crud/v1/write/updateOne.json deleted file mode 100644 index 76d2086bdb..0000000000 --- a/test/spec/crud/v1/write/updateOne.json +++ /dev/null @@ -1,167 +0,0 @@ -{ - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "minServerVersion": "2.6", - "tests": [ - { - "description": "UpdateOne when many documents match", - "operation": { - "name": "updateOne", - "arguments": { - "filter": { - "_id": { - "$gt": 1 - } - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0 - } - } - }, - { - "description": "UpdateOne when one document matches", - "operation": { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 12 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "UpdateOne when no documents match", - "operation": { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 4 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - "outcome": { - "result": { - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "UpdateOne with upsert when no documents match", - "operation": { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 4 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "upsert": true - } - }, - "outcome": { - "result": { - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 1, - "upsertedId": 4 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 1 - } - ] - } - } - } - ] -} diff --git a/test/spec/crud/v1/write/updateOne.yml b/test/spec/crud/v1/write/updateOne.yml deleted file mode 100644 index 223532feac..0000000000 --- a/test/spec/crud/v1/write/updateOne.yml +++ /dev/null @@ -1,84 +0,0 @@ -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} -minServerVersion: '2.6' - -tests: - - - description: "UpdateOne when many documents match" - operation: - name: "updateOne" - arguments: - filter: - _id: {$gt: 1} - update: - $inc: {x: 1} - - outcome: - result: - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - # Can't verify collection data because we don't have a way of - # knowing which document gets updated. - - - description: "UpdateOne when one document matches" - operation: - name: "updateOne" - arguments: - filter: {_id: 1} - update: - $inc: {x: 1} - - outcome: - result: - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - collection: - data: - - {_id: 1, x: 12} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - - description: "UpdateOne when no documents match" - operation: - name: "updateOne" - arguments: - filter: {_id: 4} - update: - $inc: {x: 1} - - outcome: - result: - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 0 - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - - description: "UpdateOne with upsert when no documents match" - operation: - name: "updateOne" - arguments: - filter: {_id: 4} - update: - $inc: {x: 1} - upsert: true - - outcome: - result: - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 1 - upsertedId: 4 - collection: - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - {_id: 4, x: 1} diff --git a/test/spec/gridfs/README.md b/test/spec/gridfs/README.md new file mode 100644 index 0000000000..8285b2e306 --- /dev/null +++ b/test/spec/gridfs/README.md @@ -0,0 +1,28 @@ +# GridFS Tests + +______________________________________________________________________ + +## Introduction + +The YAML and JSON files in this directory are platform-independent tests meant to exercise a driver's implementation of +GridFS. These tests utilize the [Unified Test Format](../../unified-test-format/unified-test-format.md). + +## Conventions for Expressing Binary Data + +The unified test format allows binary stream data to be expressed and matched with `$$hexBytes` (for uploads) and +`$$matchesHexBytes` (for downloads), respectively; however, those operators are not supported in all contexts, such as +`insertData` and `outcome`. When binary data must be expressed as a base64-encoded string +([Extended JSON](../../extended-json.md) for a BSON binary type), the test SHOULD include a comment noting the +equivalent value in hexadecimal for human-readability. For example: + +```yaml +data: { $binary: { base64: "ESIzRA==", subType: "00" } } # hex 11223344 +``` + +Creating the base64-encoded string for a sequence of hexadecimal bytes is left as an exercise to the developer. Consider +the following PHP one-liner: + +```shell-session +$ php -r 'echo base64_encode(hex2bin('11223344')), "\n";' +ESIzRA== +``` diff --git a/test/spec/gridfs/delete.json b/test/spec/gridfs/delete.json new file mode 100644 index 0000000000..7a4ec27f88 --- /dev/null +++ b/test/spec/gridfs/delete.json @@ -0,0 +1,799 @@ +{ + "description": "gridfs-delete", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "gridfs-tests" + } + }, + { + "bucket": { + "id": "bucket0", + "database": "database0" + } + }, + { + "collection": { + "id": "bucket0_files_collection", + "database": "database0", + "collectionName": "fs.files" + } + }, + { + "collection": { + "id": "bucket0_chunks_collection", + "database": "database0", + "collectionName": "fs.chunks" + } + } + ], + "initialData": [ + { + "collectionName": "fs.files", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "length": 0, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "d41d8cd98f00b204e9800998ecf8427e", + "filename": "length-0", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000002" + }, + "length": 0, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "d41d8cd98f00b204e9800998ecf8427e", + "filename": "length-0-with-empty-chunk", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000003" + }, + "length": 2, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "c700ed4fdb1d27055aa3faa2c2432283", + "filename": "length-2", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000004" + }, + "length": 8, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "dd254cdc958e53abaa67da9f797125f5", + "filename": "length-8", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + } + ] + }, + { + "collectionName": "fs.chunks", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "files_id": { + "$oid": "000000000000000000000002" + }, + "n": 0, + "data": { + "$binary": { + "base64": "", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000002" + }, + "files_id": { + "$oid": "000000000000000000000003" + }, + "n": 0, + "data": { + "$binary": { + "base64": "ESI=", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000003" + }, + "files_id": { + "$oid": "000000000000000000000004" + }, + "n": 0, + "data": { + "$binary": { + "base64": "ESIzRA==", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000004" + }, + "files_id": { + "$oid": "000000000000000000000004" + }, + "n": 1, + "data": { + "$binary": { + "base64": "VWZ3iA==", + "subType": "00" + } + } + } + ] + } + ], + "tests": [ + { + "description": "delete when length is 0", + "operations": [ + { + "name": "delete", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000001" + } + } + } + ], + "outcome": [ + { + "collectionName": "fs.files", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000002" + }, + "length": 0, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "d41d8cd98f00b204e9800998ecf8427e", + "filename": "length-0-with-empty-chunk", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000003" + }, + "length": 2, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "c700ed4fdb1d27055aa3faa2c2432283", + "filename": "length-2", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000004" + }, + "length": 8, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "dd254cdc958e53abaa67da9f797125f5", + "filename": "length-8", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + } + ] + }, + { + "collectionName": "fs.chunks", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "files_id": { + "$oid": "000000000000000000000002" + }, + "n": 0, + "data": { + "$binary": { + "base64": "", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000002" + }, + "files_id": { + "$oid": "000000000000000000000003" + }, + "n": 0, + "data": { + "$binary": { + "base64": "ESI=", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000003" + }, + "files_id": { + "$oid": "000000000000000000000004" + }, + "n": 0, + "data": { + "$binary": { + "base64": "ESIzRA==", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000004" + }, + "files_id": { + "$oid": "000000000000000000000004" + }, + "n": 1, + "data": { + "$binary": { + "base64": "VWZ3iA==", + "subType": "00" + } + } + } + ] + } + ] + }, + { + "description": "delete when length is 0 and there is one extra empty chunk", + "operations": [ + { + "name": "delete", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000002" + } + } + } + ], + "outcome": [ + { + "collectionName": "fs.files", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "length": 0, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "d41d8cd98f00b204e9800998ecf8427e", + "filename": "length-0", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000003" + }, + "length": 2, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "c700ed4fdb1d27055aa3faa2c2432283", + "filename": "length-2", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000004" + }, + "length": 8, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "dd254cdc958e53abaa67da9f797125f5", + "filename": "length-8", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + } + ] + }, + { + "collectionName": "fs.chunks", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000002" + }, + "files_id": { + "$oid": "000000000000000000000003" + }, + "n": 0, + "data": { + "$binary": { + "base64": "ESI=", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000003" + }, + "files_id": { + "$oid": "000000000000000000000004" + }, + "n": 0, + "data": { + "$binary": { + "base64": "ESIzRA==", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000004" + }, + "files_id": { + "$oid": "000000000000000000000004" + }, + "n": 1, + "data": { + "$binary": { + "base64": "VWZ3iA==", + "subType": "00" + } + } + } + ] + } + ] + }, + { + "description": "delete when length is 8", + "operations": [ + { + "name": "delete", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000004" + } + } + } + ], + "outcome": [ + { + "collectionName": "fs.files", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "length": 0, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "d41d8cd98f00b204e9800998ecf8427e", + "filename": "length-0", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000002" + }, + "length": 0, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "d41d8cd98f00b204e9800998ecf8427e", + "filename": "length-0-with-empty-chunk", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000003" + }, + "length": 2, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "c700ed4fdb1d27055aa3faa2c2432283", + "filename": "length-2", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + } + ] + }, + { + "collectionName": "fs.chunks", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "files_id": { + "$oid": "000000000000000000000002" + }, + "n": 0, + "data": { + "$binary": { + "base64": "", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000002" + }, + "files_id": { + "$oid": "000000000000000000000003" + }, + "n": 0, + "data": { + "$binary": { + "base64": "ESI=", + "subType": "00" + } + } + } + ] + } + ] + }, + { + "description": "delete when files entry does not exist", + "operations": [ + { + "name": "delete", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000000" + } + }, + "expectError": { + "isError": true + } + } + ], + "outcome": [ + { + "collectionName": "fs.files", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "length": 0, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "d41d8cd98f00b204e9800998ecf8427e", + "filename": "length-0", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000002" + }, + "length": 0, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "d41d8cd98f00b204e9800998ecf8427e", + "filename": "length-0-with-empty-chunk", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000003" + }, + "length": 2, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "c700ed4fdb1d27055aa3faa2c2432283", + "filename": "length-2", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000004" + }, + "length": 8, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "dd254cdc958e53abaa67da9f797125f5", + "filename": "length-8", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + } + ] + }, + { + "collectionName": "fs.chunks", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "files_id": { + "$oid": "000000000000000000000002" + }, + "n": 0, + "data": { + "$binary": { + "base64": "", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000002" + }, + "files_id": { + "$oid": "000000000000000000000003" + }, + "n": 0, + "data": { + "$binary": { + "base64": "ESI=", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000003" + }, + "files_id": { + "$oid": "000000000000000000000004" + }, + "n": 0, + "data": { + "$binary": { + "base64": "ESIzRA==", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000004" + }, + "files_id": { + "$oid": "000000000000000000000004" + }, + "n": 1, + "data": { + "$binary": { + "base64": "VWZ3iA==", + "subType": "00" + } + } + } + ] + } + ] + }, + { + "description": "delete when files entry does not exist and there are orphaned chunks", + "operations": [ + { + "name": "deleteOne", + "object": "bucket0_files_collection", + "arguments": { + "filter": { + "_id": { + "$oid": "000000000000000000000004" + } + } + }, + "expectResult": { + "deletedCount": 1 + } + }, + { + "name": "delete", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000004" + } + }, + "expectError": { + "isError": true + } + } + ], + "outcome": [ + { + "collectionName": "fs.files", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "length": 0, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "d41d8cd98f00b204e9800998ecf8427e", + "filename": "length-0", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000002" + }, + "length": 0, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "d41d8cd98f00b204e9800998ecf8427e", + "filename": "length-0-with-empty-chunk", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000003" + }, + "length": 2, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "c700ed4fdb1d27055aa3faa2c2432283", + "filename": "length-2", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + } + ] + }, + { + "collectionName": "fs.chunks", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "files_id": { + "$oid": "000000000000000000000002" + }, + "n": 0, + "data": { + "$binary": { + "base64": "", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000002" + }, + "files_id": { + "$oid": "000000000000000000000003" + }, + "n": 0, + "data": { + "$binary": { + "base64": "ESI=", + "subType": "00" + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/gridfs/delete.yml b/test/spec/gridfs/delete.yml new file mode 100644 index 0000000000..b300cad1bc --- /dev/null +++ b/test/spec/gridfs/delete.yml @@ -0,0 +1,198 @@ +description: "gridfs-delete" + +schemaVersion: "1.0" + +createEntities: + - client: + id: &client0 client0 + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name gridfs-tests + - bucket: + id: &bucket0 bucket0 + database: *database0 + - collection: + id: &bucket0_files_collection bucket0_files_collection + database: *database0 + collectionName: &bucket0_files_collectionName fs.files + - collection: + id: &bucket0_chunks_collection bucket0_chunks_collection + database: *database0 + collectionName: &bucket0_chunks_collectionName fs.chunks + +initialData: + - collectionName: *bucket0_files_collectionName + databaseName: *database0Name + documents: + - &file1 + _id: { "$oid": "000000000000000000000001" } + length: 0 + chunkSize: 4 + uploadDate: { "$date": "1970-01-01T00:00:00.000Z" } + md5: "d41d8cd98f00b204e9800998ecf8427e" + filename: "length-0" + contentType: "application/octet-stream" + aliases: [] + metadata: {} + - &file2 + _id: { "$oid": "000000000000000000000002" } + length: 0 + chunkSize: 4 + uploadDate: { "$date": "1970-01-01T00:00:00.000Z" } + md5: "d41d8cd98f00b204e9800998ecf8427e" + filename: "length-0-with-empty-chunk" + contentType: "application/octet-stream" + aliases: [] + metadata: {} + - &file3 + _id: { "$oid": "000000000000000000000003" } + length: 2 + chunkSize: 4 + uploadDate: { "$date": "1970-01-01T00:00:00.000Z" } + md5: "c700ed4fdb1d27055aa3faa2c2432283" + filename: "length-2" + contentType: "application/octet-stream" + aliases: [] + metadata: {} + - &file4 + _id: { "$oid": "000000000000000000000004" } + length: 8 + chunkSize: 4 + uploadDate: { "$date": "1970-01-01T00:00:00.000Z" } + md5: "dd254cdc958e53abaa67da9f797125f5" + filename: "length-8" + contentType: "application/octet-stream" + aliases: [] + metadata: {} + - collectionName: *bucket0_chunks_collectionName + databaseName: *database0Name + documents: + - &file2_chunk0 + _id: { "$oid": "000000000000000000000001" } + files_id: { "$oid": "000000000000000000000002" } + n: 0 + data: { "$binary": { "base64": "", "subType": "00" } } + - &file3_chunk0 + _id: { "$oid": "000000000000000000000002" } + files_id: { "$oid": "000000000000000000000003" } + n: 0 + data: { "$binary": { "base64": "ESI=", "subType": "00" } } # hex: 1122 + - &file4_chunk0 + _id: { "$oid": "000000000000000000000003" } + files_id: { "$oid": "000000000000000000000004" } + n: 0 + data: { "$binary": { "base64": "ESIzRA==", "subType": "00" } } # hex: 11223344 + - &file4_chunk1 + _id: { "$oid": "000000000000000000000004" } + files_id: { "$oid": "000000000000000000000004" } + n: 1 + data: { "$binary": { "base64": "VWZ3iA==", "subType": "00" } } # hex: 55667788 + +tests: + - description: "delete when length is 0" + operations: + - name: delete + object: *bucket0 + arguments: + id: { $oid: "000000000000000000000001" } + outcome: + - collectionName: *bucket0_files_collectionName + databaseName: *database0Name + documents: + - *file2 + - *file3 + - *file4 + - collectionName: *bucket0_chunks_collectionName + databaseName: *database0Name + documents: + - *file2_chunk0 + - *file3_chunk0 + - *file4_chunk0 + - *file4_chunk1 + - description: "delete when length is 0 and there is one extra empty chunk" + operations: + - name: delete + object: *bucket0 + arguments: + id: { $oid: "000000000000000000000002" } + outcome: + - collectionName: *bucket0_files_collectionName + databaseName: *database0Name + documents: + - *file1 + - *file3 + - *file4 + - collectionName: *bucket0_chunks_collectionName + databaseName: *database0Name + documents: + - *file3_chunk0 + - *file4_chunk0 + - *file4_chunk1 + - description: "delete when length is 8" + operations: + - name: delete + object: *bucket0 + arguments: + id: { $oid: "000000000000000000000004" } + outcome: + - collectionName: *bucket0_files_collectionName + databaseName: *database0Name + documents: + - *file1 + - *file2 + - *file3 + - collectionName: *bucket0_chunks_collectionName + databaseName: *database0Name + documents: + - *file2_chunk0 + - *file3_chunk0 + - description: "delete when files entry does not exist" + operations: + - name: delete + object: *bucket0 + arguments: + id: { $oid: "000000000000000000000000" } + expectError: { isError: true } # FileNotFound + outcome: + - collectionName: *bucket0_files_collectionName + databaseName: *database0Name + documents: + - *file1 + - *file2 + - *file3 + - *file4 + - collectionName: *bucket0_chunks_collectionName + databaseName: *database0Name + documents: + - *file2_chunk0 + - *file3_chunk0 + - *file4_chunk0 + - *file4_chunk1 + - description: "delete when files entry does not exist and there are orphaned chunks" + operations: + - name: deleteOne + object: *bucket0_files_collection + arguments: + filter: + _id: { $oid: "000000000000000000000004" } + expectResult: + deletedCount: 1 + - name: delete + object: *bucket0 + arguments: + id: { $oid: "000000000000000000000004" } + expectError: { isError: true } # FileNotFound + outcome: + - collectionName: *bucket0_files_collectionName + databaseName: *database0Name + documents: + - *file1 + - *file2 + - *file3 + # Orphaned chunks are still deleted even if fs.files + - collectionName: *bucket0_chunks_collectionName + databaseName: *database0Name + documents: + - *file2_chunk0 + - *file3_chunk0 diff --git a/test/spec/gridfs/download.json b/test/spec/gridfs/download.json new file mode 100644 index 0000000000..48d3246218 --- /dev/null +++ b/test/spec/gridfs/download.json @@ -0,0 +1,558 @@ +{ + "description": "gridfs-download", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "gridfs-tests" + } + }, + { + "bucket": { + "id": "bucket0", + "database": "database0" + } + }, + { + "collection": { + "id": "bucket0_files_collection", + "database": "database0", + "collectionName": "fs.files" + } + }, + { + "collection": { + "id": "bucket0_chunks_collection", + "database": "database0", + "collectionName": "fs.chunks" + } + } + ], + "initialData": [ + { + "collectionName": "fs.files", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "length": 0, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "d41d8cd98f00b204e9800998ecf8427e", + "filename": "length-0", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000002" + }, + "length": 0, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "d41d8cd98f00b204e9800998ecf8427e", + "filename": "length-0-with-empty-chunk", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000003" + }, + "length": 2, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "c700ed4fdb1d27055aa3faa2c2432283", + "filename": "length-2", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000004" + }, + "length": 8, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "dd254cdc958e53abaa67da9f797125f5", + "filename": "length-8", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000005" + }, + "length": 10, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "57d83cd477bfb1ccd975ab33d827a92b", + "filename": "length-10", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000006" + }, + "length": 2, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "c700ed4fdb1d27055aa3faa2c2432283", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + } + ] + }, + { + "collectionName": "fs.chunks", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "files_id": { + "$oid": "000000000000000000000002" + }, + "n": 0, + "data": { + "$binary": { + "base64": "", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000002" + }, + "files_id": { + "$oid": "000000000000000000000003" + }, + "n": 0, + "data": { + "$binary": { + "base64": "ESI=", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000003" + }, + "files_id": { + "$oid": "000000000000000000000004" + }, + "n": 0, + "data": { + "$binary": { + "base64": "ESIzRA==", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000004" + }, + "files_id": { + "$oid": "000000000000000000000004" + }, + "n": 1, + "data": { + "$binary": { + "base64": "VWZ3iA==", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000005" + }, + "files_id": { + "$oid": "000000000000000000000005" + }, + "n": 0, + "data": { + "$binary": { + "base64": "ESIzRA==", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000006" + }, + "files_id": { + "$oid": "000000000000000000000005" + }, + "n": 1, + "data": { + "$binary": { + "base64": "VWZ3iA==", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000007" + }, + "files_id": { + "$oid": "000000000000000000000005" + }, + "n": 2, + "data": { + "$binary": { + "base64": "mao=", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000008" + }, + "files_id": { + "$oid": "000000000000000000000006" + }, + "n": 0, + "data": { + "$binary": { + "base64": "ESI=", + "subType": "00" + } + } + } + ] + } + ], + "tests": [ + { + "description": "download when length is zero", + "operations": [ + { + "name": "download", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000001" + } + }, + "expectResult": { + "$$matchesHexBytes": "" + } + } + ] + }, + { + "description": "download when length is zero and there is one empty chunk", + "operations": [ + { + "name": "download", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000002" + } + }, + "expectResult": { + "$$matchesHexBytes": "" + } + } + ] + }, + { + "description": "download when there is one chunk", + "operations": [ + { + "name": "download", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000003" + } + }, + "expectResult": { + "$$matchesHexBytes": "1122" + } + } + ] + }, + { + "description": "download when there are two chunks", + "operations": [ + { + "name": "download", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000004" + } + }, + "expectResult": { + "$$matchesHexBytes": "1122334455667788" + } + } + ] + }, + { + "description": "download when there are three chunks", + "operations": [ + { + "name": "download", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000005" + } + }, + "expectResult": { + "$$matchesHexBytes": "112233445566778899aa" + } + } + ] + }, + { + "description": "download when files entry does not exist", + "operations": [ + { + "name": "download", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000000" + } + }, + "expectError": { + "isError": true + } + } + ] + }, + { + "description": "download when an intermediate chunk is missing", + "operations": [ + { + "name": "deleteOne", + "object": "bucket0_chunks_collection", + "arguments": { + "filter": { + "files_id": { + "$oid": "000000000000000000000005" + }, + "n": 1 + } + }, + "expectResult": { + "deletedCount": 1 + } + }, + { + "name": "download", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000005" + } + }, + "expectError": { + "isError": true + } + } + ] + }, + { + "description": "download when final chunk is missing", + "operations": [ + { + "name": "deleteOne", + "object": "bucket0_chunks_collection", + "arguments": { + "filter": { + "files_id": { + "$oid": "000000000000000000000005" + }, + "n": 2 + } + }, + "expectResult": { + "deletedCount": 1 + } + }, + { + "name": "download", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000005" + } + }, + "expectError": { + "isError": true + } + } + ] + }, + { + "description": "download when an intermediate chunk is the wrong size", + "operations": [ + { + "name": "bulkWrite", + "object": "bucket0_chunks_collection", + "arguments": { + "requests": [ + { + "updateOne": { + "filter": { + "files_id": { + "$oid": "000000000000000000000005" + }, + "n": 1 + }, + "update": { + "$set": { + "data": { + "$binary": { + "base64": "VWZ3", + "subType": "00" + } + } + } + } + } + }, + { + "updateOne": { + "filter": { + "files_id": { + "$oid": "000000000000000000000005" + }, + "n": 2 + }, + "update": { + "$set": { + "data": { + "$binary": { + "base64": "iJmq", + "subType": "00" + } + } + } + } + } + } + ] + }, + "expectResult": { + "matchedCount": 2, + "modifiedCount": 2 + } + }, + { + "name": "download", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000005" + } + }, + "expectError": { + "isError": true + } + } + ] + }, + { + "description": "download when final chunk is the wrong size", + "operations": [ + { + "name": "updateOne", + "object": "bucket0_chunks_collection", + "arguments": { + "filter": { + "files_id": { + "$oid": "000000000000000000000005" + }, + "n": 2 + }, + "update": { + "$set": { + "data": { + "$binary": { + "base64": "mQ==", + "subType": "00" + } + } + } + } + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1 + } + }, + { + "name": "download", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000005" + } + }, + "expectError": { + "isError": true + } + } + ] + }, + { + "description": "download legacy file with no name", + "operations": [ + { + "name": "download", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000006" + } + }, + "expectResult": { + "$$matchesHexBytes": "1122" + } + } + ] + } + ] +} diff --git a/test/spec/gridfs/download.yml b/test/spec/gridfs/download.yml new file mode 100644 index 0000000000..3da5ee950f --- /dev/null +++ b/test/spec/gridfs/download.yml @@ -0,0 +1,241 @@ +description: "gridfs-download" + +schemaVersion: "1.0" + +createEntities: + - client: + id: &client0 client0 + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name gridfs-tests + - bucket: + id: &bucket0 bucket0 + database: *database0 + - collection: + id: &bucket0_files_collection bucket0_files_collection + database: *database0 + collectionName: &bucket0_files_collectionName fs.files + - collection: + id: &bucket0_chunks_collection bucket0_chunks_collection + database: *database0 + collectionName: &bucket0_chunks_collectionName fs.chunks + +initialData: + - collectionName: *bucket0_files_collectionName + databaseName: *database0Name + documents: + - _id: { "$oid": "000000000000000000000001" } + length: 0 + chunkSize: 4 + uploadDate: { "$date": "1970-01-01T00:00:00.000Z" } + md5: "d41d8cd98f00b204e9800998ecf8427e" + filename: "length-0" + contentType: "application/octet-stream" + aliases: [] + metadata: {} + - _id: { "$oid": "000000000000000000000002" } + length: 0 + chunkSize: 4 + uploadDate: { "$date": "1970-01-01T00:00:00.000Z" } + md5: "d41d8cd98f00b204e9800998ecf8427e" + filename: "length-0-with-empty-chunk" + contentType: "application/octet-stream" + aliases: [] + metadata: {} + - _id: { "$oid": "000000000000000000000003" } + length: 2 + chunkSize: 4 + uploadDate: { "$date": "1970-01-01T00:00:00.000Z" } + md5: "c700ed4fdb1d27055aa3faa2c2432283" + filename: "length-2" + contentType: "application/octet-stream" + aliases: [] + metadata: {} + - _id: { "$oid": "000000000000000000000004" } + length: 8 + chunkSize: 4 + uploadDate: { "$date": "1970-01-01T00:00:00.000Z" } + md5: "dd254cdc958e53abaa67da9f797125f5" + filename: "length-8" + contentType: "application/octet-stream" + aliases: [] + metadata: {} + - _id: { "$oid": "000000000000000000000005" } + length: 10 + chunkSize: 4 + uploadDate: { "$date": "1970-01-01T00:00:00.000Z" } + md5: "57d83cd477bfb1ccd975ab33d827a92b" + filename: "length-10" + contentType: "application/octet-stream" + aliases: [] + metadata: {} + - _id: { "$oid": "000000000000000000000006" } + length: 2 + chunkSize: 4 + uploadDate: { "$date": "1970-01-01T00:00:00.000Z" } + md5: "c700ed4fdb1d27055aa3faa2c2432283" + # filename is intentionally omitted + contentType: "application/octet-stream" + aliases: [] + metadata: {} + - collectionName: *bucket0_chunks_collectionName + databaseName: *database0Name + documents: + - _id: { "$oid": "000000000000000000000001" } + files_id: { "$oid": "000000000000000000000002" } + n: 0 + data: { "$binary": { "base64": "", "subType": "00" } } + - _id: { "$oid": "000000000000000000000002" } + files_id: { "$oid": "000000000000000000000003" } + n: 0 + data: { "$binary": { "base64": "ESI=", "subType": "00" } } # hex: 1122 + - _id: { "$oid": "000000000000000000000003" } + files_id: { "$oid": "000000000000000000000004" } + n: 0 + data: { "$binary": { "base64": "ESIzRA==", "subType": "00" } } # hex: 11223344 + - _id: { "$oid": "000000000000000000000004" } + files_id: { "$oid": "000000000000000000000004" } + n: 1 + data: { "$binary": { "base64": "VWZ3iA==", "subType": "00" } } # hex: 55667788 + - _id: { "$oid": "000000000000000000000005" } + files_id: { "$oid": "000000000000000000000005" } + n: 0 + data: { "$binary": { "base64": "ESIzRA==", "subType": "00" } } # hex: 11223344 + - _id: { "$oid": "000000000000000000000006" } + files_id: { "$oid": "000000000000000000000005" } + n: 1 + data: { "$binary": { "base64": "VWZ3iA==", "subType": "00" } } # hex: 55667788 + - _id: { "$oid": "000000000000000000000007" } + files_id: { "$oid": "000000000000000000000005" } + n: 2 + data: { "$binary" : { "base64": "mao=", "subType" : "00" } } # hex: 99aa + - _id: { "$oid": "000000000000000000000008" } + files_id: { "$oid": "000000000000000000000006" } + n: 0 + data: { "$binary": { "base64": "ESI=", "subType": "00" } } # hex: 1122 + +tests: + - description: "download when length is zero" + operations: + - name: download + object: *bucket0 + arguments: + id: { $oid: "000000000000000000000001" } + expectResult: { $$matchesHexBytes: "" } + - description: "download when length is zero and there is one empty chunk" + operations: + - name: download + object: *bucket0 + arguments: + id: { $oid: "000000000000000000000002" } + expectResult: { $$matchesHexBytes: "" } + - description: "download when there is one chunk" + operations: + - name: download + object: *bucket0 + arguments: + id: { $oid: "000000000000000000000003" } + expectResult: { $$matchesHexBytes: "1122" } + - description: "download when there are two chunks" + operations: + - name: download + object: *bucket0 + arguments: + id: { $oid: "000000000000000000000004" } + expectResult: { $$matchesHexBytes: "1122334455667788" } + - description: "download when there are three chunks" + operations: + - name: download + object: *bucket0 + arguments: + id: { $oid: "000000000000000000000005" } + expectResult: { $$matchesHexBytes: "112233445566778899aa" } + - description: "download when files entry does not exist" + operations: + - name: download + object: *bucket0 + arguments: + id: { $oid: "000000000000000000000000" } + expectError: { isError: true } # FileNotFound + - description: "download when an intermediate chunk is missing" + operations: + - name: deleteOne + object: *bucket0_chunks_collection + arguments: + filter: + files_id: { $oid: "000000000000000000000005" } + n: 1 + expectResult: + deletedCount: 1 + - name: download + object: *bucket0 + arguments: + id: { $oid: "000000000000000000000005" } + expectError: { isError: true } # ChunkIsMissing + - description: "download when final chunk is missing" + operations: + - name: deleteOne + object: *bucket0_chunks_collection + arguments: + filter: + files_id: { $oid: "000000000000000000000005" } + n: 2 + expectResult: + deletedCount: 1 + - name: download + object: *bucket0 + arguments: + id: { $oid: "000000000000000000000005" } + expectError: { isError: true } # ChunkIsMissing + - description: "download when an intermediate chunk is the wrong size" + operations: + - name: bulkWrite + object: *bucket0_chunks_collection + arguments: + requests: + - updateOne: + filter: + files_id: { $oid: "000000000000000000000005" } + n: 1 + update: + $set: { data: { "$binary": { "base64": "VWZ3", "subType": "00" } } } # hex: 556677 + - updateOne: + filter: + files_id: { $oid: "000000000000000000000005" } + n: 2 + update: + $set: { data: { "$binary": { "base64": "iJmq", "subType": "00" } } } # hex: 8899aa + expectResult: + matchedCount: 2 + modifiedCount: 2 + - name: download + object: *bucket0 + arguments: + id: { $oid: "000000000000000000000005" } + expectError: { isError: true } # ChunkIsWrongSize + - description: "download when final chunk is the wrong size" + operations: + - name: updateOne + object: *bucket0_chunks_collection + arguments: + filter: + files_id: { $oid: "000000000000000000000005" } + n: 2 + update: + $set: { data: { "$binary": { "base64": "mQ==", "subType": "00" } } } # hex: 99 + expectResult: + matchedCount: 1 + modifiedCount: 1 + - name: download + object: *bucket0 + arguments: + id: { $oid: "000000000000000000000005" } + expectError: { isError: true } # ChunkIsWrongSize + - description: "download legacy file with no name" + operations: + - name: download + object: *bucket0 + arguments: + id: { $oid: "000000000000000000000006" } + expectResult: { $$matchesHexBytes: "1122" } diff --git a/test/spec/gridfs/downloadByName.json b/test/spec/gridfs/downloadByName.json new file mode 100644 index 0000000000..cd44663957 --- /dev/null +++ b/test/spec/gridfs/downloadByName.json @@ -0,0 +1,330 @@ +{ + "description": "gridfs-downloadByName", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "gridfs-tests" + } + }, + { + "bucket": { + "id": "bucket0", + "database": "database0" + } + }, + { + "collection": { + "id": "bucket0_files_collection", + "database": "database0", + "collectionName": "fs.files" + } + }, + { + "collection": { + "id": "bucket0_chunks_collection", + "database": "database0", + "collectionName": "fs.chunks" + } + } + ], + "initialData": [ + { + "collectionName": "fs.files", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "length": 1, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "md5": "47ed733b8d10be225eceba344d533586", + "filename": "abc", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000002" + }, + "length": 1, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-02T00:00:00.000Z" + }, + "md5": "b15835f133ff2e27c7cb28117bfae8f4", + "filename": "abc", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000003" + }, + "length": 1, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-03T00:00:00.000Z" + }, + "md5": "eccbc87e4b5ce2fe28308fd9f2a7baf3", + "filename": "abc", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000004" + }, + "length": 1, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-04T00:00:00.000Z" + }, + "md5": "f623e75af30e62bbd73d6df5b50bb7b5", + "filename": "abc", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000005" + }, + "length": 1, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-05T00:00:00.000Z" + }, + "md5": "4c614360da93c0a041b22e537de151eb", + "filename": "abc", + "contentType": "application/octet-stream", + "aliases": [], + "metadata": {} + } + ] + }, + { + "collectionName": "fs.chunks", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "files_id": { + "$oid": "000000000000000000000001" + }, + "n": 0, + "data": { + "$binary": { + "base64": "EQ==", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000002" + }, + "files_id": { + "$oid": "000000000000000000000002" + }, + "n": 0, + "data": { + "$binary": { + "base64": "Ig==", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000003" + }, + "files_id": { + "$oid": "000000000000000000000003" + }, + "n": 0, + "data": { + "$binary": { + "base64": "Mw==", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000004" + }, + "files_id": { + "$oid": "000000000000000000000004" + }, + "n": 0, + "data": { + "$binary": { + "base64": "RA==", + "subType": "00" + } + } + }, + { + "_id": { + "$oid": "000000000000000000000005" + }, + "files_id": { + "$oid": "000000000000000000000005" + }, + "n": 0, + "data": { + "$binary": { + "base64": "VQ==", + "subType": "00" + } + } + } + ] + } + ], + "tests": [ + { + "description": "downloadByName defaults to latest revision (-1)", + "operations": [ + { + "name": "downloadByName", + "object": "bucket0", + "arguments": { + "filename": "abc" + }, + "expectResult": { + "$$matchesHexBytes": "55" + } + } + ] + }, + { + "description": "downloadByName when revision is 0", + "operations": [ + { + "name": "downloadByName", + "object": "bucket0", + "arguments": { + "filename": "abc", + "revision": 0 + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ] + }, + { + "description": "downloadByName when revision is 1", + "operations": [ + { + "name": "downloadByName", + "object": "bucket0", + "arguments": { + "filename": "abc", + "revision": 1 + }, + "expectResult": { + "$$matchesHexBytes": "22" + } + } + ] + }, + { + "description": "downloadByName when revision is 2", + "operations": [ + { + "name": "downloadByName", + "object": "bucket0", + "arguments": { + "filename": "abc", + "revision": 2 + }, + "expectResult": { + "$$matchesHexBytes": "33" + } + } + ] + }, + { + "description": "downloadByName when revision is -2", + "operations": [ + { + "name": "downloadByName", + "object": "bucket0", + "arguments": { + "filename": "abc", + "revision": -2 + }, + "expectResult": { + "$$matchesHexBytes": "44" + } + } + ] + }, + { + "description": "downloadByName when revision is -1", + "operations": [ + { + "name": "downloadByName", + "object": "bucket0", + "arguments": { + "filename": "abc", + "revision": -1 + }, + "expectResult": { + "$$matchesHexBytes": "55" + } + } + ] + }, + { + "description": "downloadByName when files entry does not exist", + "operations": [ + { + "name": "downloadByName", + "object": "bucket0", + "arguments": { + "filename": "xyz" + }, + "expectError": { + "isError": true + } + } + ] + }, + { + "description": "downloadByName when revision does not exist", + "operations": [ + { + "name": "downloadByName", + "object": "bucket0", + "arguments": { + "filename": "abc", + "revision": 999 + }, + "expectError": { + "isError": true + } + } + ] + } + ] +} diff --git a/test/spec/gridfs/downloadByName.yml b/test/spec/gridfs/downloadByName.yml new file mode 100644 index 0000000000..6dfc602b66 --- /dev/null +++ b/test/spec/gridfs/downloadByName.yml @@ -0,0 +1,159 @@ +description: "gridfs-downloadByName" + +schemaVersion: "1.0" + +createEntities: + - client: + id: &client0 client0 + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name gridfs-tests + - bucket: + id: &bucket0 bucket0 + database: *database0 + - collection: + id: &bucket0_files_collection bucket0_files_collection + database: *database0 + collectionName: &bucket0_files_collectionName fs.files + - collection: + id: &bucket0_chunks_collection bucket0_chunks_collection + database: *database0 + collectionName: &bucket0_chunks_collectionName fs.chunks + +initialData: + - collectionName: *bucket0_files_collectionName + databaseName: *database0Name + documents: + - _id: { $oid: "000000000000000000000001" } + length: 1 + chunkSize: 4 + uploadDate: { $date: "1970-01-01T00:00:00.000Z" } + md5: "47ed733b8d10be225eceba344d533586" + filename: "abc" + contentType: "application/octet-stream" + aliases: [] + metadata: {} + - _id: { $oid: "000000000000000000000002" } + length: 1 + chunkSize: 4 + uploadDate: { $date: "1970-01-02T00:00:00.000Z" } + md5: "b15835f133ff2e27c7cb28117bfae8f4" + filename: "abc" + contentType: "application/octet-stream" + aliases: [] + metadata: {} + - _id: { $oid: "000000000000000000000003" } + length: 1 + chunkSize: 4 + uploadDate: { $date: "1970-01-03T00:00:00.000Z" } + md5: "eccbc87e4b5ce2fe28308fd9f2a7baf3" + filename: "abc" + contentType: "application/octet-stream" + aliases: [] + metadata: {} + - _id: { $oid: "000000000000000000000004" } + length: 1 + chunkSize: 4 + uploadDate: { $date: "1970-01-04T00:00:00.000Z" } + md5: "f623e75af30e62bbd73d6df5b50bb7b5" + filename: "abc" + contentType: "application/octet-stream" + aliases: [] + metadata: {} + - _id: { $oid: "000000000000000000000005" } + length: 1 + chunkSize: 4 + uploadDate: { $date: "1970-01-05T00:00:00.000Z" } + md5: "4c614360da93c0a041b22e537de151eb" + filename: "abc" + contentType: "application/octet-stream" + aliases: [] + metadata: {} + - collectionName: *bucket0_chunks_collectionName + databaseName: *database0Name + documents: + - _id: { $oid: "000000000000000000000001" } + files_id: { $oid: "000000000000000000000001" } + n: 0 + data: { "$binary": { "base64": "EQ==", "subType": "00" } } # hex: 11 + - _id: { $oid: "000000000000000000000002" } + files_id: { $oid: "000000000000000000000002" } + n: 0 + data: { "$binary": { "base64": "Ig==", "subType": "00" } } # hex: 22 + - _id: { $oid: "000000000000000000000003" } + files_id: { $oid: "000000000000000000000003" } + n: 0 + data: { "$binary": { "base64": "Mw==", "subType": "00" } } # hex: 33 + - _id: { $oid: "000000000000000000000004" } + files_id: { $oid: "000000000000000000000004" } + n: 0 + data: { "$binary": { "base64": "RA==", "subType": "00" } } # hex: 44 + - _id: { $oid: "000000000000000000000005" } + files_id: { $oid: "000000000000000000000005" } + n: 0 + data: { "$binary": { "base64": "VQ==", "subType": "00" } } # hex: 55 + +tests: + - description: "downloadByName defaults to latest revision (-1)" + operations: + - name: downloadByName + object: *bucket0 + arguments: + filename: "abc" + expectResult: { $$matchesHexBytes: "55" } + - description: "downloadByName when revision is 0" + operations: + - name: downloadByName + object: *bucket0 + arguments: + filename: "abc" + revision: 0 + expectResult: { $$matchesHexBytes: "11" } + - description: "downloadByName when revision is 1" + operations: + - name: downloadByName + object: *bucket0 + arguments: + filename: "abc" + revision: 1 + expectResult: { $$matchesHexBytes: "22" } + - description: "downloadByName when revision is 2" + operations: + - name: downloadByName + object: *bucket0 + arguments: + filename: "abc" + revision: 2 + expectResult: { $$matchesHexBytes: "33" } + - description: "downloadByName when revision is -2" + operations: + - name: downloadByName + object: *bucket0 + arguments: + filename: "abc" + revision: -2 + expectResult: { $$matchesHexBytes: "44" } + - description: "downloadByName when revision is -1" + operations: + - name: downloadByName + object: *bucket0 + arguments: + filename: "abc" + revision: -1 + expectResult: { $$matchesHexBytes: "55" } + - description: "downloadByName when files entry does not exist" + operations: + - name: downloadByName + object: *bucket0 + arguments: + filename: "xyz" + expectError: { isError: true } # FileNotFound + - description: "downloadByName when revision does not exist" + operations: + - name: downloadByName + object: *bucket0 + arguments: + filename: "abc" + revision: 999 + expectError: { isError: true } # RevisionNotFound diff --git a/test/spec/gridfs/gridfs-download.json b/test/spec/gridfs/gridfs-download.json deleted file mode 100644 index 19b78f65fa..0000000000 --- a/test/spec/gridfs/gridfs-download.json +++ /dev/null @@ -1,564 +0,0 @@ -{ - "data": { - "files": [ - { - "_id": { - "$oid": "000000000000000000000001" - }, - "length": 0, - "chunkSize": 4, - "uploadDate": { - "$date": "1970-01-01T00:00:00.000Z" - }, - "md5": "d41d8cd98f00b204e9800998ecf8427e", - "filename": "length-0", - "contentType": "application/octet-stream", - "aliases": [ - - ], - "metadata": { - } - }, - { - "_id": { - "$oid": "000000000000000000000002" - }, - "length": 0, - "chunkSize": 4, - "uploadDate": { - "$date": "1970-01-01T00:00:00.000Z" - }, - "md5": "d41d8cd98f00b204e9800998ecf8427e", - "filename": "length-0-with-empty-chunk", - "contentType": "application/octet-stream", - "aliases": [ - - ], - "metadata": { - } - }, - { - "_id": { - "$oid": "000000000000000000000003" - }, - "length": 2, - "chunkSize": 4, - "uploadDate": { - "$date": "1970-01-01T00:00:00.000Z" - }, - "md5": "c700ed4fdb1d27055aa3faa2c2432283", - "filename": "length-2", - "contentType": "application/octet-stream", - "aliases": [ - - ], - "metadata": { - } - }, - { - "_id": { - "$oid": "000000000000000000000004" - }, - "length": 8, - "chunkSize": 4, - "uploadDate": { - "$date": "1970-01-01T00:00:00.000Z" - }, - "md5": "dd254cdc958e53abaa67da9f797125f5", - "filename": "length-8", - "contentType": "application/octet-stream", - "aliases": [ - - ], - "metadata": { - } - }, - { - "_id": { - "$oid": "000000000000000000000005" - }, - "length": 10, - "chunkSize": 4, - "uploadDate": { - "$date": "1970-01-01T00:00:00.000Z" - }, - "md5": "57d83cd477bfb1ccd975ab33d827a92b", - "filename": "length-10", - "contentType": "application/octet-stream", - "aliases": [ - - ], - "metadata": { - } - }, - { - "_id": { - "$oid": "000000000000000000000006" - }, - "length": 12, - "chunkSize": 4, - "uploadDate": { - "$date": "1970-01-01T00:00:00.000Z" - }, - "md5": "6289ac1db331d1c7677a4b7e123178f9", - "filename": "length-12-with-empty-chunk", - "contentType": "application/octet-stream", - "aliases": [ - - ], - "metadata": { - } - } - ], - "chunks": [ - { - "_id": { - "$oid": "000000000000000000000001" - }, - "files_id": { - "$oid": "000000000000000000000002" - }, - "n": 0, - "data": { - "$hex": "" - } - }, - { - "_id": { - "$oid": "000000000000000000000002" - }, - "files_id": { - "$oid": "000000000000000000000003" - }, - "n": 0, - "data": { - "$hex": "1122" - } - }, - { - "_id": { - "$oid": "000000000000000000000003" - }, - "files_id": { - "$oid": "000000000000000000000004" - }, - "n": 0, - "data": { - "$hex": "11223344" - } - }, - { - "_id": { - "$oid": "000000000000000000000004" - }, - "files_id": { - "$oid": "000000000000000000000004" - }, - "n": 1, - "data": { - "$hex": "55667788" - } - }, - { - "_id": { - "$oid": "000000000000000000000005" - }, - "files_id": { - "$oid": "000000000000000000000005" - }, - "n": 0, - "data": { - "$hex": "11223344" - } - }, - { - "_id": { - "$oid": "000000000000000000000006" - }, - "files_id": { - "$oid": "000000000000000000000005" - }, - "n": 1, - "data": { - "$hex": "55667788" - } - }, - { - "_id": { - "$oid": "000000000000000000000007" - }, - "files_id": { - "$oid": "000000000000000000000005" - }, - "n": 2, - "data": { - "$hex": "99aa" - } - }, - { - "_id": { - "$oid": "000000000000000000000008" - }, - "files_id": { - "$oid": "000000000000000000000006" - }, - "n": 0, - "data": { - "$hex": "11223344" - } - }, - { - "_id": { - "$oid": "000000000000000000000009" - }, - "files_id": { - "$oid": "000000000000000000000006" - }, - "n": 1, - "data": { - "$hex": "55667788" - } - }, - { - "_id": { - "$oid": "000000000000000000000010" - }, - "files_id": { - "$oid": "000000000000000000000006" - }, - "n": 2, - "data": { - "$hex": "99aabbcc" - } - }, - { - "_id": { - "$oid": "000000000000000000000011" - }, - "files_id": { - "$oid": "000000000000000000000006" - }, - "n": 3, - "data": { - "$hex": "" - } - } - ] - }, - "tests": [ - { - "description": "Download when length is zero", - "act": { - "operation": "download", - "arguments": { - "id": { - "$oid": "000000000000000000000001" - }, - "options": { - } - } - }, - "assert": { - "result": { - "$hex": "" - } - } - }, - { - "description": "Download when length is zero and there is one empty chunk", - "act": { - "operation": "download", - "arguments": { - "id": { - "$oid": "000000000000000000000002" - }, - "options": { - } - } - }, - "assert": { - "result": { - "$hex": "" - } - } - }, - { - "description": "Download when there is one chunk", - "act": { - "operation": "download", - "arguments": { - "id": { - "$oid": "000000000000000000000003" - }, - "options": { - } - } - }, - "assert": { - "result": { - "$hex": "1122" - } - } - }, - { - "description": "Download when there are two chunks", - "act": { - "operation": "download", - "arguments": { - "id": { - "$oid": "000000000000000000000004" - }, - "options": { - } - } - }, - "assert": { - "result": { - "$hex": "1122334455667788" - } - } - }, - { - "description": "Download when there are three chunks", - "act": { - "operation": "download", - "arguments": { - "id": { - "$oid": "000000000000000000000005" - }, - "options": { - } - } - }, - "assert": { - "result": { - "$hex": "112233445566778899aa" - } - } - }, - { - "description": "Download when there are three chunks and one extra empty chunk at the end", - "act": { - "operation": "download", - "arguments": { - "id": { - "$oid": "000000000000000000000006" - }, - "options": { - } - } - }, - "assert": { - "result": { - "$hex": "112233445566778899aabbcc" - } - } - }, - { - "description": "Download when files entry does not exist", - "act": { - "operation": "download", - "arguments": { - "id": { - "$oid": "000000000000000000000000" - }, - "options": { - } - } - }, - "assert": { - "error": "FileNotFound" - } - }, - { - "description": "Download when an intermediate chunk is missing", - "arrange": { - "data": [ - { - "delete": "fs.chunks", - "deletes": [ - { - "q": { - "files_id": { - "$oid": "000000000000000000000005" - }, - "n": 1 - }, - "limit": 1 - } - ] - } - ] - }, - "act": { - "operation": "download", - "arguments": { - "id": { - "$oid": "000000000000000000000005" - } - } - }, - "assert": { - "error": "ChunkIsMissing" - } - }, - { - "description": "Download when final chunk is missing", - "arrange": { - "data": [ - { - "delete": "fs.chunks", - "deletes": [ - { - "q": { - "files_id": { - "$oid": "000000000000000000000005" - }, - "n": 1 - }, - "limit": 1 - } - ] - } - ] - }, - "act": { - "operation": "download", - "arguments": { - "id": { - "$oid": "000000000000000000000005" - } - } - }, - "assert": { - "error": "ChunkIsMissing" - } - }, - { - "description": "Download when there is an extra chunk", - "arrange": { - "data": [ - { - "insert": "fs.chunks", - "documents": [ - { - "_id": { - "$oid": "000000000000000000000012" - }, - "files_id": { - "$oid": "000000000000000000000004" - }, - "n": 2, - "data": { - "$hex": "99" - } - } - ] - } - ] - }, - "act": { - "operation": "download", - "arguments": { - "id": { - "$oid": "000000000000000000000004" - } - } - }, - "assert": { - "error": "ExtraChunk" - } - }, - { - "description": "Download when an intermediate chunk is the wrong size", - "arrange": { - "data": [ - { - "update": "fs.chunks", - "updates": [ - { - "q": { - "files_id": { - "$oid": "000000000000000000000005" - }, - "n": 1 - }, - "u": { - "$set": { - "data": { - "$hex": "556677" - } - } - } - }, - { - "q": { - "files_id": { - "$oid": "000000000000000000000005" - }, - "n": 2 - }, - "u": { - "$set": { - "data": { - "$hex": "8899aa" - } - } - } - } - ] - } - ] - }, - "act": { - "operation": "download", - "arguments": { - "id": { - "$oid": "000000000000000000000005" - } - } - }, - "assert": { - "error": "ChunkIsWrongSize" - } - }, - { - "description": "Download when final chunk is the wrong size", - "arrange": { - "data": [ - { - "update": "fs.chunks", - "updates": [ - { - "q": { - "files_id": { - "$oid": "000000000000000000000005" - }, - "n": 2 - }, - "u": { - "$set": { - "data": { - "$hex": "99" - } - } - } - } - ] - } - ] - }, - "act": { - "operation": "download", - "arguments": { - "id": { - "$oid": "000000000000000000000005" - } - } - }, - "assert": { - "error": "ChunkIsWrongSize" - } - } - ] -} diff --git a/test/spec/gridfs/gridfs-upload.json b/test/spec/gridfs/gridfs-upload.json deleted file mode 100644 index f581acd11c..0000000000 --- a/test/spec/gridfs/gridfs-upload.json +++ /dev/null @@ -1,391 +0,0 @@ -{ - "data": { - "files": [ - - ], - "chunks": [ - - ] - }, - "tests": [ - { - "description": "Upload when length is 0", - "act": { - "operation": "upload", - "arguments": { - "filename": "filename", - "source": { - "$hex": "" - }, - "options": { - "chunkSizeBytes": 4 - } - } - }, - "assert": { - "result": "&result", - "data": [ - { - "insert": "expected.files", - "documents": [ - { - "_id": "*result", - "length": 0, - "chunkSize": 4, - "uploadDate": "*actual", - "md5": "d41d8cd98f00b204e9800998ecf8427e", - "filename": "filename" - } - ] - } - ] - } - }, - { - "description": "Upload when length is 1", - "act": { - "operation": "upload", - "arguments": { - "filename": "filename", - "source": { - "$hex": "11" - }, - "options": { - "chunkSizeBytes": 4 - } - } - }, - "assert": { - "result": "&result", - "data": [ - { - "insert": "expected.files", - "documents": [ - { - "_id": "*result", - "length": 1, - "chunkSize": 4, - "uploadDate": "*actual", - "md5": "47ed733b8d10be225eceba344d533586", - "filename": "filename" - } - ] - }, - { - "insert": "expected.chunks", - "documents": [ - { - "_id": "*actual", - "files_id": "*result", - "n": 0, - "data": { - "$hex": "11" - } - } - ] - } - ] - } - }, - { - "description": "Upload when length is 3", - "act": { - "operation": "upload", - "arguments": { - "filename": "filename", - "source": { - "$hex": "112233" - }, - "options": { - "chunkSizeBytes": 4 - } - } - }, - "assert": { - "result": "&result", - "data": [ - { - "insert": "expected.files", - "documents": [ - { - "_id": "*result", - "length": 3, - "chunkSize": 4, - "uploadDate": "*actual", - "md5": "bafae3a174ab91fc70db7a6aa50f4f52", - "filename": "filename" - } - ] - }, - { - "insert": "expected.chunks", - "documents": [ - { - "_id": "*actual", - "files_id": "*result", - "n": 0, - "data": { - "$hex": "112233" - } - } - ] - } - ] - } - }, - { - "description": "Upload when length is 4", - "act": { - "operation": "upload", - "arguments": { - "filename": "filename", - "source": { - "$hex": "11223344" - }, - "options": { - "chunkSizeBytes": 4 - } - } - }, - "assert": { - "result": "&result", - "data": [ - { - "insert": "expected.files", - "documents": [ - { - "_id": "*result", - "length": 4, - "chunkSize": 4, - "uploadDate": "*actual", - "md5": "7e7c77cff5705d1f7574a25ef6662117", - "filename": "filename" - } - ] - }, - { - "insert": "expected.chunks", - "documents": [ - { - "_id": "*actual", - "files_id": "*result", - "n": 0, - "data": { - "$hex": "11223344" - } - } - ] - } - ] - } - }, - { - "description": "Upload when length is 5", - "act": { - "operation": "upload", - "arguments": { - "filename": "filename", - "source": { - "$hex": "1122334455" - }, - "options": { - "chunkSizeBytes": 4 - } - } - }, - "assert": { - "result": "&result", - "data": [ - { - "insert": "expected.files", - "documents": [ - { - "_id": "*result", - "length": 5, - "chunkSize": 4, - "uploadDate": "*actual", - "md5": "283d4fea5dded59cf837d3047328f5af", - "filename": "filename" - } - ] - }, - { - "insert": "expected.chunks", - "documents": [ - { - "_id": "*actual", - "files_id": "*result", - "n": 0, - "data": { - "$hex": "11223344" - } - }, - { - "_id": "*actual", - "files_id": "*result", - "n": 1, - "data": { - "$hex": "55" - } - } - ] - } - ] - } - }, - { - "description": "Upload when length is 8", - "act": { - "operation": "upload", - "arguments": { - "filename": "filename", - "source": { - "$hex": "1122334455667788" - }, - "options": { - "chunkSizeBytes": 4 - } - } - }, - "assert": { - "result": "&result", - "data": [ - { - "insert": "expected.files", - "documents": [ - { - "_id": "*result", - "length": 8, - "chunkSize": 4, - "uploadDate": "*actual", - "md5": "dd254cdc958e53abaa67da9f797125f5", - "filename": "filename" - } - ] - }, - { - "insert": "expected.chunks", - "documents": [ - { - "_id": "*actual", - "files_id": "*result", - "n": 0, - "data": { - "$hex": "11223344" - } - }, - { - "_id": "*actual", - "files_id": "*result", - "n": 1, - "data": { - "$hex": "55667788" - } - } - ] - } - ] - } - }, - { - "description": "Upload when contentType is provided", - "act": { - "operation": "upload", - "arguments": { - "filename": "filename", - "source": { - "$hex": "11" - }, - "options": { - "chunkSizeBytes": 4, - "contentType": "image/jpeg" - } - } - }, - "assert": { - "result": "&result", - "data": [ - { - "insert": "expected.files", - "documents": [ - { - "_id": "*result", - "length": 1, - "chunkSize": 4, - "uploadDate": "*actual", - "md5": "47ed733b8d10be225eceba344d533586", - "filename": "filename", - "contentType": "image/jpeg" - } - ] - }, - { - "insert": "expected.chunks", - "documents": [ - { - "_id": "*actual", - "files_id": "*result", - "n": 0, - "data": { - "$hex": "11" - } - } - ] - } - ] - } - }, - { - "description": "Upload when metadata is provided", - "act": { - "operation": "upload", - "arguments": { - "filename": "filename", - "source": { - "$hex": "11" - }, - "options": { - "chunkSizeBytes": 4, - "metadata": { - "x": 1 - } - } - } - }, - "assert": { - "result": "&result", - "data": [ - { - "insert": "expected.files", - "documents": [ - { - "_id": "*result", - "length": 1, - "chunkSize": 4, - "uploadDate": "*actual", - "md5": "47ed733b8d10be225eceba344d533586", - "filename": "filename", - "metadata": { - "x": 1 - } - } - ] - }, - { - "insert": "expected.chunks", - "documents": [ - { - "_id": "*actual", - "files_id": "*result", - "n": 0, - "data": { - "$hex": "11" - } - } - ] - } - ] - } - } - ] -} diff --git a/test/spec/gridfs/upload-disableMD5.json b/test/spec/gridfs/upload-disableMD5.json new file mode 100644 index 0000000000..d5a9d6f4ab --- /dev/null +++ b/test/spec/gridfs/upload-disableMD5.json @@ -0,0 +1,172 @@ +{ + "description": "gridfs-upload-disableMD5", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "gridfs-tests" + } + }, + { + "bucket": { + "id": "bucket0", + "database": "database0" + } + }, + { + "collection": { + "id": "bucket0_files_collection", + "database": "database0", + "collectionName": "fs.files" + } + }, + { + "collection": { + "id": "bucket0_chunks_collection", + "database": "database0", + "collectionName": "fs.chunks" + } + } + ], + "initialData": [ + { + "collectionName": "fs.files", + "databaseName": "gridfs-tests", + "documents": [] + }, + { + "collectionName": "fs.chunks", + "databaseName": "gridfs-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "upload when length is 0 sans MD5", + "operations": [ + { + "name": "upload", + "object": "bucket0", + "arguments": { + "filename": "filename", + "source": { + "$$hexBytes": "" + }, + "chunkSizeBytes": 4, + "disableMD5": true + }, + "expectResult": { + "$$type": "objectId" + }, + "saveResultAsEntity": "uploadedObjectId" + }, + { + "name": "find", + "object": "bucket0_files_collection", + "arguments": { + "filter": {} + }, + "expectResult": [ + { + "_id": { + "$$matchesEntity": "uploadedObjectId" + }, + "length": 0, + "chunkSize": 4, + "uploadDate": { + "$$type": "date" + }, + "md5": { + "$$exists": false + }, + "filename": "filename" + } + ] + }, + { + "name": "find", + "object": "bucket0_chunks_collection", + "arguments": { + "filter": {} + }, + "expectResult": [] + } + ] + }, + { + "description": "upload when length is 1 sans MD5", + "operations": [ + { + "name": "upload", + "object": "bucket0", + "arguments": { + "filename": "filename", + "source": { + "$$hexBytes": "11" + }, + "chunkSizeBytes": 4, + "disableMD5": true + }, + "expectResult": { + "$$type": "objectId" + }, + "saveResultAsEntity": "uploadedObjectId" + }, + { + "name": "find", + "object": "bucket0_files_collection", + "arguments": { + "filter": {} + }, + "expectResult": [ + { + "_id": { + "$$matchesEntity": "uploadedObjectId" + }, + "length": 1, + "chunkSize": 4, + "uploadDate": { + "$$type": "date" + }, + "md5": { + "$$exists": false + }, + "filename": "filename" + } + ] + }, + { + "name": "find", + "object": "bucket0_chunks_collection", + "arguments": { + "filter": {} + }, + "expectResult": [ + { + "_id": { + "$$type": "objectId" + }, + "files_id": { + "$$matchesEntity": "uploadedObjectId" + }, + "n": 0, + "data": { + "$binary": { + "base64": "EQ==", + "subType": "00" + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/gridfs/upload-disableMD5.yml b/test/spec/gridfs/upload-disableMD5.yml new file mode 100644 index 0000000000..4f77f5a1a2 --- /dev/null +++ b/test/spec/gridfs/upload-disableMD5.yml @@ -0,0 +1,92 @@ +description: "gridfs-upload-disableMD5" + +schemaVersion: "1.0" + +createEntities: + - client: + id: &client0 client0 + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name gridfs-tests + - bucket: + id: &bucket0 bucket0 + database: *database0 + - collection: + id: &bucket0_files_collection bucket0_files_collection + database: *database0 + collectionName: &bucket0_files_collectionName fs.files + - collection: + id: &bucket0_chunks_collection bucket0_chunks_collection + database: *database0 + collectionName: &bucket0_chunks_collectionName fs.chunks + +initialData: + - collectionName: *bucket0_files_collectionName + databaseName: *database0Name + documents: [] + - collectionName: *bucket0_chunks_collectionName + databaseName: *database0Name + documents: [] + +# Note: these tests utilize the transitional "disableMD5" option. Drivers that +# do not support the option should skip this file. +tests: + - description: "upload when length is 0 sans MD5" + operations: + - name: upload + object: *bucket0 + arguments: + filename: "filename" + source: { $$hexBytes: "" } + chunkSizeBytes: 4 + disableMD5: true + expectResult: { $$type: objectId } + saveResultAsEntity: &uploadedObjectId uploadedObjectId + - name: find + object: *bucket0_files_collection + arguments: + filter: {} + expectResult: + - _id: { $$matchesEntity: *uploadedObjectId } + length: 0 + chunkSize: 4 + uploadDate: { $$type: date } + md5: { $$exists: false } + filename: filename + - name: find + object: *bucket0_chunks_collection + arguments: + filter: {} + expectResult: [] + - description: "upload when length is 1 sans MD5" + operations: + - name: upload + object: *bucket0 + arguments: + filename: "filename" + source: { $$hexBytes: "11" } + chunkSizeBytes: 4 + disableMD5: true + expectResult: { $$type: objectId } + saveResultAsEntity: *uploadedObjectId + - name: find + object: *bucket0_files_collection + arguments: + filter: {} + expectResult: + - _id: { $$matchesEntity: *uploadedObjectId } + length: 1 + chunkSize: 4 + uploadDate: { $$type: date } + md5: { $$exists: false } + filename: filename + - name: find + object: *bucket0_chunks_collection + arguments: + filter: {} + expectResult: + - _id: { $$type: objectId } + files_id: { $$matchesEntity: *uploadedObjectId } + n: 0 + data: { $binary: { base64: "EQ==", subType: "00" } } # hex 11 diff --git a/test/spec/gridfs/upload.json b/test/spec/gridfs/upload.json new file mode 100644 index 0000000000..97e18d2bc2 --- /dev/null +++ b/test/spec/gridfs/upload.json @@ -0,0 +1,616 @@ +{ + "description": "gridfs-upload", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "gridfs-tests" + } + }, + { + "bucket": { + "id": "bucket0", + "database": "database0" + } + }, + { + "collection": { + "id": "bucket0_files_collection", + "database": "database0", + "collectionName": "fs.files" + } + }, + { + "collection": { + "id": "bucket0_chunks_collection", + "database": "database0", + "collectionName": "fs.chunks" + } + } + ], + "initialData": [ + { + "collectionName": "fs.files", + "databaseName": "gridfs-tests", + "documents": [] + }, + { + "collectionName": "fs.chunks", + "databaseName": "gridfs-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "upload when length is 0", + "operations": [ + { + "name": "upload", + "object": "bucket0", + "arguments": { + "filename": "filename", + "source": { + "$$hexBytes": "" + }, + "chunkSizeBytes": 4 + }, + "expectResult": { + "$$type": "objectId" + }, + "saveResultAsEntity": "uploadedObjectId" + }, + { + "name": "find", + "object": "bucket0_files_collection", + "arguments": { + "filter": {} + }, + "expectResult": [ + { + "_id": { + "$$matchesEntity": "uploadedObjectId" + }, + "length": 0, + "chunkSize": 4, + "uploadDate": { + "$$type": "date" + }, + "md5": { + "$$unsetOrMatches": "d41d8cd98f00b204e9800998ecf8427e" + }, + "filename": "filename" + } + ] + }, + { + "name": "find", + "object": "bucket0_chunks_collection", + "arguments": { + "filter": {} + }, + "expectResult": [] + } + ] + }, + { + "description": "upload when length is 1", + "operations": [ + { + "name": "upload", + "object": "bucket0", + "arguments": { + "filename": "filename", + "source": { + "$$hexBytes": "11" + }, + "chunkSizeBytes": 4 + }, + "expectResult": { + "$$type": "objectId" + }, + "saveResultAsEntity": "uploadedObjectId" + }, + { + "name": "find", + "object": "bucket0_files_collection", + "arguments": { + "filter": {} + }, + "expectResult": [ + { + "_id": { + "$$matchesEntity": "uploadedObjectId" + }, + "length": 1, + "chunkSize": 4, + "uploadDate": { + "$$type": "date" + }, + "md5": { + "$$unsetOrMatches": "47ed733b8d10be225eceba344d533586" + }, + "filename": "filename" + } + ] + }, + { + "name": "find", + "object": "bucket0_chunks_collection", + "arguments": { + "filter": {} + }, + "expectResult": [ + { + "_id": { + "$$type": "objectId" + }, + "files_id": { + "$$matchesEntity": "uploadedObjectId" + }, + "n": 0, + "data": { + "$binary": { + "base64": "EQ==", + "subType": "00" + } + } + } + ] + } + ] + }, + { + "description": "upload when length is 3", + "operations": [ + { + "name": "upload", + "object": "bucket0", + "arguments": { + "filename": "filename", + "source": { + "$$hexBytes": "112233" + }, + "chunkSizeBytes": 4 + }, + "expectResult": { + "$$type": "objectId" + }, + "saveResultAsEntity": "uploadedObjectId" + }, + { + "name": "find", + "object": "bucket0_files_collection", + "arguments": { + "filter": {} + }, + "expectResult": [ + { + "_id": { + "$$matchesEntity": "uploadedObjectId" + }, + "length": 3, + "chunkSize": 4, + "uploadDate": { + "$$type": "date" + }, + "md5": { + "$$unsetOrMatches": "bafae3a174ab91fc70db7a6aa50f4f52" + }, + "filename": "filename" + } + ] + }, + { + "name": "find", + "object": "bucket0_chunks_collection", + "arguments": { + "filter": {} + }, + "expectResult": [ + { + "_id": { + "$$type": "objectId" + }, + "files_id": { + "$$matchesEntity": "uploadedObjectId" + }, + "n": 0, + "data": { + "$binary": { + "base64": "ESIz", + "subType": "00" + } + } + } + ] + } + ] + }, + { + "description": "upload when length is 4", + "operations": [ + { + "name": "upload", + "object": "bucket0", + "arguments": { + "filename": "filename", + "source": { + "$$hexBytes": "11223344" + }, + "chunkSizeBytes": 4 + }, + "expectResult": { + "$$type": "objectId" + }, + "saveResultAsEntity": "uploadedObjectId" + }, + { + "name": "find", + "object": "bucket0_files_collection", + "arguments": { + "filter": {} + }, + "expectResult": [ + { + "_id": { + "$$matchesEntity": "uploadedObjectId" + }, + "length": 4, + "chunkSize": 4, + "uploadDate": { + "$$type": "date" + }, + "md5": { + "$$unsetOrMatches": "7e7c77cff5705d1f7574a25ef6662117" + }, + "filename": "filename" + } + ] + }, + { + "name": "find", + "object": "bucket0_chunks_collection", + "arguments": { + "filter": {} + }, + "expectResult": [ + { + "_id": { + "$$type": "objectId" + }, + "files_id": { + "$$matchesEntity": "uploadedObjectId" + }, + "n": 0, + "data": { + "$binary": { + "base64": "ESIzRA==", + "subType": "00" + } + } + } + ] + } + ] + }, + { + "description": "upload when length is 5", + "operations": [ + { + "name": "upload", + "object": "bucket0", + "arguments": { + "filename": "filename", + "source": { + "$$hexBytes": "1122334455" + }, + "chunkSizeBytes": 4 + }, + "expectResult": { + "$$type": "objectId" + }, + "saveResultAsEntity": "uploadedObjectId" + }, + { + "name": "find", + "object": "bucket0_files_collection", + "arguments": { + "filter": {} + }, + "expectResult": [ + { + "_id": { + "$$matchesEntity": "uploadedObjectId" + }, + "length": 5, + "chunkSize": 4, + "uploadDate": { + "$$type": "date" + }, + "md5": { + "$$unsetOrMatches": "283d4fea5dded59cf837d3047328f5af" + }, + "filename": "filename" + } + ] + }, + { + "name": "find", + "object": "bucket0_chunks_collection", + "arguments": { + "filter": {}, + "sort": { + "n": 1 + } + }, + "expectResult": [ + { + "_id": { + "$$type": "objectId" + }, + "files_id": { + "$$matchesEntity": "uploadedObjectId" + }, + "n": 0, + "data": { + "$binary": { + "base64": "ESIzRA==", + "subType": "00" + } + } + }, + { + "_id": { + "$$type": "objectId" + }, + "files_id": { + "$$matchesEntity": "uploadedObjectId" + }, + "n": 1, + "data": { + "$binary": { + "base64": "VQ==", + "subType": "00" + } + } + } + ] + } + ] + }, + { + "description": "upload when length is 8", + "operations": [ + { + "name": "upload", + "object": "bucket0", + "arguments": { + "filename": "filename", + "source": { + "$$hexBytes": "1122334455667788" + }, + "chunkSizeBytes": 4 + }, + "expectResult": { + "$$type": "objectId" + }, + "saveResultAsEntity": "uploadedObjectId" + }, + { + "name": "find", + "object": "bucket0_files_collection", + "arguments": { + "filter": {} + }, + "expectResult": [ + { + "_id": { + "$$matchesEntity": "uploadedObjectId" + }, + "length": 8, + "chunkSize": 4, + "uploadDate": { + "$$type": "date" + }, + "md5": { + "$$unsetOrMatches": "dd254cdc958e53abaa67da9f797125f5" + }, + "filename": "filename" + } + ] + }, + { + "name": "find", + "object": "bucket0_chunks_collection", + "arguments": { + "filter": {}, + "sort": { + "n": 1 + } + }, + "expectResult": [ + { + "_id": { + "$$type": "objectId" + }, + "files_id": { + "$$matchesEntity": "uploadedObjectId" + }, + "n": 0, + "data": { + "$binary": { + "base64": "ESIzRA==", + "subType": "00" + } + } + }, + { + "_id": { + "$$type": "objectId" + }, + "files_id": { + "$$matchesEntity": "uploadedObjectId" + }, + "n": 1, + "data": { + "$binary": { + "base64": "VWZ3iA==", + "subType": "00" + } + } + } + ] + } + ] + }, + { + "description": "upload when contentType is provided", + "operations": [ + { + "name": "upload", + "object": "bucket0", + "arguments": { + "filename": "filename", + "source": { + "$$hexBytes": "11" + }, + "chunkSizeBytes": 4, + "contentType": "image/jpeg" + }, + "expectResult": { + "$$type": "objectId" + }, + "saveResultAsEntity": "uploadedObjectId" + }, + { + "name": "find", + "object": "bucket0_files_collection", + "arguments": { + "filter": {} + }, + "expectResult": [ + { + "_id": { + "$$matchesEntity": "uploadedObjectId" + }, + "length": 1, + "chunkSize": 4, + "uploadDate": { + "$$type": "date" + }, + "md5": { + "$$unsetOrMatches": "47ed733b8d10be225eceba344d533586" + }, + "filename": "filename", + "contentType": "image/jpeg" + } + ] + }, + { + "name": "find", + "object": "bucket0_chunks_collection", + "arguments": { + "filter": {} + }, + "expectResult": [ + { + "_id": { + "$$type": "objectId" + }, + "files_id": { + "$$matchesEntity": "uploadedObjectId" + }, + "n": 0, + "data": { + "$binary": { + "base64": "EQ==", + "subType": "00" + } + } + } + ] + } + ] + }, + { + "description": "upload when metadata is provided", + "operations": [ + { + "name": "upload", + "object": "bucket0", + "arguments": { + "filename": "filename", + "source": { + "$$hexBytes": "11" + }, + "chunkSizeBytes": 4, + "metadata": { + "x": 1 + } + }, + "expectResult": { + "$$type": "objectId" + }, + "saveResultAsEntity": "uploadedObjectId" + }, + { + "name": "find", + "object": "bucket0_files_collection", + "arguments": { + "filter": {} + }, + "expectResult": [ + { + "_id": { + "$$matchesEntity": "uploadedObjectId" + }, + "length": 1, + "chunkSize": 4, + "uploadDate": { + "$$type": "date" + }, + "md5": { + "$$unsetOrMatches": "47ed733b8d10be225eceba344d533586" + }, + "filename": "filename", + "metadata": { + "x": 1 + } + } + ] + }, + { + "name": "find", + "object": "bucket0_chunks_collection", + "arguments": { + "filter": {} + }, + "expectResult": [ + { + "_id": { + "$$type": "objectId" + }, + "files_id": { + "$$matchesEntity": "uploadedObjectId" + }, + "n": 0, + "data": { + "$binary": { + "base64": "EQ==", + "subType": "00" + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/gridfs/upload.yml b/test/spec/gridfs/upload.yml new file mode 100644 index 0000000000..27f3186fc4 --- /dev/null +++ b/test/spec/gridfs/upload.yml @@ -0,0 +1,288 @@ +description: "gridfs-upload" + +schemaVersion: "1.0" + +createEntities: + - client: + id: &client0 client0 + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name gridfs-tests + - bucket: + id: &bucket0 bucket0 + database: *database0 + - collection: + id: &bucket0_files_collection bucket0_files_collection + database: *database0 + collectionName: &bucket0_files_collectionName fs.files + - collection: + id: &bucket0_chunks_collection bucket0_chunks_collection + database: *database0 + collectionName: &bucket0_chunks_collectionName fs.chunks + +initialData: + - collectionName: *bucket0_files_collectionName + databaseName: *database0Name + documents: [] + - collectionName: *bucket0_chunks_collectionName + databaseName: *database0Name + documents: [] + +# Note: Uploaded files and chunks include ObjectIds, which we cannot match with +# "outcome" since it does not allow operators. Instead, these tests will use +# find operations to assert the contents of uploaded files and chunks. +tests: + - description: "upload when length is 0" + operations: + - name: upload + object: *bucket0 + arguments: + filename: "filename" + source: { $$hexBytes: "" } + chunkSizeBytes: 4 + expectResult: { $$type: objectId } + saveResultAsEntity: &uploadedObjectId uploadedObjectId + - name: find + object: *bucket0_files_collection + arguments: + filter: {} + expectResult: + - _id: { $$matchesEntity: *uploadedObjectId } + length: 0 + chunkSize: 4 + uploadDate: { $$type: date } + # The md5 field is deprecated so some drivers do not calculate it when uploading files. + md5: { $$unsetOrMatches: "d41d8cd98f00b204e9800998ecf8427e" } + filename: filename + - name: find + object: *bucket0_chunks_collection + arguments: + filter: {} + expectResult: [] + - description: "upload when length is 1" + operations: + - name: upload + object: *bucket0 + arguments: + filename: "filename" + source: { $$hexBytes: "11" } + chunkSizeBytes: 4 + expectResult: { $$type: objectId } + saveResultAsEntity: *uploadedObjectId + - name: find + object: *bucket0_files_collection + arguments: + filter: {} + expectResult: + - _id: { $$matchesEntity: *uploadedObjectId } + length: 1 + chunkSize: 4 + uploadDate: { $$type: date } + md5: { $$unsetOrMatches: "47ed733b8d10be225eceba344d533586" } + filename: filename + - name: find + object: *bucket0_chunks_collection + arguments: + filter: {} + expectResult: + - _id: { $$type: objectId } + files_id: { $$matchesEntity: *uploadedObjectId } + n: 0 + data: { $binary: { base64: "EQ==", subType: "00" } } # hex 11 + - description: "upload when length is 3" + operations: + - name: upload + object: *bucket0 + arguments: + filename: "filename" + source: { $$hexBytes: "112233" } + chunkSizeBytes: 4 + expectResult: { $$type: objectId } + saveResultAsEntity: *uploadedObjectId + - name: find + object: *bucket0_files_collection + arguments: + filter: {} + expectResult: + - _id: { $$matchesEntity: *uploadedObjectId } + length: 3 + chunkSize: 4 + uploadDate: { $$type: date } + md5: { $$unsetOrMatches: "bafae3a174ab91fc70db7a6aa50f4f52" } + filename: filename + - name: find + object: *bucket0_chunks_collection + arguments: + filter: {} + expectResult: + - _id: { $$type: objectId } + files_id: { $$matchesEntity: *uploadedObjectId } + n: 0 + data: { $binary: { base64: "ESIz", subType: "00" } } # hex 112233 + - description: "upload when length is 4" + operations: + - name: upload + object: *bucket0 + arguments: + filename: "filename" + source: { $$hexBytes: "11223344" } + chunkSizeBytes: 4 + expectResult: { $$type: objectId } + saveResultAsEntity: *uploadedObjectId + - name: find + object: *bucket0_files_collection + arguments: + filter: {} + expectResult: + - _id: { $$matchesEntity: *uploadedObjectId } + length: 4 + chunkSize: 4 + uploadDate: { $$type: date } + md5: { $$unsetOrMatches: "7e7c77cff5705d1f7574a25ef6662117" } + filename: filename + - name: find + object: *bucket0_chunks_collection + arguments: + filter: {} + expectResult: + - _id: { $$type: objectId } + files_id: { $$matchesEntity: *uploadedObjectId } + n: 0 + data: { $binary: { base64: "ESIzRA==", subType: "00" } } # hex 11223344 + - description: "upload when length is 5" + operations: + - name: upload + object: *bucket0 + arguments: + filename: filename + source: { $$hexBytes: "1122334455" } + chunkSizeBytes: 4 + expectResult: { $$type: objectId } + saveResultAsEntity: *uploadedObjectId + - name: find + object: *bucket0_files_collection + arguments: + filter: {} + expectResult: + - _id: { $$matchesEntity: *uploadedObjectId } + length: 5 + chunkSize: 4 + uploadDate: { $$type: date } + md5: { $$unsetOrMatches: "283d4fea5dded59cf837d3047328f5af" } + filename: filename + - name: find + object: *bucket0_chunks_collection + arguments: + filter: {} + # Sort to ensure chunks are returned in a deterministic order + sort: { n: 1 } + expectResult: + - _id: { $$type: objectId } + files_id: { $$matchesEntity: *uploadedObjectId } + n: 0 + data: { $binary: { base64: "ESIzRA==", subType: "00" } } # hex 11223344 + - _id: { $$type: objectId } + files_id: { $$matchesEntity: *uploadedObjectId } + n: 1 + data: { $binary: { base64: "VQ==", subType: "00" } } # hex 55 + - description: "upload when length is 8" + operations: + - name: upload + object: *bucket0 + arguments: + filename: filename + source: { $$hexBytes: "1122334455667788" } + chunkSizeBytes: 4 + expectResult: { $$type: objectId } + saveResultAsEntity: *uploadedObjectId + - name: find + object: *bucket0_files_collection + arguments: + filter: {} + expectResult: + - _id: { $$matchesEntity: *uploadedObjectId } + length: 8 + chunkSize: 4 + uploadDate: { $$type: date } + md5: { $$unsetOrMatches: "dd254cdc958e53abaa67da9f797125f5" } + filename: filename + - name: find + object: *bucket0_chunks_collection + arguments: + filter: {} + # Sort to ensure chunks are returned in a deterministic order + sort: { n: 1 } + expectResult: + - _id: { $$type: objectId } + files_id: { $$matchesEntity: *uploadedObjectId } + n: 0 + data: { $binary: { base64: "ESIzRA==", subType: "00" } } # hex 11223344 + - _id: { $$type: objectId } + files_id: { $$matchesEntity: *uploadedObjectId } + n: 1 + data: { $binary: { base64: "VWZ3iA==", subType: "00" } } # hex 55667788 + - description: "upload when contentType is provided" + operations: + - name: upload + object: *bucket0 + arguments: + filename: "filename" + source: { $$hexBytes: "11" } + chunkSizeBytes: 4 + contentType: "image/jpeg" + expectResult: { $$type: objectId } + saveResultAsEntity: *uploadedObjectId + - name: find + object: *bucket0_files_collection + arguments: + filter: {} + expectResult: + - _id: { $$matchesEntity: *uploadedObjectId } + length: 1 + chunkSize: 4 + uploadDate: { $$type: date } + md5: { $$unsetOrMatches: "47ed733b8d10be225eceba344d533586" } + filename: filename + contentType: "image/jpeg" + - name: find + object: *bucket0_chunks_collection + arguments: + filter: {} + expectResult: + - _id: { $$type: objectId } + files_id: { $$matchesEntity: *uploadedObjectId } + n: 0 + data: { $binary: { base64: "EQ==", subType: "00" } } # hex 11 + - description: "upload when metadata is provided" + operations: + - name: upload + object: *bucket0 + arguments: + filename: "filename" + source: { $$hexBytes: "11" } + chunkSizeBytes: 4 + metadata: { x: 1 } + expectResult: { $$type: objectId } + saveResultAsEntity: *uploadedObjectId + - name: find + object: *bucket0_files_collection + arguments: + filter: {} + expectResult: + - _id: { $$matchesEntity: *uploadedObjectId } + length: 1 + chunkSize: 4 + uploadDate: { $$type: date } + md5: { $$unsetOrMatches: "47ed733b8d10be225eceba344d533586" } + filename: filename + metadata: { x: 1 } + - name: find + object: *bucket0_chunks_collection + arguments: + filter: {} + expectResult: + - _id: { $$type: objectId } + files_id: { $$matchesEntity: *uploadedObjectId } + n: 0 + data: { $binary: { base64: "EQ==", subType: "00" } } # hex 11 diff --git a/test/spec/read-write-concern/README.rst b/test/spec/read-write-concern/README.rst index 2f2b84dc9c..4c4dd984f2 100644 --- a/test/spec/read-write-concern/README.rst +++ b/test/spec/read-write-concern/README.rst @@ -57,19 +57,7 @@ Operation These tests check that the default write concern is omitted in operations. -The spec test format is an extension of `transactions spec tests `_ with the following additions: - -- ``writeConcern`` in the ``databaseOptions`` or ``collectionOptions`` may be an empty document to indicate a `server default write concern `_. For example, in libmongoc: - - .. code:: c - - /* Create a default write concern, and set on a collection object. */ - mongoc_write_concern_t *wc = mongoc_write_concern_new (); - mongoc_collection_set_write_concern (collection, wc); - - If the driver has no way to explicitly set a default write concern on a database or collection, ignore the empty ``writeConcern`` document and continue with the test. -- The operations ``createIndex``, ``dropIndex`` are introduced. - +The tests utilize the `Unified Test Format <../../unified-test-format/unified-test-format.md>`__. Use as unit tests ================= diff --git a/test/spec/read-write-concern/operation/default-write-concern-2.6.json b/test/spec/read-write-concern/operation/default-write-concern-2.6.json index c623298cd7..0d8f9c98a1 100644 --- a/test/spec/read-write-concern/operation/default-write-concern-2.6.json +++ b/test/spec/read-write-concern/operation/default-write-concern-2.6.json @@ -1,19 +1,55 @@ { - "data": [ + "description": "default-write-concern-2.6", + "schemaVersion": "1.0", + "runOnRequirements": [ { - "_id": 1, - "x": 11 + "minServerVersion": "2.6" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "default-write-concern-tests", + "databaseOptions": { + "writeConcern": {} + } + } }, { - "_id": 2, - "x": 22 + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll", + "collectionOptions": { + "writeConcern": {} + } + } } ], - "collection_name": "default_write_concern_coll", - "database_name": "default_write_concern_db", - "runOn": [ + "initialData": [ { - "minServerVersion": "2.6" + "collectionName": "coll", + "databaseName": "default-write-concern-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] } ], "tests": [ @@ -22,32 +58,36 @@ "operations": [ { "name": "deleteOne", - "object": "collection", - "collectionOptions": { - "writeConcern": {} - }, + "object": "collection0", "arguments": { "filter": {} }, - "result": { + "expectResult": { "deletedCount": 1 } } ], - "expectations": [ + "expectEvents": [ { - "command_started_event": { - "command": { - "delete": "default_write_concern_coll", - "deletes": [ - { - "q": {}, - "limit": 1 + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "delete": "coll", + "deletes": [ + { + "q": {}, + "limit": 1 + } + ], + "writeConcern": { + "$$exists": false + } } - ], - "writeConcern": null + } } - } + ] } ] }, @@ -56,32 +96,36 @@ "operations": [ { "name": "deleteMany", - "object": "collection", - "collectionOptions": { - "writeConcern": {} - }, + "object": "collection0", "arguments": { "filter": {} }, - "result": { + "expectResult": { "deletedCount": 2 } } ], - "expectations": [ + "expectEvents": [ { - "command_started_event": { - "command": { - "delete": "default_write_concern_coll", - "deletes": [ - { - "q": {}, - "limit": 0 + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "delete": "coll", + "deletes": [ + { + "q": {}, + "limit": 0 + } + ], + "writeConcern": { + "$$exists": false + } } - ], - "writeConcern": null + } } - } + ] } ] }, @@ -90,30 +134,24 @@ "operations": [ { "name": "bulkWrite", - "object": "collection", - "collectionOptions": { - "writeConcern": {} - }, + "object": "collection0", "arguments": { "ordered": true, "requests": [ { - "name": "deleteMany", - "arguments": { + "deleteMany": { "filter": {} } }, { - "name": "insertOne", - "arguments": { + "insertOne": { "document": { "_id": 1 } } }, { - "name": "updateOne", - "arguments": { + "updateOne": { "filter": { "_id": 1 }, @@ -125,16 +163,14 @@ } }, { - "name": "insertOne", - "arguments": { + "insertOne": { "document": { "_id": 2 } } }, { - "name": "replaceOne", - "arguments": { + "replaceOne": { "filter": { "_id": 1 }, @@ -144,16 +180,14 @@ } }, { - "name": "insertOne", - "arguments": { + "insertOne": { "document": { "_id": 3 } } }, { - "name": "updateMany", - "arguments": { + "updateMany": { "filter": { "_id": 1 }, @@ -165,8 +199,7 @@ } }, { - "name": "deleteOne", - "arguments": { + "deleteOne": { "filter": { "_id": 3 } @@ -176,148 +209,185 @@ } } ], - "outcome": { - "collection": { - "name": "default_write_concern_coll", - "data": [ + "expectEvents": [ + { + "client": "client0", + "events": [ { - "_id": 1, - "x": 3 + "commandStartedEvent": { + "command": { + "delete": "coll", + "deletes": [ + { + "q": {}, + "limit": 0 + } + ], + "writeConcern": { + "$$exists": false + } + } + } }, { - "_id": 2 - } - ] - } - }, - "expectations": [ - { - "command_started_event": { - "command": { - "delete": "default_write_concern_coll", - "deletes": [ - { - "q": {}, - "limit": 0 + "commandStartedEvent": { + "command": { + "insert": "coll", + "documents": [ + { + "_id": 1 + } + ], + "writeConcern": { + "$$exists": false + } } - ], - "writeConcern": null - } - } - }, - { - "command_started_event": { - "command": { - "insert": "default_write_concern_coll", - "documents": [ - { - "_id": 1 + } + }, + { + "commandStartedEvent": { + "command": { + "update": "coll", + "updates": [ + { + "q": { + "_id": 1 + }, + "u": { + "$set": { + "x": 1 + } + }, + "upsert": { + "$$unsetOrMatches": false + }, + "multi": { + "$$unsetOrMatches": false + } + } + ], + "writeConcern": { + "$$exists": false + } } - ], - "writeConcern": null - } - } - }, - { - "command_started_event": { - "command": { - "update": "default_write_concern_coll", - "updates": [ - { - "q": { - "_id": 1 - }, - "u": { - "$set": { - "x": 1 + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "coll", + "documents": [ + { + "_id": 2 } + ], + "writeConcern": { + "$$exists": false } } - ], - "writeConcern": null - } - } - }, - { - "command_started_event": { - "command": { - "insert": "default_write_concern_coll", - "documents": [ - { - "_id": 2 + } + }, + { + "commandStartedEvent": { + "command": { + "update": "coll", + "updates": [ + { + "q": { + "_id": 1 + }, + "u": { + "x": 2 + }, + "upsert": { + "$$unsetOrMatches": false + }, + "multi": { + "$$unsetOrMatches": false + } + } + ], + "writeConcern": { + "$$exists": false + } } - ], - "writeConcern": null - } - } - }, - { - "command_started_event": { - "command": { - "update": "default_write_concern_coll", - "updates": [ - { - "q": { - "_id": 1 - }, - "u": { - "x": 2 + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "coll", + "documents": [ + { + "_id": 3 + } + ], + "writeConcern": { + "$$exists": false } } - ], - "writeConcern": null - } - } - }, - { - "command_started_event": { - "command": { - "insert": "default_write_concern_coll", - "documents": [ - { - "_id": 3 + } + }, + { + "commandStartedEvent": { + "command": { + "update": "coll", + "updates": [ + { + "q": { + "_id": 1 + }, + "u": { + "$set": { + "x": 3 + } + }, + "multi": true, + "upsert": { + "$$unsetOrMatches": false + } + } + ], + "writeConcern": { + "$$exists": false + } } - ], - "writeConcern": null - } - } - }, - { - "command_started_event": { - "command": { - "update": "default_write_concern_coll", - "updates": [ - { - "q": { - "_id": 1 - }, - "u": { - "$set": { - "x": 3 + } + }, + { + "commandStartedEvent": { + "command": { + "delete": "coll", + "deletes": [ + { + "q": { + "_id": 3 + }, + "limit": 1 } - }, - "multi": true + ], + "writeConcern": { + "$$exists": false + } } - ], - "writeConcern": null + } } - } - }, + ] + } + ], + "outcome": [ { - "command_started_event": { - "command": { - "delete": "default_write_concern_coll", - "deletes": [ - { - "q": { - "_id": 3 - }, - "limit": 1 - } - ], - "writeConcern": null + "collectionName": "coll", + "databaseName": "default-write-concern-tests", + "documents": [ + { + "_id": 1, + "x": 3 + }, + { + "_id": 2 } - } + ] } ] }, @@ -326,10 +396,7 @@ "operations": [ { "name": "insertOne", - "object": "collection", - "collectionOptions": { - "writeConcern": {} - }, + "object": "collection0", "arguments": { "document": { "_id": 3 @@ -338,10 +405,7 @@ }, { "name": "insertMany", - "object": "collection", - "collectionOptions": { - "writeConcern": {} - }, + "object": "collection0", "arguments": { "documents": [ { @@ -354,10 +418,51 @@ } } ], - "outcome": { - "collection": { - "name": "default_write_concern_coll", - "data": [ + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "coll", + "documents": [ + { + "_id": 3 + } + ], + "writeConcern": { + "$$exists": false + } + } + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "coll", + "documents": [ + { + "_id": 4 + }, + { + "_id": 5 + } + ], + "writeConcern": { + "$$exists": false + } + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "default-write-concern-tests", + "documents": [ { "_id": 1, "x": 11 @@ -377,37 +482,6 @@ } ] } - }, - "expectations": [ - { - "command_started_event": { - "command": { - "insert": "default_write_concern_coll", - "documents": [ - { - "_id": 3 - } - ], - "writeConcern": null - } - } - }, - { - "command_started_event": { - "command": { - "insert": "default_write_concern_coll", - "documents": [ - { - "_id": 4 - }, - { - "_id": 5 - } - ], - "writeConcern": null - } - } - } ] }, { @@ -415,10 +489,7 @@ "operations": [ { "name": "updateOne", - "object": "collection", - "collectionOptions": { - "writeConcern": {} - }, + "object": "collection0", "arguments": { "filter": { "_id": 1 @@ -432,10 +503,7 @@ }, { "name": "updateMany", - "object": "collection", - "collectionOptions": { - "writeConcern": {} - }, + "object": "collection0", "arguments": { "filter": { "_id": 2 @@ -449,10 +517,7 @@ }, { "name": "replaceOne", - "object": "collection", - "collectionOptions": { - "writeConcern": {} - }, + "object": "collection0", "arguments": { "filter": { "_id": 2 @@ -463,80 +528,107 @@ } } ], - "outcome": { - "collection": { - "name": "default_write_concern_coll", - "data": [ + "expectEvents": [ + { + "client": "client0", + "events": [ { - "_id": 1, - "x": 1 + "commandStartedEvent": { + "command": { + "update": "coll", + "updates": [ + { + "q": { + "_id": 1 + }, + "u": { + "$set": { + "x": 1 + } + }, + "upsert": { + "$$unsetOrMatches": false + }, + "multi": { + "$$unsetOrMatches": false + } + } + ], + "writeConcern": { + "$$exists": false + } + } + } }, { - "_id": 2, - "x": 3 - } - ] - } - }, - "expectations": [ - { - "command_started_event": { - "command": { - "update": "default_write_concern_coll", - "updates": [ - { - "q": { - "_id": 1 - }, - "u": { - "$set": { - "x": 1 + "commandStartedEvent": { + "command": { + "update": "coll", + "updates": [ + { + "q": { + "_id": 2 + }, + "u": { + "$set": { + "x": 2 + } + }, + "multi": true, + "upsert": { + "$$unsetOrMatches": false + } } + ], + "writeConcern": { + "$$exists": false } } - ], - "writeConcern": null - } - } - }, - { - "command_started_event": { - "command": { - "update": "default_write_concern_coll", - "updates": [ - { - "q": { - "_id": 2 - }, - "u": { - "$set": { - "x": 2 + } + }, + { + "commandStartedEvent": { + "command": { + "update": "coll", + "updates": [ + { + "q": { + "_id": 2 + }, + "u": { + "x": 3 + }, + "upsert": { + "$$unsetOrMatches": false + }, + "multi": { + "$$unsetOrMatches": false + } } - }, - "multi": true + ], + "writeConcern": { + "$$exists": false + } } - ], - "writeConcern": null + } } - } - }, + ] + } + ], + "outcome": [ { - "command_started_event": { - "command": { - "update": "default_write_concern_coll", - "updates": [ - { - "q": { - "_id": 2 - }, - "u": { - "x": 3 - } - } - ], - "writeConcern": null + "collectionName": "coll", + "databaseName": "default-write-concern-tests", + "documents": [ + { + "_id": 1, + "x": 1 + }, + { + "_id": 2, + "x": 3 } - } + ] } ] } diff --git a/test/spec/read-write-concern/operation/default-write-concern-2.6.yml b/test/spec/read-write-concern/operation/default-write-concern-2.6.yml index 725bcfca12..d18962a7fb 100644 --- a/test/spec/read-write-concern/operation/default-write-concern-2.6.yml +++ b/test/spec/read-write-concern/operation/default-write-concern-2.6.yml @@ -1,215 +1,296 @@ -# Test that setting a default write concern does not add a write concern -# to the command sent over the wire. +# Test that setting a default write concern does not add a write concern to the command sent over the wire. # Test operations that require 2.6+ server. -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} -collection_name: &collection_name default_write_concern_coll -database_name: &database_name default_write_concern_db +description: default-write-concern-2.6 -runOn: - - minServerVersion: "2.6" +schemaVersion: "1.0" + +runOnRequirements: + - minServerVersion: "2.6" + +createEntities: + - + client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name default-write-concern-tests + databaseOptions: + writeConcern: {} + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + collectionOptions: + writeConcern: {} + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } tests: - - description: DeleteOne omits default write concern + - + description: DeleteOne omits default write concern operations: - - name: deleteOne - object: collection - collectionOptions: {writeConcern: {}} + - + name: deleteOne + object: *collection0 arguments: filter: {} - result: + expectResult: deletedCount: 1 - expectations: - - command_started_event: - command: - delete: *collection_name - deletes: - - {q: {}, limit: 1} - writeConcern: null - - description: DeleteMany omits default write concern + expectEvents: + - + client: *client0 + events: + - + commandStartedEvent: + command: + delete: *collection_name + deletes: [ { q: {}, limit: 1 } ] + writeConcern: { $$exists: false } + - + description: DeleteMany omits default write concern operations: - - name: deleteMany - object: collection - collectionOptions: {writeConcern: {}} + - + name: deleteMany + object: *collection0 arguments: filter: {} - result: + expectResult: deletedCount: 2 - expectations: - - command_started_event: - command: - delete: *collection_name - deletes: [{q: {}, limit: 0}] - writeConcern: null - - description: BulkWrite with all models omits default write concern + expectEvents: + - + client: *client0 + events: + - + commandStartedEvent: + command: + delete: *collection_name + deletes: [ { q: {}, limit: 0 } ] + writeConcern: { $$exists: false } + - + description: BulkWrite with all models omits default write concern operations: - - name: bulkWrite - object: collection - collectionOptions: {writeConcern: {}} + - + name: bulkWrite + object: *collection0 arguments: ordered: true requests: - - name: deleteMany - arguments: + - + deleteMany: filter: {} - - name: insertOne - arguments: - document: {_id: 1} - - name: updateOne - arguments: - filter: {_id: 1} - update: {$set: {x: 1}} - - name: insertOne - arguments: - document: {_id: 2} - - name: replaceOne - arguments: - filter: {_id: 1} - replacement: {x: 2} - - name: insertOne - arguments: - document: {_id: 3} - - name: updateMany - arguments: - filter: {_id: 1} - update: {$set: {x: 3}} - - name: deleteOne - arguments: - filter: {_id: 3} + - + insertOne: + document: { _id: 1 } + - + updateOne: + filter: { _id: 1 } + update: { $set: { x: 1 } } + - + insertOne: + document: { _id: 2 } + - + replaceOne: + filter: { _id: 1 } + replacement: { x: 2 } + - + insertOne: + document: { _id: 3 } + - + updateMany: + filter: { _id: 1 } + update: { $set: { x: 3 } } + - + deleteOne: + filter: { _id: 3 } + expectEvents: + - + client: *client0 + events: + - + commandStartedEvent: + command: + delete: *collection_name + deletes: [ { q: {}, limit: 0 } ] + writeConcern: { $$exists: false } + - + commandStartedEvent: + command: + insert: *collection_name + documents: [ { _id: 1 } ] + writeConcern: { $$exists: false } + - + commandStartedEvent: + command: + update: *collection_name + updates: + - + q: { _id: 1 } + u: { $set: { x: 1 } } + upsert: { $$unsetOrMatches: false } + multi: { $$unsetOrMatches: false } + writeConcern: { $$exists: false } + - + commandStartedEvent: + command: + insert: *collection_name + documents: [ { _id: 2 } ] + writeConcern: { $$exists: false } + - + commandStartedEvent: + command: + update: *collection_name + updates: + - + q: { _id: 1 } + u: { x: 2 } + upsert: { $$unsetOrMatches: false } + multi: { $$unsetOrMatches: false } + writeConcern: { $$exists: false } + - + commandStartedEvent: + command: + insert: *collection_name + documents: [ { _id: 3 } ] + writeConcern: { $$exists: false } + - + commandStartedEvent: + command: + update: *collection_name + updates: + - + q: { _id: 1 } + u: { $set: { x: 3 } } + multi: true + upsert: { $$unsetOrMatches: false } + writeConcern: { $$exists: false } + - + commandStartedEvent: + command: + delete: *collection_name + deletes: [ { q: { _id: 3 }, limit: 1 } ] + writeConcern: { $$exists: false } outcome: - collection: - name: *collection_name - data: - - {_id: 1, x: 3} - - {_id: 2} - expectations: - - command_started_event: - command: - delete: *collection_name - deletes: [{q: {}, limit: 0}] - writeConcern: null - - command_started_event: - command: - insert: *collection_name - documents: - - {_id: 1} - writeConcern: null - - command_started_event: - command: - update: *collection_name - updates: - - {q: {_id: 1}, u: {$set: {x: 1}}} - writeConcern: null - - command_started_event: - command: - insert: *collection_name - documents: - - {_id: 2} - writeConcern: null - - command_started_event: - command: - update: *collection_name - updates: - - {q: {_id: 1}, u: {x: 2}} - writeConcern: null - - command_started_event: - command: - insert: *collection_name - documents: - - {_id: 3} - writeConcern: null - - command_started_event: - command: - update: *collection_name - updates: - - {q: {_id: 1}, u: {$set: {x: 3}}, multi: true} - writeConcern: null - - command_started_event: - command: - delete: *collection_name - deletes: [{q: {_id: 3}, limit: 1}] - writeConcern: null - - description: 'InsertOne and InsertMany omit default write concern' + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 3 } + - { _id: 2 } + - + description: InsertOne and InsertMany omit default write concern operations: - - name: insertOne - object: collection - collectionOptions: {writeConcern: {}} + - + name: insertOne + object: *collection0 arguments: - document: {_id: 3} - - name: insertMany - object: collection - collectionOptions: {writeConcern: {}} + document: { _id: 3 } + - + name: insertMany + object: *collection0 arguments: documents: - - {_id: 4} - - {_id: 5} + - { _id: 4 } + - { _id: 5 } + expectEvents: + - + client: *client0 + events: + - + commandStartedEvent: + command: + insert: *collection_name + documents: [ { _id: 3 } ] + writeConcern: { $$exists: false } + - + commandStartedEvent: + command: + insert: *collection_name + documents: [ { _id: 4 }, { _id: 5 } ] + writeConcern: { $$exists: false } outcome: - collection: - name: *collection_name - data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3} - - {_id: 4} - - {_id: 5} - expectations: - - command_started_event: - command: - insert: *collection_name - documents: - - {_id: 3} - writeConcern: null - - command_started_event: - command: - insert: *collection_name - documents: - - {_id: 4} - - {_id: 5} - writeConcern: null - - description: 'UpdateOne, UpdateMany, and ReplaceOne omit default write concern' + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3 } + - { _id: 4 } + - { _id: 5 } + - + description: UpdateOne, UpdateMany, and ReplaceOne omit default write concern operations: - - name: updateOne - object: collection - collectionOptions: {writeConcern: {}} + - + name: updateOne + object: *collection0 arguments: - filter: {_id: 1} - update: {$set: {x: 1}} - - name: updateMany - object: collection - collectionOptions: {writeConcern: {}} + filter: { _id: 1 } + update: { $set: { x: 1 } } + - + name: updateMany + object: *collection0 arguments: - filter: {_id: 2} - update: {$set: {x: 2}} - - name: replaceOne - object: collection - collectionOptions: {writeConcern: {}} + filter: { _id: 2 } + update: { $set: { x: 2 } } + - + name: replaceOne + object: *collection0 arguments: - filter: {_id: 2} - replacement: {x: 3} + filter: { _id: 2 } + replacement: { x: 3 } + expectEvents: + - + client: *client0 + events: + - + commandStartedEvent: + command: + update: *collection_name + updates: + - + q: { _id: 1 } + u: { $set: { x: 1 } } + upsert: { $$unsetOrMatches: false } + multi: { $$unsetOrMatches: false } + writeConcern: { $$exists: false } + - + commandStartedEvent: + command: + update: *collection_name + updates: + - + q: { _id: 2 } + u: { $set: { x: 2 } } + multi: true + upsert: { $$unsetOrMatches: false } + writeConcern: { $$exists: false } + - + commandStartedEvent: + command: + update: *collection_name + updates: + - + q: { _id: 2 } + u: { x: 3 } + upsert: { $$unsetOrMatches: false } + multi: { $$unsetOrMatches: false } + writeConcern: { $$exists: false } outcome: - collection: - name: *collection_name - data: - - {_id: 1, x: 1} - - {_id: 2, x: 3} - expectations: - - command_started_event: - command: - update: *collection_name - updates: - - {q: {_id: 1}, u: {$set: {x: 1}}} - writeConcern: null - - command_started_event: - command: - update: *collection_name - updates: - - {q: {_id: 2}, u: {$set: {x: 2}}, multi: true} - writeConcern: null - - command_started_event: - command: - update: *collection_name - updates: - - {q: {_id: 2}, u: {x: 3}} - writeConcern: null \ No newline at end of file + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 1 } + - { _id: 2, x: 3 } diff --git a/test/spec/read-write-concern/operation/default-write-concern-3.2.json b/test/spec/read-write-concern/operation/default-write-concern-3.2.json index 04dd231f04..166a184916 100644 --- a/test/spec/read-write-concern/operation/default-write-concern-3.2.json +++ b/test/spec/read-write-concern/operation/default-write-concern-3.2.json @@ -1,19 +1,55 @@ { - "data": [ + "description": "default-write-concern-3.2", + "schemaVersion": "1.0", + "runOnRequirements": [ { - "_id": 1, - "x": 11 + "minServerVersion": "3.2" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } }, { - "_id": 2, - "x": 22 + "database": { + "id": "database0", + "client": "client0", + "databaseName": "default-write-concern-tests", + "databaseOptions": { + "writeConcern": {} + } + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll", + "collectionOptions": { + "writeConcern": {} + } + } } ], - "collection_name": "default_write_concern_coll", - "database_name": "default_write_concern_db", - "runOn": [ + "initialData": [ { - "minServerVersion": "3.2" + "collectionName": "coll", + "databaseName": "default-write-concern-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] } ], "tests": [ @@ -22,10 +58,7 @@ "operations": [ { "name": "findOneAndUpdate", - "object": "collection", - "collectionOptions": { - "writeConcern": {} - }, + "object": "collection0", "arguments": { "filter": { "_id": 1 @@ -39,10 +72,7 @@ }, { "name": "findOneAndReplace", - "object": "collection", - "collectionOptions": { - "writeConcern": {} - }, + "object": "collection0", "arguments": { "filter": { "_id": 2 @@ -54,10 +84,7 @@ }, { "name": "findOneAndDelete", - "object": "collection", - "collectionOptions": { - "writeConcern": {} - }, + "object": "collection0", "arguments": { "filter": { "_id": 2 @@ -65,59 +92,71 @@ } } ], - "outcome": { - "collection": { - "name": "default_write_concern_coll", - "data": [ + "expectEvents": [ + { + "client": "client0", + "events": [ { - "_id": 1, - "x": 1 + "commandStartedEvent": { + "command": { + "findAndModify": "coll", + "query": { + "_id": 1 + }, + "update": { + "$set": { + "x": 1 + } + }, + "writeConcern": { + "$$exists": false + } + } + } + }, + { + "commandStartedEvent": { + "command": { + "findAndModify": "coll", + "query": { + "_id": 2 + }, + "update": { + "x": 2 + }, + "writeConcern": { + "$$exists": false + } + } + } + }, + { + "commandStartedEvent": { + "command": { + "findAndModify": "coll", + "query": { + "_id": 2 + }, + "remove": true, + "writeConcern": { + "$$exists": false + } + } + } } ] } - }, - "expectations": [ - { - "command_started_event": { - "command": { - "findAndModify": "default_write_concern_coll", - "query": { - "_id": 1 - }, - "update": { - "$set": { - "x": 1 - } - }, - "writeConcern": null - } - } - }, - { - "command_started_event": { - "command": { - "findAndModify": "default_write_concern_coll", - "query": { - "_id": 2 - }, - "update": { - "x": 2 - }, - "writeConcern": null - } - } - }, + ], + "outcome": [ { - "command_started_event": { - "command": { - "findAndModify": "default_write_concern_coll", - "query": { - "_id": 2 - }, - "remove": true, - "writeConcern": null + "collectionName": "coll", + "databaseName": "default-write-concern-tests", + "documents": [ + { + "_id": 1, + "x": 1 } - } + ] } ] } diff --git a/test/spec/read-write-concern/operation/default-write-concern-3.2.yml b/test/spec/read-write-concern/operation/default-write-concern-3.2.yml index dccb7e0d07..eb109cb9fb 100644 --- a/test/spec/read-write-concern/operation/default-write-concern-3.2.yml +++ b/test/spec/read-write-concern/operation/default-write-concern-3.2.yml @@ -1,58 +1,91 @@ -# Test that setting a default write concern does not add a write concern -# to the command sent over the wire. -# Test operations that require 3.2+ server, where findAndModify started -# to accept a write concern. +# Test that setting a default write concern does not add a write concern to the command sent over the wire. +# Test operations that require 3.2+ server, where findAndModify started to accept a write concern. -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} -collection_name: &collection_name default_write_concern_coll -database_name: &database_name default_write_concern_db +description: default-write-concern-3.2 -runOn: - - minServerVersion: "3.2" +schemaVersion: "1.0" + +runOnRequirements: + - minServerVersion: "3.2" + +createEntities: + - + client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name default-write-concern-tests + databaseOptions: + writeConcern: {} + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + collectionOptions: + writeConcern: {} + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } tests: - - description: 'findAndModify operations omit default write concern' + - + description: findAndModify operations omit default write concern operations: - - name: findOneAndUpdate - object: collection - collectionOptions: {writeConcern: {}} + - + name: findOneAndUpdate + object: *collection0 arguments: - filter: {_id: 1} - update: {$set: {x: 1}} - - name: findOneAndReplace - object: collection - collectionOptions: {writeConcern: {}} + filter: { _id: 1 } + update: { $set: { x: 1 } } + - + name: findOneAndReplace + object: *collection0 arguments: - filter: {_id: 2} - replacement: {x: 2} - - name: findOneAndDelete - object: collection - collectionOptions: {writeConcern: {}} + filter: { _id: 2 } + replacement: { x: 2 } + - + name: findOneAndDelete + object: *collection0 arguments: - filter: {_id: 2} + filter: { _id: 2 } + expectEvents: + - + client: *client0 + events: + - + commandStartedEvent: + command: + findAndModify: *collection_name + query: { _id: 1 } + update: { $set: { x: 1 } } + writeConcern: { $$exists: false } + - + commandStartedEvent: + command: + findAndModify: *collection_name + query: { _id: 2 } + update: { x: 2 } + writeConcern: { $$exists: false } + - + commandStartedEvent: + command: + findAndModify: *collection_name + query: { _id: 2 } + remove: true + writeConcern: { $$exists: false } outcome: - collection: - name: *collection_name - data: - - {_id: 1, x: 1} - expectations: - - command_started_event: - command: - findAndModify: *collection_name - query: {_id: 1} - update: {$set: {x: 1}} - writeConcern: null - - command_started_event: - command: - findAndModify: *collection_name - query: {_id: 2} - update: {x: 2} - writeConcern: null - - command_started_event: - command: - findAndModify: *collection_name - query: {_id: 2} - remove: true - writeConcern: null \ No newline at end of file + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 1 } diff --git a/test/spec/read-write-concern/operation/default-write-concern-3.4.json b/test/spec/read-write-concern/operation/default-write-concern-3.4.json index 6519f6f089..e18cdfc0c4 100644 --- a/test/spec/read-write-concern/operation/default-write-concern-3.4.json +++ b/test/spec/read-write-concern/operation/default-write-concern-3.4.json @@ -1,30 +1,68 @@ { - "data": [ + "description": "default-write-concern-3.4", + "schemaVersion": "1.4", + "runOnRequirements": [ { - "_id": 1, - "x": 11 + "minServerVersion": "3.4" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "default-write-concern-tests", + "databaseOptions": { + "writeConcern": {} + } + } }, { - "_id": 2, - "x": 22 + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll", + "collectionOptions": { + "writeConcern": {} + } + } } ], - "collection_name": "default_write_concern_coll", - "database_name": "default_write_concern_db", - "runOn": [ + "initialData": [ { - "minServerVersion": "3.4" + "collectionName": "coll", + "databaseName": "default-write-concern-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] } ], "tests": [ { "description": "Aggregate with $out omits default write concern", + "runOnRequirements": [ + { + "serverless": "forbid" + } + ], "operations": [ { - "object": "collection", - "collectionOptions": { - "writeConcern": {} - }, + "object": "collection0", "name": "aggregate", "arguments": { "pipeline": [ @@ -42,37 +80,45 @@ } } ], - "outcome": { - "collection": { - "name": "other_collection_name", - "data": [ + "expectEvents": [ + { + "client": "client0", + "events": [ { - "_id": 2, - "x": 22 + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$out": "other_collection_name" + } + ], + "writeConcern": { + "$$exists": false + } + } + } } ] } - }, - "expectations": [ + ], + "outcome": [ { - "command_started_event": { - "command": { - "aggregate": "default_write_concern_coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$out": "other_collection_name" - } - ], - "writeConcern": null + "collectionName": "other_collection_name", + "databaseName": "default-write-concern-tests", + "documents": [ + { + "_id": 2, + "x": 22 } - } + ] } ] }, @@ -80,39 +126,43 @@ "description": "RunCommand with a write command omits default write concern (runCommand should never inherit write concern)", "operations": [ { - "object": "database", - "databaseOptions": { - "writeConcern": {} - }, + "object": "database0", "name": "runCommand", - "command_name": "delete", "arguments": { "command": { - "delete": "default_write_concern_coll", + "delete": "coll", "deletes": [ { "q": {}, "limit": 1 } ] - } + }, + "commandName": "delete" } } ], - "expectations": [ + "expectEvents": [ { - "command_started_event": { - "command": { - "delete": "default_write_concern_coll", - "deletes": [ - { - "q": {}, - "limit": 1 + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "delete": "coll", + "deletes": [ + { + "q": {}, + "limit": 1 + } + ], + "writeConcern": { + "$$exists": false + } } - ], - "writeConcern": null + } } - } + ] } ] }, @@ -120,10 +170,7 @@ "description": "CreateIndex and dropIndex omits default write concern", "operations": [ { - "object": "collection", - "collectionOptions": { - "writeConcern": {} - }, + "object": "collection0", "name": "createIndex", "arguments": { "keys": { @@ -132,53 +179,61 @@ } }, { - "object": "collection", - "collectionOptions": { - "writeConcern": {} - }, + "object": "collection0", "name": "dropIndex", "arguments": { "name": "x_1" } } ], - "expectations": [ + "expectEvents": [ { - "command_started_event": { - "command": { - "createIndexes": "default_write_concern_coll", - "indexes": [ - { - "name": "x_1", - "key": { - "x": 1 + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "createIndexes": "coll", + "indexes": [ + { + "name": "x_1", + "key": { + "x": 1 + } + } + ], + "writeConcern": { + "$$exists": false } } - ], - "writeConcern": null - } - } - }, - { - "command_started_event": { - "command": { - "dropIndexes": "default_write_concern_coll", - "index": "x_1", - "writeConcern": null + } + }, + { + "commandStartedEvent": { + "command": { + "dropIndexes": "coll", + "index": "x_1", + "writeConcern": { + "$$exists": false + } + } + } } - } + ] } ] }, { "description": "MapReduce omits default write concern", + "runOnRequirements": [ + { + "serverless": "forbid" + } + ], "operations": [ { "name": "mapReduce", - "object": "collection", - "collectionOptions": { - "writeConcern": {} - }, + "object": "collection0", "arguments": { "map": { "$code": "function inc() { return emit(0, this.x + 1) }" @@ -192,23 +247,30 @@ } } ], - "expectations": [ + "expectEvents": [ { - "command_started_event": { - "command": { - "mapReduce": "default_write_concern_coll", - "map": { - "$code": "function inc() { return emit(0, this.x + 1) }" - }, - "reduce": { - "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" - }, - "out": { - "inline": 1 - }, - "writeConcern": null + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "mapReduce": "coll", + "map": { + "$code": "function inc() { return emit(0, this.x + 1) }" + }, + "reduce": { + "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" + }, + "out": { + "inline": 1 + }, + "writeConcern": { + "$$exists": false + } + } + } } - } + ] } ] } diff --git a/test/spec/read-write-concern/operation/default-write-concern-3.4.yml b/test/spec/read-write-concern/operation/default-write-concern-3.4.yml index c7b586cadc..7596208868 100644 --- a/test/spec/read-write-concern/operation/default-write-concern-3.4.yml +++ b/test/spec/read-write-concern/operation/default-write-concern-3.4.yml @@ -1,95 +1,144 @@ -# Test that setting a default write concern does not add a write concern -# to the command sent over the wire. -# Test operations that require 3.4+ server, where all commands started -# to accept a write concern. +# Test that setting a default write concern does not add a write concern to the command sent over the wire. +# Test operations that require 3.4+ server, where all commands started to accept a write concern. -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} -collection_name: &collection_name default_write_concern_coll -database_name: &database_name default_write_concern_db +description: default-write-concern-3.4 -runOn: - - minServerVersion: "3.4" +schemaVersion: "1.4" + +runOnRequirements: + - minServerVersion: "3.4" + +createEntities: + - + client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name default-write-concern-tests + databaseOptions: + writeConcern: {} + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + collectionOptions: + writeConcern: {} + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } tests: - - description: Aggregate with $out omits default write concern + - + description: Aggregate with $out omits default write concern + # Serverless does not support $out stage + runOnRequirements: + - serverless: forbid operations: - - object: collection - collectionOptions: {writeConcern: {}} + - + object: *collection0 name: aggregate arguments: pipeline: &out_pipeline - - $match: {_id: {$gt: 1}} + - $match: { _id: { $gt: 1 } } - $out: &other_collection_name "other_collection_name" + expectEvents: + - + client: *client0 + events: + - + commandStartedEvent: + command: + aggregate: *collection_name + pipeline: *out_pipeline + writeConcern: { $$exists: false } outcome: - collection: - name: *other_collection_name - data: - - {_id: 2, x: 22} - expectations: - - command_started_event: - command: - aggregate: *collection_name - pipeline: *out_pipeline - writeConcern: null - - description: RunCommand with a write command omits default write concern (runCommand should never inherit write concern) + - + collectionName: *other_collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 22 } + - + description: RunCommand with a write command omits default write concern (runCommand should never inherit write concern) operations: - - object: database - databaseOptions: {writeConcern: {}} + - + object: *database0 name: runCommand - command_name: delete arguments: command: delete: *collection_name - deletes: - - {q: {}, limit: 1} - expectations: - - command_started_event: - command: - delete: *collection_name - deletes: - - {q: {}, limit: 1} - writeConcern: null - - description: CreateIndex and dropIndex omits default write concern + deletes: [ { q: {}, limit: 1 } ] + commandName: delete + expectEvents: + - + client: *client0 + events: + - + commandStartedEvent: + command: + delete: *collection_name + deletes: [ { q: {}, limit: 1 } ] + writeConcern: { $$exists: false } + - + description: CreateIndex and dropIndex omits default write concern operations: - - object: collection - collectionOptions: {writeConcern: {}} + - + object: *collection0 name: createIndex arguments: - keys: {x: 1} - - object: collection - collectionOptions: {writeConcern: {}} + keys: { x: 1 } + - + object: *collection0 name: dropIndex arguments: name: x_1 - expectations: - - command_started_event: - command: - createIndexes: *collection_name - indexes: - - name: x_1 - key: {x: 1} - writeConcern: null - - command_started_event: - command: - dropIndexes: *collection_name - index: x_1 - writeConcern: null - - description: MapReduce omits default write concern + expectEvents: + - + client: *client0 + events: + - + commandStartedEvent: + command: + createIndexes: *collection_name + indexes: [ { name: "x_1", key: { x: 1 } } ] + writeConcern: { $$exists: false } + - + commandStartedEvent: + command: + dropIndexes: *collection_name + index: x_1 + writeConcern: { $$exists: false } + - + description: MapReduce omits default write concern + # Serverless does not support mapReduce operation + runOnRequirements: + - serverless: forbid operations: - - name: mapReduce - object: collection - collectionOptions: {writeConcern: {}} + - + name: mapReduce + object: *collection0 arguments: - map: { $code: 'function inc() { return emit(0, this.x + 1) }' } - reduce: { $code: 'function sum(key, values) { return values.reduce((acc, x) => acc + x); }' } + map: { $code: "function inc() { return emit(0, this.x + 1) }" } + reduce: { $code: "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" } out: { inline: 1 } - expectations: - - command_started_event: - command: - mapReduce: *collection_name - map: { $code: 'function inc() { return emit(0, this.x + 1) }' } - reduce: { $code: 'function sum(key, values) { return values.reduce((acc, x) => acc + x); }' } - out: { inline: 1 } - writeConcern: null \ No newline at end of file + expectEvents: + - + client: *client0 + events: + - + commandStartedEvent: + command: + mapReduce: *collection_name + map: { $code: "function inc() { return emit(0, this.x + 1) }" } + reduce: { $code: "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" } + out: { inline: 1 } + writeConcern: { $$exists: false } diff --git a/test/spec/read-write-concern/operation/default-write-concern-4.2.json b/test/spec/read-write-concern/operation/default-write-concern-4.2.json index fef192d1a3..e8bb78d91d 100644 --- a/test/spec/read-write-concern/operation/default-write-concern-4.2.json +++ b/test/spec/read-write-concern/operation/default-write-concern-4.2.json @@ -1,19 +1,55 @@ { - "data": [ + "description": "default-write-concern-4.2", + "schemaVersion": "1.0", + "runOnRequirements": [ { - "_id": 1, - "x": 11 + "minServerVersion": "4.2" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } }, { - "_id": 2, - "x": 22 + "database": { + "id": "database0", + "client": "client0", + "databaseName": "default-write-concern-tests", + "databaseOptions": { + "writeConcern": {} + } + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll", + "collectionOptions": { + "writeConcern": {} + } + } } ], - "collection_name": "default_write_concern_coll", - "database_name": "default_write_concern_db", - "runOn": [ + "initialData": [ { - "minServerVersion": "4.2" + "collectionName": "coll", + "databaseName": "default-write-concern-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] } ], "tests": [ @@ -21,13 +57,7 @@ "description": "Aggregate with $merge omits default write concern", "operations": [ { - "object": "collection", - "databaseOptions": { - "writeConcern": {} - }, - "collectionOptions": { - "writeConcern": {} - }, + "object": "collection0", "name": "aggregate", "arguments": { "pipeline": [ @@ -47,41 +77,49 @@ } } ], - "expectations": [ + "expectEvents": [ { - "command_started_event": { - "command": { - "aggregate": "default_write_concern_coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$merge": { + "into": "other_collection_name" + } } - } - }, - { - "$merge": { - "into": "other_collection_name" + ], + "writeConcern": { + "$$exists": false } } - ], - "writeConcern": null + } } - } + ] } ], - "outcome": { - "collection": { - "name": "other_collection_name", - "data": [ + "outcome": [ + { + "collectionName": "other_collection_name", + "databaseName": "default-write-concern-tests", + "documents": [ { "_id": 2, "x": 22 } ] } - } + ] } ] } diff --git a/test/spec/read-write-concern/operation/default-write-concern-4.2.yml b/test/spec/read-write-concern/operation/default-write-concern-4.2.yml index 6039b55814..3ce742e655 100644 --- a/test/spec/read-write-concern/operation/default-write-concern-4.2.yml +++ b/test/spec/read-write-concern/operation/default-write-concern-4.2.yml @@ -1,36 +1,66 @@ -# Test that setting a default write concern does not add a write concern -# to the command sent over the wire. +# Test that setting a default write concern does not add a write concern to the command sent over the wire. # Test operations that require 4.2+ server. -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} -collection_name: &collection_name default_write_concern_coll -database_name: &database_name default_write_concern_db +description: default-write-concern-4.2 -runOn: - - minServerVersion: "4.2" +schemaVersion: "1.0" + +runOnRequirements: + - minServerVersion: "4.2" + +createEntities: + - + client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name default-write-concern-tests + databaseOptions: + writeConcern: {} + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + collectionOptions: + writeConcern: {} + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } tests: - - description: Aggregate with $merge omits default write concern + - + description: Aggregate with $merge omits default write concern operations: - - object: collection - databaseOptions: {writeConcern: {}} - collectionOptions: {writeConcern: {}} + - + object: *collection0 name: aggregate arguments: pipeline: &merge_pipeline - - $match: {_id: {$gt: 1}} - - $merge: {into: &other_collection_name "other_collection_name" } - expectations: - - command_started_event: - command: - aggregate: *collection_name - pipeline: *merge_pipeline - # "null" fields will be checked for non-existence - writeConcern: null + - $match: { _id: { $gt: 1 } } + - $merge: { into: &other_collection_name "other_collection_name" } + expectEvents: + - + client: *client0 + events: + - + commandStartedEvent: + command: + aggregate: *collection_name + pipeline: *merge_pipeline + writeConcern: { $$exists: false } outcome: - collection: - name: *other_collection_name - data: - - {_id: 2, x: 22} \ No newline at end of file + - + collectionName: *other_collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-reads/legacy/aggregate-merge.json b/test/spec/retryable-reads/legacy/aggregate-merge.json deleted file mode 100644 index b401d741ba..0000000000 --- a/test/spec/retryable-reads/legacy/aggregate-merge.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.1.11" - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "tests": [ - { - "description": "Aggregate with $merge does not retry", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "closeConnection": true - } - }, - "operations": [ - { - "object": "collection", - "name": "aggregate", - "arguments": { - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - }, - { - "$merge": { - "into": "output-collection" - } - } - ] - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - }, - { - "$merge": { - "into": "output-collection" - } - } - ] - }, - "command_name": "aggregate", - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/aggregate-merge.yml b/test/spec/retryable-reads/legacy/aggregate-merge.yml deleted file mode 100644 index f9913348f4..0000000000 --- a/test/spec/retryable-reads/legacy/aggregate-merge.yml +++ /dev/null @@ -1,39 +0,0 @@ -runOn: - - - minServerVersion: "4.1.11" - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - -tests: - - - description: "Aggregate with $merge does not retry" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: [aggregate] - closeConnection: true - operations: - - - object: collection - name: aggregate - arguments: - pipeline: &pipeline - - $match: {_id: {$gt: 1}} - - $sort: {x: 1} - - $merge: { into: "output-collection" } - error: true - expectations: - - - command_started_event: - command: - aggregate: *collection_name - pipeline: *pipeline - command_name: aggregate - database_name: *database_name diff --git a/test/spec/retryable-reads/legacy/aggregate-serverErrors.json b/test/spec/retryable-reads/legacy/aggregate-serverErrors.json deleted file mode 100644 index 1155f808dc..0000000000 --- a/test/spec/retryable-reads/legacy/aggregate-serverErrors.json +++ /dev/null @@ -1,1208 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "tests": [ - { - "description": "Aggregate succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 11600 - } - }, - "operations": [ - { - "name": "aggregate", - "object": "collection", - "arguments": { - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "result": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Aggregate succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 11602 - } - }, - "operations": [ - { - "name": "aggregate", - "object": "collection", - "arguments": { - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "result": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Aggregate succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "aggregate", - "object": "collection", - "arguments": { - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "result": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Aggregate succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 13435 - } - }, - "operations": [ - { - "name": "aggregate", - "object": "collection", - "arguments": { - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "result": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Aggregate succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 13436 - } - }, - "operations": [ - { - "name": "aggregate", - "object": "collection", - "arguments": { - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "result": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Aggregate succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 189 - } - }, - "operations": [ - { - "name": "aggregate", - "object": "collection", - "arguments": { - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "result": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Aggregate succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 91 - } - }, - "operations": [ - { - "name": "aggregate", - "object": "collection", - "arguments": { - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "result": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Aggregate succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 7 - } - }, - "operations": [ - { - "name": "aggregate", - "object": "collection", - "arguments": { - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "result": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Aggregate succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 6 - } - }, - "operations": [ - { - "name": "aggregate", - "object": "collection", - "arguments": { - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "result": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Aggregate succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 89 - } - }, - "operations": [ - { - "name": "aggregate", - "object": "collection", - "arguments": { - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "result": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Aggregate succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 9001 - } - }, - "operations": [ - { - "name": "aggregate", - "object": "collection", - "arguments": { - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "result": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Aggregate fails after two NotWritablePrimary errors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "aggregate", - "object": "collection", - "arguments": { - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Aggregate fails after NotWritablePrimary when retryReads is false", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "aggregate", - "object": "collection", - "arguments": { - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/aggregate-serverErrors.yml b/test/spec/retryable-reads/legacy/aggregate-serverErrors.yml deleted file mode 100644 index bf9fc01892..0000000000 --- a/test/spec/retryable-reads/legacy/aggregate-serverErrors.yml +++ /dev/null @@ -1,157 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - -tests: - - - description: "Aggregate succeeds after InterruptedAtShutdown" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: { failCommands: [aggregate], errorCode: 11600 } - operations: - - &retryable_operation_succeeds - <<: &retryable_operation - name: aggregate - object: collection - arguments: - pipeline: - - $match: - _id: {$gt: 1} - - $sort: {x: 1} - result: - - {_id: 2, x: 22} - - {_id: 3, x: 33} - expectations: - - &retryable_command_started_event - command_started_event: - command: - aggregate: *collection_name - pipeline: [{$match: {_id: {$gt: 1}}}, {$sort: {x: 1}}] - database_name: *database_name - - *retryable_command_started_event - - - description: "Aggregate succeeds after InterruptedDueToReplStateChange" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 11602 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Aggregate succeeds after NotWritablePrimary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 10107 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Aggregate succeeds after NotPrimaryNoSecondaryOk" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 13435 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Aggregate succeeds after NotPrimaryOrSecondary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 13436 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Aggregate succeeds after PrimarySteppedDown" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 189 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Aggregate succeeds after ShutdownInProgress" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 91 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Aggregate succeeds after HostNotFound" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 7 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Aggregate succeeds after HostUnreachable" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 6 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Aggregate succeeds after NetworkTimeout" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 89 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Aggregate succeeds after SocketException" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 9001 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Aggregate fails after two NotWritablePrimary errors" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - data: { failCommands: [aggregate], errorCode: 10107 } - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Aggregate fails after NotWritablePrimary when retryReads is false" - clientOptions: - retryReads: false - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 10107 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event diff --git a/test/spec/retryable-reads/legacy/aggregate.json b/test/spec/retryable-reads/legacy/aggregate.json deleted file mode 100644 index f23d5c6793..0000000000 --- a/test/spec/retryable-reads/legacy/aggregate.json +++ /dev/null @@ -1,406 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "tests": [ - { - "description": "Aggregate succeeds on first attempt", - "operations": [ - { - "name": "aggregate", - "object": "collection", - "arguments": { - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "result": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Aggregate succeeds on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "aggregate", - "object": "collection", - "arguments": { - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "result": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Aggregate fails on first attempt", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "aggregate", - "object": "collection", - "arguments": { - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Aggregate fails on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "aggregate", - "object": "collection", - "arguments": { - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Aggregate with $out does not retry", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "aggregate", - "object": "collection", - "arguments": { - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - }, - { - "$out": "output-collection" - } - ] - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": { - "_id": { - "$gt": 1 - } - } - }, - { - "$sort": { - "x": 1 - } - }, - { - "$out": "output-collection" - } - ] - }, - "command_name": "aggregate", - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/aggregate.yml b/test/spec/retryable-reads/legacy/aggregate.yml deleted file mode 100644 index de9c0d7069..0000000000 --- a/test/spec/retryable-reads/legacy/aggregate.yml +++ /dev/null @@ -1,87 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - -tests: - - - description: "Aggregate succeeds on first attempt" - operations: - - &retryable_operation_succeeds - <<: &retryable_operation - name: aggregate - object: collection - arguments: - pipeline: - - $match: {_id: {$gt: 1}} - - $sort: {x: 1} - result: - - {_id: 2, x: 22} - - {_id: 3, x: 33} - expectations: - - &retryable_command_started_event - command_started_event: - command: - aggregate: *collection_name - pipeline: [{$match: {_id: {$gt: 1}}}, {$sort: {x: 1}}] - database_name: *database_name - - - description: "Aggregate succeeds on second attempt" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: [aggregate] - closeConnection: true - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Aggregate fails on first attempt" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - - description: "Aggregate fails on second attempt" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Aggregate with $out does not retry" - failPoint: *failCommand_failPoint - operations: - - <<: *retryable_operation_fails - arguments: - pipeline: - - $match: {_id: {$gt: 1}} - - $sort: {x: 1} - - $out: "output-collection" - expectations: - - command_started_event: - command: - aggregate: *collection_name - pipeline: [{$match: {_id: {$gt: 1}}}, {$sort: {x: 1}}, {$out: 'output-collection'}] - command_name: aggregate - database_name: *database_name diff --git a/test/spec/retryable-reads/legacy/changeStreams-client.watch-serverErrors.json b/test/spec/retryable-reads/legacy/changeStreams-client.watch-serverErrors.json deleted file mode 100644 index 73dbfee916..0000000000 --- a/test/spec/retryable-reads/legacy/changeStreams-client.watch-serverErrors.json +++ /dev/null @@ -1,740 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ], - "serverless": "forbid" - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "tests": [ - { - "description": "client.watch succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 11600 - } - }, - "operations": [ - { - "name": "watch", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - } - ] - }, - { - "description": "client.watch succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 11602 - } - }, - "operations": [ - { - "name": "watch", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - } - ] - }, - { - "description": "client.watch succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "watch", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - } - ] - }, - { - "description": "client.watch succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 13435 - } - }, - "operations": [ - { - "name": "watch", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - } - ] - }, - { - "description": "client.watch succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 13436 - } - }, - "operations": [ - { - "name": "watch", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - } - ] - }, - { - "description": "client.watch succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 189 - } - }, - "operations": [ - { - "name": "watch", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - } - ] - }, - { - "description": "client.watch succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 91 - } - }, - "operations": [ - { - "name": "watch", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - } - ] - }, - { - "description": "client.watch succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 7 - } - }, - "operations": [ - { - "name": "watch", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - } - ] - }, - { - "description": "client.watch succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 6 - } - }, - "operations": [ - { - "name": "watch", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - } - ] - }, - { - "description": "client.watch succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 89 - } - }, - "operations": [ - { - "name": "watch", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - } - ] - }, - { - "description": "client.watch succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 9001 - } - }, - "operations": [ - { - "name": "watch", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - } - ] - }, - { - "description": "client.watch fails after two NotWritablePrimary errors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "watch", - "object": "client", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - } - ] - }, - { - "description": "client.watch fails after NotWritablePrimary when retryReads is false", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "watch", - "object": "client", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/changeStreams-client.watch-serverErrors.yml b/test/spec/retryable-reads/legacy/changeStreams-client.watch-serverErrors.yml deleted file mode 100644 index a1f1069643..0000000000 --- a/test/spec/retryable-reads/legacy/changeStreams-client.watch-serverErrors.yml +++ /dev/null @@ -1,150 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - serverless: "forbid" - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - -tests: - - - description: "client.watch succeeds after InterruptedAtShutdown" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: { failCommands: [aggregate], errorCode: 11600 } - operations: - - &retryable_operation - name: watch - object: client - expectations: - - &retryable_command_started_event - command_started_event: - command: - aggregate: 1 - cursor: {} - pipeline: [ { $changeStream: { allChangesForCluster: true } } ] - database_name: admin - - *retryable_command_started_event - - - description: "client.watch succeeds after InterruptedDueToReplStateChange" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 11602 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "client.watch succeeds after NotWritablePrimary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 10107 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "client.watch succeeds after NotPrimaryNoSecondaryOk" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 13435 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "client.watch succeeds after NotPrimaryOrSecondary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 13436 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "client.watch succeeds after PrimarySteppedDown" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 189 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "client.watch succeeds after ShutdownInProgress" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 91 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "client.watch succeeds after HostNotFound" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 7 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "client.watch succeeds after HostUnreachable" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 6 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "client.watch succeeds after NetworkTimeout" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 89 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "client.watch succeeds after SocketException" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 9001 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "client.watch fails after two NotWritablePrimary errors" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - data: { failCommands: [aggregate], errorCode: 10107 } - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "client.watch fails after NotWritablePrimary when retryReads is false" - clientOptions: - retryReads: false - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 10107 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event diff --git a/test/spec/retryable-reads/legacy/changeStreams-client.watch.json b/test/spec/retryable-reads/legacy/changeStreams-client.watch.json deleted file mode 100644 index 30a53037ad..0000000000 --- a/test/spec/retryable-reads/legacy/changeStreams-client.watch.json +++ /dev/null @@ -1,209 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ], - "serverless": "forbid" - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - } - ], - "tests": [ - { - "description": "client.watch succeeds on first attempt", - "operations": [ - { - "name": "watch", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - } - ] - }, - { - "description": "client.watch succeeds on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "watch", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - } - ] - }, - { - "description": "client.watch fails on first attempt", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "watch", - "object": "client", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - } - ] - }, - { - "description": "client.watch fails on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "watch", - "object": "client", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": { - "allChangesForCluster": true - } - } - ] - }, - "database_name": "admin" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/changeStreams-client.watch.yml b/test/spec/retryable-reads/legacy/changeStreams-client.watch.yml deleted file mode 100644 index ea7f7e069a..0000000000 --- a/test/spec/retryable-reads/legacy/changeStreams-client.watch.yml +++ /dev/null @@ -1,62 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - serverless: "forbid" - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - {_id: 1, x: 11} - -tests: - - - description: "client.watch succeeds on first attempt" - operations: - - &retryable_operation - name: watch - object: client - expectations: - - &retryable_command_started_event - command_started_event: - command: - aggregate: 1 - cursor: {} - pipeline: [ { $changeStream: { "allChangesForCluster": true } } ] - database_name: admin - - - description: "client.watch succeeds on second attempt" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: [aggregate] - closeConnection: true - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "client.watch fails on first attempt" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - - description: "client.watch fails on second attempt" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event diff --git a/test/spec/retryable-reads/legacy/changeStreams-db.coll.watch-serverErrors.json b/test/spec/retryable-reads/legacy/changeStreams-db.coll.watch-serverErrors.json deleted file mode 100644 index 77b3af04f4..0000000000 --- a/test/spec/retryable-reads/legacy/changeStreams-db.coll.watch-serverErrors.json +++ /dev/null @@ -1,690 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ], - "serverless": "forbid" - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "tests": [ - { - "description": "db.coll.watch succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 11600 - } - }, - "operations": [ - { - "name": "watch", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.coll.watch succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 11602 - } - }, - "operations": [ - { - "name": "watch", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.coll.watch succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "watch", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.coll.watch succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 13435 - } - }, - "operations": [ - { - "name": "watch", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.coll.watch succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 13436 - } - }, - "operations": [ - { - "name": "watch", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.coll.watch succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 189 - } - }, - "operations": [ - { - "name": "watch", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.coll.watch succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 91 - } - }, - "operations": [ - { - "name": "watch", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.coll.watch succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 7 - } - }, - "operations": [ - { - "name": "watch", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.coll.watch succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 6 - } - }, - "operations": [ - { - "name": "watch", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.coll.watch succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 89 - } - }, - "operations": [ - { - "name": "watch", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.coll.watch succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 9001 - } - }, - "operations": [ - { - "name": "watch", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.coll.watch fails after two NotWritablePrimary errors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "watch", - "object": "collection", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.coll.watch fails after NotWritablePrimary when retryReads is false", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "watch", - "object": "collection", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/changeStreams-db.coll.watch-serverErrors.yml b/test/spec/retryable-reads/legacy/changeStreams-db.coll.watch-serverErrors.yml deleted file mode 100644 index 4e4bb4a1b7..0000000000 --- a/test/spec/retryable-reads/legacy/changeStreams-db.coll.watch-serverErrors.yml +++ /dev/null @@ -1,150 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - serverless: "forbid" - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - -tests: - - - description: "db.coll.watch succeeds after InterruptedAtShutdown" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: { failCommands: [aggregate], errorCode: 11600 } - operations: - - &retryable_operation - name: watch - object: collection - expectations: - - &retryable_command_started_event - command_started_event: - command: - aggregate: *collection_name - cursor: {} - pipeline: [ { $changeStream: { } } ] - database_name: *database_name - - *retryable_command_started_event - - - description: "db.coll.watch succeeds after InterruptedDueToReplStateChange" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 11602 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.coll.watch succeeds after NotWritablePrimary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 10107 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.coll.watch succeeds after NotPrimaryNoSecondaryOk" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 13435 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.coll.watch succeeds after NotPrimaryOrSecondary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 13436 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.coll.watch succeeds after PrimarySteppedDown" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 189 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.coll.watch succeeds after ShutdownInProgress" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 91 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.coll.watch succeeds after HostNotFound" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 7 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.coll.watch succeeds after HostUnreachable" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 6 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.coll.watch succeeds after NetworkTimeout" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 89 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.coll.watch succeeds after SocketException" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 9001 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.coll.watch fails after two NotWritablePrimary errors" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - data: { failCommands: [aggregate], errorCode: 10107 } - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.coll.watch fails after NotWritablePrimary when retryReads is false" - clientOptions: - retryReads: false - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 10107 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event diff --git a/test/spec/retryable-reads/legacy/changeStreams-db.coll.watch.json b/test/spec/retryable-reads/legacy/changeStreams-db.coll.watch.json deleted file mode 100644 index 27f6105a4b..0000000000 --- a/test/spec/retryable-reads/legacy/changeStreams-db.coll.watch.json +++ /dev/null @@ -1,197 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ], - "serverless": "forbid" - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - } - ], - "tests": [ - { - "description": "db.coll.watch succeeds on first attempt", - "operations": [ - { - "name": "watch", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.coll.watch succeeds on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "watch", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.coll.watch fails on first attempt", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "watch", - "object": "collection", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.coll.watch fails on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "watch", - "object": "collection", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/changeStreams-db.coll.watch.yml b/test/spec/retryable-reads/legacy/changeStreams-db.coll.watch.yml deleted file mode 100644 index c8334b1a99..0000000000 --- a/test/spec/retryable-reads/legacy/changeStreams-db.coll.watch.yml +++ /dev/null @@ -1,66 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - serverless: "forbid" - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - {_id: 1, x: 11} - -tests: - - - description: "db.coll.watch succeeds on first attempt" - operations: - - &retryable_operation - name: watch - object: collection - expectations: - - &retryable_command_started_event - command_started_event: - command: - aggregate: *collection_name - cursor: {} - pipeline: [ { $changeStream: { } } ] - database_name: *database_name - - - description: "db.coll.watch succeeds on second attempt" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: - - aggregate - closeConnection: true - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.coll.watch fails on first attempt" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - - description: "db.coll.watch fails on second attempt" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - diff --git a/test/spec/retryable-reads/legacy/changeStreams-db.watch-serverErrors.json b/test/spec/retryable-reads/legacy/changeStreams-db.watch-serverErrors.json deleted file mode 100644 index 7a87534508..0000000000 --- a/test/spec/retryable-reads/legacy/changeStreams-db.watch-serverErrors.json +++ /dev/null @@ -1,690 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ], - "serverless": "forbid" - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "tests": [ - { - "description": "db.watch succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 11600 - } - }, - "operations": [ - { - "name": "watch", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.watch succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 11602 - } - }, - "operations": [ - { - "name": "watch", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.watch succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "watch", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.watch succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 13435 - } - }, - "operations": [ - { - "name": "watch", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.watch succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 13436 - } - }, - "operations": [ - { - "name": "watch", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.watch succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 189 - } - }, - "operations": [ - { - "name": "watch", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.watch succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 91 - } - }, - "operations": [ - { - "name": "watch", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.watch succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 7 - } - }, - "operations": [ - { - "name": "watch", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.watch succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 6 - } - }, - "operations": [ - { - "name": "watch", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.watch succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 89 - } - }, - "operations": [ - { - "name": "watch", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.watch succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 9001 - } - }, - "operations": [ - { - "name": "watch", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.watch fails after two NotWritablePrimary errors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "watch", - "object": "database", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.watch fails after NotWritablePrimary when retryReads is false", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "watch", - "object": "database", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/changeStreams-db.watch-serverErrors.yml b/test/spec/retryable-reads/legacy/changeStreams-db.watch-serverErrors.yml deleted file mode 100644 index a527935bae..0000000000 --- a/test/spec/retryable-reads/legacy/changeStreams-db.watch-serverErrors.yml +++ /dev/null @@ -1,154 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - serverless: "forbid" - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - -tests: - - - description: "db.watch succeeds after InterruptedAtShutdown" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: { failCommands: [aggregate], errorCode: 11600 } - operations: - - &retryable_operation - name: watch - object: database - expectations: - - &retryable_command_started_event - command_started_event: - command: - aggregate: 1 - cursor: {} - pipeline: [ { $changeStream: { } } ] - database_name: *database_name - - *retryable_command_started_event - - - description: "db.watch succeeds after InterruptedDueToReplStateChange" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 11602 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.watch succeeds after NotWritablePrimary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 10107 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.watch succeeds after NotPrimaryNoSecondaryOk" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 13435 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.watch succeeds after NotPrimaryOrSecondary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 13436 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.watch succeeds after PrimarySteppedDown" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 189 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.watch succeeds after ShutdownInProgress" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 91 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.watch succeeds after HostNotFound" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 7 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.watch succeeds after HostUnreachable" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 6 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.watch succeeds after NetworkTimeout" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 89 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.watch succeeds after SocketException" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 9001 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.watch fails after two NotWritablePrimary errors" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - data: { failCommands: [aggregate], errorCode: 10107 } - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.watch fails after NotWritablePrimary when retryReads is false" - clientOptions: - retryReads: false - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 10107 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - - - diff --git a/test/spec/retryable-reads/legacy/changeStreams-db.watch.json b/test/spec/retryable-reads/legacy/changeStreams-db.watch.json deleted file mode 100644 index e6b0b9b781..0000000000 --- a/test/spec/retryable-reads/legacy/changeStreams-db.watch.json +++ /dev/null @@ -1,197 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ], - "serverless": "forbid" - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - } - ], - "tests": [ - { - "description": "db.watch succeeds on first attempt", - "operations": [ - { - "name": "watch", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.watch succeeds on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "watch", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.watch fails on first attempt", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "watch", - "object": "database", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "db.watch fails on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "watch", - "object": "database", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": 1, - "cursor": {}, - "pipeline": [ - { - "$changeStream": {} - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/changeStreams-db.watch.yml b/test/spec/retryable-reads/legacy/changeStreams-db.watch.yml deleted file mode 100644 index e2ceacbb66..0000000000 --- a/test/spec/retryable-reads/legacy/changeStreams-db.watch.yml +++ /dev/null @@ -1,62 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - serverless: "forbid" - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - {_id: 1, x: 11} - -tests: - - - description: "db.watch succeeds on first attempt" - operations: - - &retryable_operation - name: watch - object: database - expectations: - - &retryable_command_started_event - command_started_event: - command: - aggregate: 1 - cursor: {} - pipeline: [ { $changeStream: { } } ] - database_name: *database_name - - - description: "db.watch succeeds on second attempt" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: [aggregate] - closeConnection: true - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "db.watch fails on first attempt" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - - description: "db.watch fails on second attempt" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event diff --git a/test/spec/retryable-reads/legacy/count-serverErrors.json b/test/spec/retryable-reads/legacy/count-serverErrors.json deleted file mode 100644 index 36a0c17cab..0000000000 --- a/test/spec/retryable-reads/legacy/count-serverErrors.json +++ /dev/null @@ -1,586 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "Count succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 11600 - } - }, - "operations": [ - { - "name": "count", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Count succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 11602 - } - }, - "operations": [ - { - "name": "count", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Count succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "count", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Count succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 13435 - } - }, - "operations": [ - { - "name": "count", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Count succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 13436 - } - }, - "operations": [ - { - "name": "count", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Count succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 189 - } - }, - "operations": [ - { - "name": "count", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Count succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 91 - } - }, - "operations": [ - { - "name": "count", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Count succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 7 - } - }, - "operations": [ - { - "name": "count", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Count succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 6 - } - }, - "operations": [ - { - "name": "count", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Count succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 89 - } - }, - "operations": [ - { - "name": "count", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Count succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 9001 - } - }, - "operations": [ - { - "name": "count", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Count fails after two NotWritablePrimary errors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "count", - "object": "collection", - "arguments": { - "filter": {} - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Count fails after NotWritablePrimary when retryReads is false", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "count", - "object": "collection", - "arguments": { - "filter": {} - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/count-serverErrors.yml b/test/spec/retryable-reads/legacy/count-serverErrors.yml deleted file mode 100644 index 48ceaea68b..0000000000 --- a/test/spec/retryable-reads/legacy/count-serverErrors.yml +++ /dev/null @@ -1,150 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "Count succeeds after InterruptedAtShutdown" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: { failCommands: [count], errorCode: 11600 } - operations: - - &retryable_operation_succeeds - <<: &retryable_operation - name: count - object: collection - arguments: { filter: { } } - result: 2 - expectations: - - &retryable_command_started_event - command_started_event: - command: - count: *collection_name - database_name: *database_name - - *retryable_command_started_event - - - description: "Count succeeds after InterruptedDueToReplStateChange" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 11602 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Count succeeds after NotWritablePrimary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 10107 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Count succeeds after NotPrimaryNoSecondaryOk" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 13435 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Count succeeds after NotPrimaryOrSecondary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 13436 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Count succeeds after PrimarySteppedDown" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 189 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Count succeeds after ShutdownInProgress" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 91 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Count succeeds after HostNotFound" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 7 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Count succeeds after HostUnreachable" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 6 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Count succeeds after NetworkTimeout" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 89 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Count succeeds after SocketException" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 9001 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Count fails after two NotWritablePrimary errors" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - data: { failCommands: [count], errorCode: 10107 } - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Count fails after NotWritablePrimary when retryReads is false" - clientOptions: - retryReads: false - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 10107 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - diff --git a/test/spec/retryable-reads/legacy/count.json b/test/spec/retryable-reads/legacy/count.json deleted file mode 100644 index 139a545131..0000000000 --- a/test/spec/retryable-reads/legacy/count.json +++ /dev/null @@ -1,179 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "Count succeeds on first attempt", - "operations": [ - { - "name": "count", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Count succeeds on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "count", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Count fails on first attempt", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "count", - "object": "collection", - "arguments": { - "filter": {} - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Count fails on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "count" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "count", - "object": "collection", - "arguments": { - "filter": {} - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/count.yml b/test/spec/retryable-reads/legacy/count.yml deleted file mode 100644 index c9c3936b6b..0000000000 --- a/test/spec/retryable-reads/legacy/count.yml +++ /dev/null @@ -1,64 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "Count succeeds on first attempt" - operations: - - &retryable_operation_succeeds - <<: &retryable_operation - name: count - object: collection - arguments: { filter: { } } - result: 2 - expectations: - - &retryable_command_started_event - command_started_event: - command: - count: *collection_name - database_name: *database_name - - - description: "Count succeeds on second attempt" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: [count] - closeConnection: true - - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Count fails on first attempt" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - - description: "Count fails on second attempt" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event diff --git a/test/spec/retryable-reads/legacy/countDocuments-serverErrors.json b/test/spec/retryable-reads/legacy/countDocuments-serverErrors.json deleted file mode 100644 index 782ea5e4f1..0000000000 --- a/test/spec/retryable-reads/legacy/countDocuments-serverErrors.json +++ /dev/null @@ -1,911 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "CountDocuments succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 11600 - } - }, - "operations": [ - { - "name": "countDocuments", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "CountDocuments succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 11602 - } - }, - "operations": [ - { - "name": "countDocuments", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "CountDocuments succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "countDocuments", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "CountDocuments succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 13435 - } - }, - "operations": [ - { - "name": "countDocuments", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "CountDocuments succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 13436 - } - }, - "operations": [ - { - "name": "countDocuments", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "CountDocuments succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 189 - } - }, - "operations": [ - { - "name": "countDocuments", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "CountDocuments succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 91 - } - }, - "operations": [ - { - "name": "countDocuments", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "CountDocuments succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 7 - } - }, - "operations": [ - { - "name": "countDocuments", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "CountDocuments succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 6 - } - }, - "operations": [ - { - "name": "countDocuments", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "CountDocuments succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 89 - } - }, - "operations": [ - { - "name": "countDocuments", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "CountDocuments succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 9001 - } - }, - "operations": [ - { - "name": "countDocuments", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "CountDocuments fails after two NotWritablePrimary errors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "countDocuments", - "object": "collection", - "arguments": { - "filter": {} - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "CountDocuments fails after NotWritablePrimary when retryReads is false", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "countDocuments", - "object": "collection", - "arguments": { - "filter": {} - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/countDocuments-serverErrors.yml b/test/spec/retryable-reads/legacy/countDocuments-serverErrors.yml deleted file mode 100644 index 4ffb9a05b5..0000000000 --- a/test/spec/retryable-reads/legacy/countDocuments-serverErrors.yml +++ /dev/null @@ -1,150 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "CountDocuments succeeds after InterruptedAtShutdown" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: { failCommands: [aggregate], errorCode: 11600 } - operations: - - &retryable_operation_succeeds - <<: &retryable_operation - name: countDocuments - object: collection - arguments: { filter: { } } - result: 2 - expectations: - - &retryable_command_started_event - command_started_event: - command: - aggregate: *collection_name - pipeline: [{'$match': {}}, {'$group': {'_id': 1, 'n': {'$sum': 1}}}] - database_name: *database_name - - *retryable_command_started_event - - - description: "CountDocuments succeeds after InterruptedDueToReplStateChange" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 11602 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "CountDocuments succeeds after NotWritablePrimary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 10107 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "CountDocuments succeeds after NotPrimaryNoSecondaryOk" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 13435 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "CountDocuments succeeds after NotPrimaryOrSecondary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 13436 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "CountDocuments succeeds after PrimarySteppedDown" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 189 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "CountDocuments succeeds after ShutdownInProgress" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 91 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "CountDocuments succeeds after HostNotFound" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 7 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "CountDocuments succeeds after HostUnreachable" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 6 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "CountDocuments succeeds after NetworkTimeout" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 89 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "CountDocuments succeeds after SocketException" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 9001 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "CountDocuments fails after two NotWritablePrimary errors" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - data: { failCommands: [aggregate], errorCode: 10107 } - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "CountDocuments fails after NotWritablePrimary when retryReads is false" - clientOptions: - retryReads: false - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [aggregate], errorCode: 10107 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event diff --git a/test/spec/retryable-reads/legacy/countDocuments.json b/test/spec/retryable-reads/legacy/countDocuments.json deleted file mode 100644 index 57a64e45b7..0000000000 --- a/test/spec/retryable-reads/legacy/countDocuments.json +++ /dev/null @@ -1,257 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "CountDocuments succeeds on first attempt", - "operations": [ - { - "name": "countDocuments", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "CountDocuments succeeds on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "countDocuments", - "object": "collection", - "arguments": { - "filter": {} - }, - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "CountDocuments fails on first attempt", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "countDocuments", - "object": "collection", - "arguments": { - "filter": {} - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "CountDocuments fails on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "aggregate" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "countDocuments", - "object": "collection", - "arguments": { - "filter": {} - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "aggregate": "coll", - "pipeline": [ - { - "$match": {} - }, - { - "$group": { - "_id": 1, - "n": { - "$sum": 1 - } - } - } - ] - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/countDocuments.yml b/test/spec/retryable-reads/legacy/countDocuments.yml deleted file mode 100644 index 9e2565129c..0000000000 --- a/test/spec/retryable-reads/legacy/countDocuments.yml +++ /dev/null @@ -1,64 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "CountDocuments succeeds on first attempt" - operations: - - &retryable_operation_succeeds - <<: &retryable_operation - name: countDocuments - object: collection - arguments: { filter: { } } - result: 2 - expectations: - - &retryable_command_started_event - command_started_event: - command: - aggregate: *collection_name - pipeline: [{'$match': {}}, {'$group': {'_id': 1, 'n': {'$sum': 1}}}] - database_name: *database_name - - - description: "CountDocuments succeeds on second attempt" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: [aggregate] - closeConnection: true - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "CountDocuments fails on first attempt" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - - description: "CountDocuments fails on second attempt" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event diff --git a/test/spec/retryable-reads/legacy/distinct-serverErrors.json b/test/spec/retryable-reads/legacy/distinct-serverErrors.json deleted file mode 100644 index d7c6018a62..0000000000 --- a/test/spec/retryable-reads/legacy/distinct-serverErrors.json +++ /dev/null @@ -1,838 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "tests": [ - { - "description": "Distinct succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "distinct" - ], - "errorCode": 11600 - } - }, - "operations": [ - { - "name": "distinct", - "object": "collection", - "arguments": { - "fieldName": "x", - "filter": { - "_id": { - "$gt": 1 - } - } - }, - "result": [ - 22, - 33 - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Distinct succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "distinct" - ], - "errorCode": 11602 - } - }, - "operations": [ - { - "name": "distinct", - "object": "collection", - "arguments": { - "fieldName": "x", - "filter": { - "_id": { - "$gt": 1 - } - } - }, - "result": [ - 22, - 33 - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Distinct succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "distinct" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "distinct", - "object": "collection", - "arguments": { - "fieldName": "x", - "filter": { - "_id": { - "$gt": 1 - } - } - }, - "result": [ - 22, - 33 - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Distinct succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "distinct" - ], - "errorCode": 13435 - } - }, - "operations": [ - { - "name": "distinct", - "object": "collection", - "arguments": { - "fieldName": "x", - "filter": { - "_id": { - "$gt": 1 - } - } - }, - "result": [ - 22, - 33 - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Distinct succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "distinct" - ], - "errorCode": 13436 - } - }, - "operations": [ - { - "name": "distinct", - "object": "collection", - "arguments": { - "fieldName": "x", - "filter": { - "_id": { - "$gt": 1 - } - } - }, - "result": [ - 22, - 33 - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Distinct succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "distinct" - ], - "errorCode": 189 - } - }, - "operations": [ - { - "name": "distinct", - "object": "collection", - "arguments": { - "fieldName": "x", - "filter": { - "_id": { - "$gt": 1 - } - } - }, - "result": [ - 22, - 33 - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Distinct succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "distinct" - ], - "errorCode": 91 - } - }, - "operations": [ - { - "name": "distinct", - "object": "collection", - "arguments": { - "fieldName": "x", - "filter": { - "_id": { - "$gt": 1 - } - } - }, - "result": [ - 22, - 33 - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Distinct succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "distinct" - ], - "errorCode": 7 - } - }, - "operations": [ - { - "name": "distinct", - "object": "collection", - "arguments": { - "fieldName": "x", - "filter": { - "_id": { - "$gt": 1 - } - } - }, - "result": [ - 22, - 33 - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Distinct succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "distinct" - ], - "errorCode": 6 - } - }, - "operations": [ - { - "name": "distinct", - "object": "collection", - "arguments": { - "fieldName": "x", - "filter": { - "_id": { - "$gt": 1 - } - } - }, - "result": [ - 22, - 33 - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Distinct succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "distinct" - ], - "errorCode": 89 - } - }, - "operations": [ - { - "name": "distinct", - "object": "collection", - "arguments": { - "fieldName": "x", - "filter": { - "_id": { - "$gt": 1 - } - } - }, - "result": [ - 22, - 33 - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Distinct succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "distinct" - ], - "errorCode": 9001 - } - }, - "operations": [ - { - "name": "distinct", - "object": "collection", - "arguments": { - "fieldName": "x", - "filter": { - "_id": { - "$gt": 1 - } - } - }, - "result": [ - 22, - 33 - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Distinct fails after two NotWritablePrimary errors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "distinct" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "distinct", - "object": "collection", - "arguments": { - "fieldName": "x", - "filter": { - "_id": { - "$gt": 1 - } - } - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Distinct fails after NotWritablePrimary when retryReads is false", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "distinct" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "distinct", - "object": "collection", - "arguments": { - "fieldName": "x", - "filter": { - "_id": { - "$gt": 1 - } - } - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/distinct-serverErrors.yml b/test/spec/retryable-reads/legacy/distinct-serverErrors.yml deleted file mode 100644 index d4bc118ff6..0000000000 --- a/test/spec/retryable-reads/legacy/distinct-serverErrors.yml +++ /dev/null @@ -1,156 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - -tests: - - - description: "Distinct succeeds after InterruptedAtShutdown" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: { failCommands: [distinct], errorCode: 11600 } - operations: - - &retryable_operation_succeeds - <<: &retryable_operation - name: distinct - object: collection - arguments: { fieldName: "x", filter: { _id: { $gt: 1 } } } - result: - - 22 - - 33 - expectations: - - &retryable_command_started_event - command_started_event: - command: - distinct: *collection_name - key: "x" - query: - _id: {$gt: 1} - database_name: *database_name - - *retryable_command_started_event - - - description: "Distinct succeeds after InterruptedDueToReplStateChange" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [distinct], errorCode: 11602 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Distinct succeeds after NotWritablePrimary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [distinct], errorCode: 10107 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Distinct succeeds after NotPrimaryNoSecondaryOk" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [distinct], errorCode: 13435 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Distinct succeeds after NotPrimaryOrSecondary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [distinct], errorCode: 13436 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Distinct succeeds after PrimarySteppedDown" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [distinct], errorCode: 189 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Distinct succeeds after ShutdownInProgress" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [distinct], errorCode: 91 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Distinct succeeds after HostNotFound" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [distinct], errorCode: 7 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Distinct succeeds after HostUnreachable" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [distinct], errorCode: 6 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Distinct succeeds after NetworkTimeout" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [distinct], errorCode: 89 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Distinct succeeds after SocketException" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [distinct], errorCode: 9001 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Distinct fails after two NotWritablePrimary errors" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - data: { failCommands: [distinct], errorCode: 10107 } - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Distinct fails after NotWritablePrimary when retryReads is false" - clientOptions: - retryReads: false - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [distinct], errorCode: 10107 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - diff --git a/test/spec/retryable-reads/legacy/distinct.json b/test/spec/retryable-reads/legacy/distinct.json deleted file mode 100644 index 1fd415da81..0000000000 --- a/test/spec/retryable-reads/legacy/distinct.json +++ /dev/null @@ -1,245 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "tests": [ - { - "description": "Distinct succeeds on first attempt", - "operations": [ - { - "name": "distinct", - "object": "collection", - "arguments": { - "fieldName": "x", - "filter": { - "_id": { - "$gt": 1 - } - } - }, - "result": [ - 22, - 33 - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Distinct succeeds on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "distinct" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "distinct", - "object": "collection", - "arguments": { - "fieldName": "x", - "filter": { - "_id": { - "$gt": 1 - } - } - }, - "result": [ - 22, - 33 - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Distinct fails on first attempt", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "distinct" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "distinct", - "object": "collection", - "arguments": { - "fieldName": "x", - "filter": { - "_id": { - "$gt": 1 - } - } - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Distinct fails on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "distinct" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "distinct", - "object": "collection", - "arguments": { - "fieldName": "x", - "filter": { - "_id": { - "$gt": 1 - } - } - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "distinct": "coll", - "key": "x", - "query": { - "_id": { - "$gt": 1 - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/distinct.yml b/test/spec/retryable-reads/legacy/distinct.yml deleted file mode 100644 index 8ca2ac8315..0000000000 --- a/test/spec/retryable-reads/legacy/distinct.yml +++ /dev/null @@ -1,71 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - -tests: - - - description: "Distinct succeeds on first attempt" - operations: - - &retryable_operation_succeeds - <<: &retryable_operation - name: distinct - object: collection - arguments: { fieldName: "x", filter: { _id: { $gt: 1 } } } - result: - - 22 - - 33 - expectations: - - &retryable_command_started_event - command_started_event: - command: - distinct: *collection_name - key: "x" - query: - _id: {$gt: 1} - database_name: *database_name - - - description: "Distinct succeeds on second attempt" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: [distinct] - closeConnection: true - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Distinct fails on first attempt" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - - - description: "Distinct fails on second attempt" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - diff --git a/test/spec/retryable-reads/legacy/estimatedDocumentCount-serverErrors.json b/test/spec/retryable-reads/legacy/estimatedDocumentCount-serverErrors.json deleted file mode 100644 index 6bb128f5f3..0000000000 --- a/test/spec/retryable-reads/legacy/estimatedDocumentCount-serverErrors.json +++ /dev/null @@ -1,546 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "EstimatedDocumentCount succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 11600 - } - }, - "operations": [ - { - "name": "estimatedDocumentCount", - "object": "collection", - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "EstimatedDocumentCount succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 11602 - } - }, - "operations": [ - { - "name": "estimatedDocumentCount", - "object": "collection", - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "EstimatedDocumentCount succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "estimatedDocumentCount", - "object": "collection", - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "EstimatedDocumentCount succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 13435 - } - }, - "operations": [ - { - "name": "estimatedDocumentCount", - "object": "collection", - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "EstimatedDocumentCount succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 13436 - } - }, - "operations": [ - { - "name": "estimatedDocumentCount", - "object": "collection", - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "EstimatedDocumentCount succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 189 - } - }, - "operations": [ - { - "name": "estimatedDocumentCount", - "object": "collection", - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "EstimatedDocumentCount succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 91 - } - }, - "operations": [ - { - "name": "estimatedDocumentCount", - "object": "collection", - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "EstimatedDocumentCount succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 7 - } - }, - "operations": [ - { - "name": "estimatedDocumentCount", - "object": "collection", - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "EstimatedDocumentCount succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 6 - } - }, - "operations": [ - { - "name": "estimatedDocumentCount", - "object": "collection", - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "EstimatedDocumentCount succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 89 - } - }, - "operations": [ - { - "name": "estimatedDocumentCount", - "object": "collection", - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "EstimatedDocumentCount succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 9001 - } - }, - "operations": [ - { - "name": "estimatedDocumentCount", - "object": "collection", - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "EstimatedDocumentCount fails after two NotWritablePrimary errors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "estimatedDocumentCount", - "object": "collection", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "EstimatedDocumentCount fails after NotWritablePrimary when retryReads is false", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "estimatedDocumentCount", - "object": "collection", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/estimatedDocumentCount-serverErrors.yml b/test/spec/retryable-reads/legacy/estimatedDocumentCount-serverErrors.yml deleted file mode 100644 index aefb89ca69..0000000000 --- a/test/spec/retryable-reads/legacy/estimatedDocumentCount-serverErrors.yml +++ /dev/null @@ -1,148 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "EstimatedDocumentCount succeeds after InterruptedAtShutdown" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: { failCommands: [count], errorCode: 11600 } - operations: - - &retryable_operation_succeeds - <<: &retryable_operation - name: estimatedDocumentCount - object: collection - result: 2 - expectations: - - &retryable_command_started_event - command_started_event: - command: - count: *collection_name - database_name: *database_name - - *retryable_command_started_event - - - description: "EstimatedDocumentCount succeeds after InterruptedDueToReplStateChange" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 11602 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "EstimatedDocumentCount succeeds after NotWritablePrimary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 10107 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "EstimatedDocumentCount succeeds after NotPrimaryNoSecondaryOk" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 13435 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "EstimatedDocumentCount succeeds after NotPrimaryOrSecondary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 13436 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "EstimatedDocumentCount succeeds after PrimarySteppedDown" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 189 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "EstimatedDocumentCount succeeds after ShutdownInProgress" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 91 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "EstimatedDocumentCount succeeds after HostNotFound" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 7 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "EstimatedDocumentCount succeeds after HostUnreachable" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 6 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "EstimatedDocumentCount succeeds after NetworkTimeout" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 89 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "EstimatedDocumentCount succeeds after SocketException" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 9001 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "EstimatedDocumentCount fails after two NotWritablePrimary errors" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - data: { failCommands: [count], errorCode: 10107 } - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "EstimatedDocumentCount fails after NotWritablePrimary when retryReads is false" - clientOptions: - retryReads: false - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [count], errorCode: 10107 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event diff --git a/test/spec/retryable-reads/legacy/estimatedDocumentCount.json b/test/spec/retryable-reads/legacy/estimatedDocumentCount.json deleted file mode 100644 index 8dfa15a2cd..0000000000 --- a/test/spec/retryable-reads/legacy/estimatedDocumentCount.json +++ /dev/null @@ -1,166 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "EstimatedDocumentCount succeeds on first attempt", - "operations": [ - { - "name": "estimatedDocumentCount", - "object": "collection", - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "EstimatedDocumentCount succeeds on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "estimatedDocumentCount", - "object": "collection", - "result": 2 - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "EstimatedDocumentCount fails on first attempt", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "count" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "estimatedDocumentCount", - "object": "collection", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "EstimatedDocumentCount fails on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "count" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "estimatedDocumentCount", - "object": "collection", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "count": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/estimatedDocumentCount.yml b/test/spec/retryable-reads/legacy/estimatedDocumentCount.yml deleted file mode 100644 index de03e483bb..0000000000 --- a/test/spec/retryable-reads/legacy/estimatedDocumentCount.yml +++ /dev/null @@ -1,62 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "EstimatedDocumentCount succeeds on first attempt" - operations: - - &retryable_operation_succeeds - <<: &retryable_operation - name: estimatedDocumentCount - object: collection - result: 2 - expectations: - - &retryable_command_started_event - command_started_event: - command: - count: *collection_name - database_name: *database_name - - - description: "EstimatedDocumentCount succeeds on second attempt" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: [count] - closeConnection: true - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "EstimatedDocumentCount fails on first attempt" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - - description: "EstimatedDocumentCount fails on second attempt" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event diff --git a/test/spec/retryable-reads/legacy/find-serverErrors.json b/test/spec/retryable-reads/legacy/find-serverErrors.json deleted file mode 100644 index f6b96c6dcb..0000000000 --- a/test/spec/retryable-reads/legacy/find-serverErrors.json +++ /dev/null @@ -1,962 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - }, - { - "_id": 5, - "x": 55 - } - ], - "tests": [ - { - "description": "Find succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 11600 - } - }, - "operations": [ - { - "name": "find", - "object": "collection", - "arguments": { - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "result": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Find succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 11602 - } - }, - "operations": [ - { - "name": "find", - "object": "collection", - "arguments": { - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "result": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Find succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "find", - "object": "collection", - "arguments": { - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "result": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Find succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 13435 - } - }, - "operations": [ - { - "name": "find", - "object": "collection", - "arguments": { - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "result": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Find succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 13436 - } - }, - "operations": [ - { - "name": "find", - "object": "collection", - "arguments": { - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "result": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Find succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 189 - } - }, - "operations": [ - { - "name": "find", - "object": "collection", - "arguments": { - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "result": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Find succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 91 - } - }, - "operations": [ - { - "name": "find", - "object": "collection", - "arguments": { - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "result": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Find succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 7 - } - }, - "operations": [ - { - "name": "find", - "object": "collection", - "arguments": { - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "result": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Find succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 6 - } - }, - "operations": [ - { - "name": "find", - "object": "collection", - "arguments": { - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "result": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Find succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 89 - } - }, - "operations": [ - { - "name": "find", - "object": "collection", - "arguments": { - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "result": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Find succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 9001 - } - }, - "operations": [ - { - "name": "find", - "object": "collection", - "arguments": { - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "result": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Find fails after two NotWritablePrimary errors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "find", - "object": "collection", - "arguments": { - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Find fails after NotWritablePrimary when retryReads is false", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "find", - "object": "collection", - "arguments": { - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/find-serverErrors.yml b/test/spec/retryable-reads/legacy/find-serverErrors.yml deleted file mode 100644 index e122f3e2c8..0000000000 --- a/test/spec/retryable-reads/legacy/find-serverErrors.yml +++ /dev/null @@ -1,160 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - {_id: 4, x: 44} - - {_id: 5, x: 55} - -tests: - - - description: "Find succeeds after InterruptedAtShutdown" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: { failCommands: [find], errorCode: 11600 } - operations: - - &retryable_operation_succeeds - <<: &retryable_operation - name: find - object: collection - arguments: { filter: {}, sort: { _id: 1 }, limit: 4 } - result: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - {_id: 4, x: 44} - expectations: - - &retryable_command_started_event - command_started_event: - command: - find: *collection_name - filter: {} - sort: {_id: 1} - limit: 4 - database_name: *database_name - - *retryable_command_started_event - - - description: "Find succeeds after InterruptedDueToReplStateChange" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 11602 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Find succeeds after NotWritablePrimary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 10107 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Find succeeds after NotPrimaryNoSecondaryOk" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 13435 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Find succeeds after NotPrimaryOrSecondary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 13436 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Find succeeds after PrimarySteppedDown" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 189 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Find succeeds after ShutdownInProgress" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 91 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Find succeeds after HostNotFound" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 7 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Find succeeds after HostUnreachable" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 6 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Find succeeds after NetworkTimeout" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 89 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Find succeeds after SocketException" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 9001 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Find fails after two NotWritablePrimary errors" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - data: { failCommands: [find], errorCode: 10107 } - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Find fails after NotWritablePrimary when retryReads is false" - clientOptions: - retryReads: false - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 10107 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - diff --git a/test/spec/retryable-reads/legacy/find.json b/test/spec/retryable-reads/legacy/find.json deleted file mode 100644 index 00d419c0da..0000000000 --- a/test/spec/retryable-reads/legacy/find.json +++ /dev/null @@ -1,348 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - }, - { - "_id": 5, - "x": 55 - } - ], - "tests": [ - { - "description": "Find succeeds on first attempt", - "operations": [ - { - "name": "find", - "object": "collection", - "arguments": { - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "result": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Find succeeds on second attempt with explicit clientOptions", - "clientOptions": { - "retryReads": true - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "find", - "object": "collection", - "arguments": { - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "result": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Find succeeds on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "find", - "object": "collection", - "arguments": { - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "result": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Find fails on first attempt", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "find", - "object": "collection", - "arguments": { - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Find fails on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "find" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "find", - "object": "collection", - "arguments": { - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": {}, - "sort": { - "_id": 1 - }, - "limit": 4 - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/find.yml b/test/spec/retryable-reads/legacy/find.yml deleted file mode 100644 index b685c07b6a..0000000000 --- a/test/spec/retryable-reads/legacy/find.yml +++ /dev/null @@ -1,86 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - {_id: 4, x: 44} - - {_id: 5, x: 55} - -tests: - - - description: "Find succeeds on first attempt" - operations: - - &retryable_operation_succeeds - <<: &retryable_operation - name: find - object: collection - arguments: - filter: {} - sort: {_id: 1} - limit: 4 - result: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - {_id: 4, x: 44} - expectations: - - &retryable_command_started_event - command_started_event: - command: - find: *collection_name - filter: {} - sort: {_id: 1} - limit: 4 - database_name: *database_name - - - description: "Find succeeds on second attempt with explicit clientOptions" - clientOptions: - retryReads: true - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: [find] - closeConnection: true - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Find succeeds on second attempt" - failPoint: *failCommand_failPoint - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Find fails on first attempt" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - - description: "Find fails on second attempt" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - diff --git a/test/spec/retryable-reads/legacy/findOne-serverErrors.json b/test/spec/retryable-reads/legacy/findOne-serverErrors.json deleted file mode 100644 index d039ef247e..0000000000 --- a/test/spec/retryable-reads/legacy/findOne-serverErrors.json +++ /dev/null @@ -1,732 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - }, - { - "_id": 5, - "x": 55 - } - ], - "tests": [ - { - "description": "FindOne succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 11600 - } - }, - "operations": [ - { - "name": "findOne", - "object": "collection", - "arguments": { - "filter": { - "_id": 1 - } - }, - "result": { - "_id": 1, - "x": 11 - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "FindOne succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 11602 - } - }, - "operations": [ - { - "name": "findOne", - "object": "collection", - "arguments": { - "filter": { - "_id": 1 - } - }, - "result": { - "_id": 1, - "x": 11 - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "FindOne succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "findOne", - "object": "collection", - "arguments": { - "filter": { - "_id": 1 - } - }, - "result": { - "_id": 1, - "x": 11 - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "FindOne succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 13435 - } - }, - "operations": [ - { - "name": "findOne", - "object": "collection", - "arguments": { - "filter": { - "_id": 1 - } - }, - "result": { - "_id": 1, - "x": 11 - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "FindOne succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 13436 - } - }, - "operations": [ - { - "name": "findOne", - "object": "collection", - "arguments": { - "filter": { - "_id": 1 - } - }, - "result": { - "_id": 1, - "x": 11 - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "FindOne succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 189 - } - }, - "operations": [ - { - "name": "findOne", - "object": "collection", - "arguments": { - "filter": { - "_id": 1 - } - }, - "result": { - "_id": 1, - "x": 11 - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "FindOne succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 91 - } - }, - "operations": [ - { - "name": "findOne", - "object": "collection", - "arguments": { - "filter": { - "_id": 1 - } - }, - "result": { - "_id": 1, - "x": 11 - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "FindOne succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 7 - } - }, - "operations": [ - { - "name": "findOne", - "object": "collection", - "arguments": { - "filter": { - "_id": 1 - } - }, - "result": { - "_id": 1, - "x": 11 - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "FindOne succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 6 - } - }, - "operations": [ - { - "name": "findOne", - "object": "collection", - "arguments": { - "filter": { - "_id": 1 - } - }, - "result": { - "_id": 1, - "x": 11 - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "FindOne succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 89 - } - }, - "operations": [ - { - "name": "findOne", - "object": "collection", - "arguments": { - "filter": { - "_id": 1 - } - }, - "result": { - "_id": 1, - "x": 11 - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "FindOne succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 9001 - } - }, - "operations": [ - { - "name": "findOne", - "object": "collection", - "arguments": { - "filter": { - "_id": 1 - } - }, - "result": { - "_id": 1, - "x": 11 - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "FindOne fails after two NotWritablePrimary errors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "findOne", - "object": "collection", - "arguments": { - "filter": { - "_id": 1 - } - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "FindOne fails after NotWritablePrimary when retryReads is false", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "findOne", - "object": "collection", - "arguments": { - "filter": { - "_id": 1 - } - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/findOne-serverErrors.yml b/test/spec/retryable-reads/legacy/findOne-serverErrors.yml deleted file mode 100644 index b6e7657408..0000000000 --- a/test/spec/retryable-reads/legacy/findOne-serverErrors.yml +++ /dev/null @@ -1,154 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - {_id: 4, x: 44} - - {_id: 5, x: 55} - -tests: - - - description: "FindOne succeeds after InterruptedAtShutdown" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: { failCommands: [find], errorCode: 11600 } - operations: - - &retryable_operation_succeeds - <<: &retryable_operation - name: findOne - object: collection - arguments: - filter: {_id: 1} - result: {_id: 1, x: 11} - expectations: - - &retryable_command_started_event - command_started_event: - command: - find: *collection_name - filter: {_id: 1} - database_name: *database_name - - *retryable_command_started_event - - - description: "FindOne succeeds after InterruptedDueToReplStateChange" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 11602 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "FindOne succeeds after NotWritablePrimary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 10107 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "FindOne succeeds after NotPrimaryNoSecondaryOk" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 13435 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "FindOne succeeds after NotPrimaryOrSecondary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 13436 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "FindOne succeeds after PrimarySteppedDown" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 189 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "FindOne succeeds after ShutdownInProgress" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 91 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "FindOne succeeds after HostNotFound" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 7 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "FindOne succeeds after HostUnreachable" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 6 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "FindOne succeeds after NetworkTimeout" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 89 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "FindOne succeeds after SocketException" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 9001 } - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "FindOne fails after two NotWritablePrimary errors" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - data: { failCommands: [find], errorCode: 10107 } - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "FindOne fails after NotWritablePrimary when retryReads is false" - clientOptions: - retryReads: false - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 10107 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event diff --git a/test/spec/retryable-reads/legacy/findOne.json b/test/spec/retryable-reads/legacy/findOne.json deleted file mode 100644 index b9deb73d2a..0000000000 --- a/test/spec/retryable-reads/legacy/findOne.json +++ /dev/null @@ -1,223 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - }, - { - "_id": 5, - "x": 55 - } - ], - "tests": [ - { - "description": "FindOne succeeds on first attempt", - "operations": [ - { - "name": "findOne", - "object": "collection", - "arguments": { - "filter": { - "_id": 1 - } - }, - "result": { - "_id": 1, - "x": 11 - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "FindOne succeeds on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "findOne", - "object": "collection", - "arguments": { - "filter": { - "_id": 1 - } - }, - "result": { - "_id": 1, - "x": 11 - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "FindOne fails on first attempt", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "findOne", - "object": "collection", - "arguments": { - "filter": { - "_id": 1 - } - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "FindOne fails on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "find" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "findOne", - "object": "collection", - "arguments": { - "filter": { - "_id": 1 - } - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "coll", - "filter": { - "_id": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/findOne.yml b/test/spec/retryable-reads/legacy/findOne.yml deleted file mode 100644 index 911314e98e..0000000000 --- a/test/spec/retryable-reads/legacy/findOne.yml +++ /dev/null @@ -1,68 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - {_id: 1, x: 11} - - {_id: 2, x: 22} - - {_id: 3, x: 33} - - {_id: 4, x: 44} - - {_id: 5, x: 55} - -tests: - - - description: "FindOne succeeds on first attempt" - operations: - - &retryable_operation_succeeds - <<: &retryable_operation - name: findOne - object: collection - arguments: {filter: {_id: 1 }} - result: {_id: 1, x: 11} - expectations: - - &retryable_command_started_event - command_started_event: - command: - find: *collection_name - filter: {_id: 1} - database_name: *database_name - - - description: "FindOne succeeds on second attempt" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: [find] - closeConnection: true - operations: [*retryable_operation_succeeds] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "FindOne fails on first attempt" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - - description: "FindOne fails on second attempt" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - diff --git a/test/spec/retryable-reads/legacy/gridfs-download-serverErrors.json b/test/spec/retryable-reads/legacy/gridfs-download-serverErrors.json deleted file mode 100644 index cec3a5016a..0000000000 --- a/test/spec/retryable-reads/legacy/gridfs-download-serverErrors.json +++ /dev/null @@ -1,925 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "bucket_name": "fs", - "data": { - "fs.files": [ - { - "_id": { - "$oid": "000000000000000000000001" - }, - "length": 1, - "chunkSize": 4, - "uploadDate": { - "$date": "1970-01-01T00:00:00.000Z" - }, - "filename": "abc", - "metadata": {} - } - ], - "fs.chunks": [ - { - "_id": { - "$oid": "000000000000000000000002" - }, - "files_id": { - "$oid": "000000000000000000000001" - }, - "n": 0, - "data": { - "$binary": { - "base64": "EQ==", - "subType": "00" - } - } - } - ] - }, - "tests": [ - { - "description": "Download succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 11600 - } - }, - "operations": [ - { - "name": "download", - "object": "gridfsbucket", - "arguments": { - "id": { - "$oid": "000000000000000000000001" - } - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Download succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 11602 - } - }, - "operations": [ - { - "name": "download", - "object": "gridfsbucket", - "arguments": { - "id": { - "$oid": "000000000000000000000001" - } - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Download succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "download", - "object": "gridfsbucket", - "arguments": { - "id": { - "$oid": "000000000000000000000001" - } - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Download succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 13435 - } - }, - "operations": [ - { - "name": "download", - "object": "gridfsbucket", - "arguments": { - "id": { - "$oid": "000000000000000000000001" - } - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Download succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 13436 - } - }, - "operations": [ - { - "name": "download", - "object": "gridfsbucket", - "arguments": { - "id": { - "$oid": "000000000000000000000001" - } - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Download succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 189 - } - }, - "operations": [ - { - "name": "download", - "object": "gridfsbucket", - "arguments": { - "id": { - "$oid": "000000000000000000000001" - } - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Download succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 91 - } - }, - "operations": [ - { - "name": "download", - "object": "gridfsbucket", - "arguments": { - "id": { - "$oid": "000000000000000000000001" - } - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Download succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 7 - } - }, - "operations": [ - { - "name": "download", - "object": "gridfsbucket", - "arguments": { - "id": { - "$oid": "000000000000000000000001" - } - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Download succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 6 - } - }, - "operations": [ - { - "name": "download", - "object": "gridfsbucket", - "arguments": { - "id": { - "$oid": "000000000000000000000001" - } - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Download succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 89 - } - }, - "operations": [ - { - "name": "download", - "object": "gridfsbucket", - "arguments": { - "id": { - "$oid": "000000000000000000000001" - } - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Download succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 9001 - } - }, - "operations": [ - { - "name": "download", - "object": "gridfsbucket", - "arguments": { - "id": { - "$oid": "000000000000000000000001" - } - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Download fails after two NotWritablePrimary errors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "download", - "object": "gridfsbucket", - "arguments": { - "id": { - "$oid": "000000000000000000000001" - } - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Download fails after NotWritablePrimary when retryReads is false", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "download", - "object": "gridfsbucket", - "arguments": { - "id": { - "$oid": "000000000000000000000001" - } - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/gridfs-download-serverErrors.yml b/test/spec/retryable-reads/legacy/gridfs-download-serverErrors.yml deleted file mode 100644 index e120c162fd..0000000000 --- a/test/spec/retryable-reads/legacy/gridfs-download-serverErrors.yml +++ /dev/null @@ -1,173 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -bucket_name: "fs" - -data: - fs.files: - - - _id: { $oid : "000000000000000000000001" } - length: 1 - chunkSize: 4 - uploadDate: { $date : "1970-01-01T00:00:00.000Z" } - filename: abc - metadata: {} - fs.chunks: - - { _id: { $oid: "000000000000000000000002" }, files_id: { $oid: "000000000000000000000001" }, n: 0, data: { $binary: { base64: "EQ==", subType: "00" } } } - -tests: - - - description: "Download succeeds after InterruptedAtShutdown" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: { failCommands: [find], errorCode: 11600 } - operations: - - &retryable_operation - name: download - object: gridfsbucket - arguments: { id: { "$oid" : "000000000000000000000001" } } - expectations: - - &retryable_command_started_event - command_started_event: - command: - find: fs.files - filter: { _id: {$oid : "000000000000000000000001" }} - database_name: *database_name - - *retryable_command_started_event - - &find_chunks_command_started_event - command_started_event: - command: - find: fs.chunks - filter: { files_id: {$oid : "000000000000000000000001" }} - sort: { n: 1 } - database_name: *database_name - - - description: "Download succeeds after InterruptedDueToReplStateChange" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 11602 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "Download succeeds after NotWritablePrimary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 10107 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "Download succeeds after NotPrimaryNoSecondaryOk" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 13435 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "Download succeeds after NotPrimaryOrSecondary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 13436 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "Download succeeds after PrimarySteppedDown" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 189 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "Download succeeds after ShutdownInProgress" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 91 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "Download succeeds after HostNotFound" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 7 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "Download succeeds after HostUnreachable" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 6 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "Download succeeds after NetworkTimeout" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 89 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "Download succeeds after SocketException" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 9001 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "Download fails after two NotWritablePrimary errors" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - data: { failCommands: [find], errorCode: 10107 } - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "Download fails after NotWritablePrimary when retryReads is false" - clientOptions: - retryReads: false - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 10107 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event diff --git a/test/spec/retryable-reads/legacy/gridfs-download.json b/test/spec/retryable-reads/legacy/gridfs-download.json deleted file mode 100644 index 4d0d5a17e4..0000000000 --- a/test/spec/retryable-reads/legacy/gridfs-download.json +++ /dev/null @@ -1,270 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "bucket_name": "fs", - "data": { - "fs.files": [ - { - "_id": { - "$oid": "000000000000000000000001" - }, - "length": 1, - "chunkSize": 4, - "uploadDate": { - "$date": "1970-01-01T00:00:00.000Z" - }, - "filename": "abc", - "metadata": {} - } - ], - "fs.chunks": [ - { - "_id": { - "$oid": "000000000000000000000002" - }, - "files_id": { - "$oid": "000000000000000000000001" - }, - "n": 0, - "data": { - "$binary": { - "base64": "EQ==", - "subType": "00" - } - } - } - ] - }, - "tests": [ - { - "description": "Download succeeds on first attempt", - "operations": [ - { - "name": "download", - "object": "gridfsbucket", - "arguments": { - "id": { - "$oid": "000000000000000000000001" - } - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Download succeeds on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "download", - "object": "gridfsbucket", - "arguments": { - "id": { - "$oid": "000000000000000000000001" - } - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Download fails on first attempt", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "download", - "object": "gridfsbucket", - "arguments": { - "id": { - "$oid": "000000000000000000000001" - } - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "Download fails on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "find" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "download", - "object": "gridfsbucket", - "arguments": { - "id": { - "$oid": "000000000000000000000001" - } - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "_id": { - "$oid": "000000000000000000000001" - } - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/gridfs-download.yml b/test/spec/retryable-reads/legacy/gridfs-download.yml deleted file mode 100644 index a71c719d9a..0000000000 --- a/test/spec/retryable-reads/legacy/gridfs-download.yml +++ /dev/null @@ -1,79 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -bucket_name: "fs" - -data: - fs.files: - - - _id: { $oid : "000000000000000000000001" } - length: 1 - chunkSize: 4 - uploadDate: { $date : "1970-01-01T00:00:00.000Z" } - filename: abc - metadata: {} - fs.chunks: - - { _id: { $oid: "000000000000000000000002" }, files_id: { $oid: "000000000000000000000001" }, n: 0, data: { $binary: { base64: "EQ==", subType: "00" } } } - -tests: - - - description: "Download succeeds on first attempt" - operations: - - &retryable_operation - name: download - object: gridfsbucket - arguments: { id: { "$oid" : "000000000000000000000001" } } - expectations: - - &retryable_command_started_event - command_started_event: - command: - find: fs.files - filter: { _id: {$oid : "000000000000000000000001" }} - database_name: *database_name - - &find_chunks_command_started_event - command_started_event: - command: - find: fs.chunks - filter: { files_id: {$oid : "000000000000000000000001" }} - sort: { n: 1 } - database_name: *database_name - - - description: "Download succeeds on second attempt" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: [find] - closeConnection: true - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "Download fails on first attempt" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - - description: "Download fails on second attempt" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - diff --git a/test/spec/retryable-reads/legacy/gridfs-downloadByName-serverErrors.json b/test/spec/retryable-reads/legacy/gridfs-downloadByName-serverErrors.json deleted file mode 100644 index a64230d38a..0000000000 --- a/test/spec/retryable-reads/legacy/gridfs-downloadByName-serverErrors.json +++ /dev/null @@ -1,849 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "bucket_name": "fs", - "data": { - "fs.files": [ - { - "_id": { - "$oid": "000000000000000000000001" - }, - "length": 1, - "chunkSize": 4, - "uploadDate": { - "$date": "1970-01-01T00:00:00.000Z" - }, - "filename": "abc", - "metadata": {} - } - ], - "fs.chunks": [ - { - "_id": { - "$oid": "000000000000000000000002" - }, - "files_id": { - "$oid": "000000000000000000000001" - }, - "n": 0, - "data": { - "$binary": { - "base64": "EQ==", - "subType": "00" - } - } - } - ] - }, - "tests": [ - { - "description": "DownloadByName succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 11600 - } - }, - "operations": [ - { - "name": "download_by_name", - "object": "gridfsbucket", - "arguments": { - "filename": "abc" - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "DownloadByName succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 11602 - } - }, - "operations": [ - { - "name": "download_by_name", - "object": "gridfsbucket", - "arguments": { - "filename": "abc" - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "DownloadByName succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "download_by_name", - "object": "gridfsbucket", - "arguments": { - "filename": "abc" - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "DownloadByName succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 13435 - } - }, - "operations": [ - { - "name": "download_by_name", - "object": "gridfsbucket", - "arguments": { - "filename": "abc" - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "DownloadByName succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 13436 - } - }, - "operations": [ - { - "name": "download_by_name", - "object": "gridfsbucket", - "arguments": { - "filename": "abc" - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "DownloadByName succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 189 - } - }, - "operations": [ - { - "name": "download_by_name", - "object": "gridfsbucket", - "arguments": { - "filename": "abc" - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "DownloadByName succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 91 - } - }, - "operations": [ - { - "name": "download_by_name", - "object": "gridfsbucket", - "arguments": { - "filename": "abc" - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "DownloadByName succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 7 - } - }, - "operations": [ - { - "name": "download_by_name", - "object": "gridfsbucket", - "arguments": { - "filename": "abc" - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "DownloadByName succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 6 - } - }, - "operations": [ - { - "name": "download_by_name", - "object": "gridfsbucket", - "arguments": { - "filename": "abc" - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "DownloadByName succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 89 - } - }, - "operations": [ - { - "name": "download_by_name", - "object": "gridfsbucket", - "arguments": { - "filename": "abc" - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "DownloadByName succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 9001 - } - }, - "operations": [ - { - "name": "download_by_name", - "object": "gridfsbucket", - "arguments": { - "filename": "abc" - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "DownloadByName fails after two NotWritablePrimary errors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "download_by_name", - "object": "gridfsbucket", - "arguments": { - "filename": "abc" - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "DownloadByName fails after NotWritablePrimary when retryReads is false", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "download_by_name", - "object": "gridfsbucket", - "arguments": { - "filename": "abc" - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/gridfs-downloadByName-serverErrors.yml b/test/spec/retryable-reads/legacy/gridfs-downloadByName-serverErrors.yml deleted file mode 100644 index 704492135e..0000000000 --- a/test/spec/retryable-reads/legacy/gridfs-downloadByName-serverErrors.yml +++ /dev/null @@ -1,174 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -bucket_name: "fs" - -data: - fs.files: - - - _id: { $oid : "000000000000000000000001" } - length: 1 - chunkSize: 4 - uploadDate: { $date : "1970-01-01T00:00:00.000Z" } - filename: abc - metadata: {} - fs.chunks: - - { _id: { $oid: "000000000000000000000002" }, files_id: { $oid: "000000000000000000000001" }, n: 0, data: { $binary: { base64: "EQ==", subType: "00" } } } - -tests: - - - description: "DownloadByName succeeds after InterruptedAtShutdown" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: { failCommands: [find], errorCode: 11600 } - operations: - - &retryable_operation - name: download_by_name - object: gridfsbucket - arguments: - filename: abc - expectations: - - &retryable_command_started_event - command_started_event: - command: - find: fs.files - filter: { filename : "abc" } - database_name: *database_name - - *retryable_command_started_event - - &find_chunks_command_started_event - command_started_event: - command: - find: fs.chunks - filter: { files_id: { $oid : "000000000000000000000001" }} - sort: { n: 1 } - database_name: *database_name - - - description: "DownloadByName succeeds after InterruptedDueToReplStateChange" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 11602 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "DownloadByName succeeds after NotWritablePrimary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 10107 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "DownloadByName succeeds after NotPrimaryNoSecondaryOk" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 13435 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "DownloadByName succeeds after NotPrimaryOrSecondary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 13436 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "DownloadByName succeeds after PrimarySteppedDown" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 189 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "DownloadByName succeeds after ShutdownInProgress" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 91 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "DownloadByName succeeds after HostNotFound" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 7 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "DownloadByName succeeds after HostUnreachable" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 6 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "DownloadByName succeeds after NetworkTimeout" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 89 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "DownloadByName succeeds after SocketException" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 9001 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "DownloadByName fails after two NotWritablePrimary errors" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - data: { failCommands: [find], errorCode: 10107 } - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "DownloadByName fails after NotWritablePrimary when retryReads is false" - clientOptions: - retryReads: false - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [find], errorCode: 10107 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event diff --git a/test/spec/retryable-reads/legacy/gridfs-downloadByName.json b/test/spec/retryable-reads/legacy/gridfs-downloadByName.json deleted file mode 100644 index 48f2168cfc..0000000000 --- a/test/spec/retryable-reads/legacy/gridfs-downloadByName.json +++ /dev/null @@ -1,250 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "bucket_name": "fs", - "data": { - "fs.files": [ - { - "_id": { - "$oid": "000000000000000000000001" - }, - "length": 1, - "chunkSize": 4, - "uploadDate": { - "$date": "1970-01-01T00:00:00.000Z" - }, - "filename": "abc", - "metadata": {} - } - ], - "fs.chunks": [ - { - "_id": { - "$oid": "000000000000000000000002" - }, - "files_id": { - "$oid": "000000000000000000000001" - }, - "n": 0, - "data": { - "$binary": { - "base64": "EQ==", - "subType": "00" - } - } - } - ] - }, - "tests": [ - { - "description": "DownloadByName succeeds on first attempt", - "operations": [ - { - "name": "download_by_name", - "object": "gridfsbucket", - "arguments": { - "filename": "abc" - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "DownloadByName succeeds on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "download_by_name", - "object": "gridfsbucket", - "arguments": { - "filename": "abc" - } - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.chunks", - "filter": { - "files_id": { - "$oid": "000000000000000000000001" - } - }, - "sort": { - "n": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "DownloadByName fails on first attempt", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "find" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "download_by_name", - "object": "gridfsbucket", - "arguments": { - "filename": "abc" - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "DownloadByName fails on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "find" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "download_by_name", - "object": "gridfsbucket", - "arguments": { - "filename": "abc" - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "find": "fs.files", - "filter": { - "filename": "abc" - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/gridfs-downloadByName.yml b/test/spec/retryable-reads/legacy/gridfs-downloadByName.yml deleted file mode 100644 index e5586954f0..0000000000 --- a/test/spec/retryable-reads/legacy/gridfs-downloadByName.yml +++ /dev/null @@ -1,79 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -bucket_name: "fs" - -data: - fs.files: - - - _id: { $oid : "000000000000000000000001" } - length: 1 - chunkSize: 4 - uploadDate: { $date : "1970-01-01T00:00:00.000Z" } - filename: abc - metadata: {} - fs.chunks: - - { _id: { $oid: "000000000000000000000002" }, files_id: { $oid: "000000000000000000000001" }, n: 0, data: { $binary: { base64: "EQ==", subType: "00" } } } - -tests: - - - description: "DownloadByName succeeds on first attempt" - operations: - - &retryable_operation - name: download_by_name - object: gridfsbucket - arguments: { filename: "abc" } - expectations: - - &retryable_command_started_event - command_started_event: - command: - find: fs.files - filter: { filename : "abc" } - database_name: *database_name - - &find_chunks_command_started_event - command_started_event: - command: - find: fs.chunks - filter: { files_id: {$oid : "000000000000000000000001"} } - sort: { n: 1 } - database_name: *database_name - - - description: "DownloadByName succeeds on second attempt" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: [find] - closeConnection: true - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - *find_chunks_command_started_event - - - description: "DownloadByName fails on first attempt" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - - description: "DownloadByName fails on second attempt" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - diff --git a/test/spec/retryable-reads/legacy/listCollectionNames-serverErrors.json b/test/spec/retryable-reads/legacy/listCollectionNames-serverErrors.json deleted file mode 100644 index bbdce625ad..0000000000 --- a/test/spec/retryable-reads/legacy/listCollectionNames-serverErrors.json +++ /dev/null @@ -1,502 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [], - "tests": [ - { - "description": "ListCollectionNames succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 11600 - } - }, - "operations": [ - { - "name": "listCollectionNames", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionNames succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 11602 - } - }, - "operations": [ - { - "name": "listCollectionNames", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionNames succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listCollectionNames", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionNames succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 13435 - } - }, - "operations": [ - { - "name": "listCollectionNames", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionNames succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 13436 - } - }, - "operations": [ - { - "name": "listCollectionNames", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionNames succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 189 - } - }, - "operations": [ - { - "name": "listCollectionNames", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionNames succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 91 - } - }, - "operations": [ - { - "name": "listCollectionNames", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionNames succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 7 - } - }, - "operations": [ - { - "name": "listCollectionNames", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionNames succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 6 - } - }, - "operations": [ - { - "name": "listCollectionNames", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionNames succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 89 - } - }, - "operations": [ - { - "name": "listCollectionNames", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionNames succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 9001 - } - }, - "operations": [ - { - "name": "listCollectionNames", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionNames fails after two NotWritablePrimary errors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listCollectionNames", - "object": "database", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionNames fails after NotWritablePrimary when retryReads is false", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listCollectionNames", - "object": "database", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/listCollectionNames-serverErrors.yml b/test/spec/retryable-reads/legacy/listCollectionNames-serverErrors.yml deleted file mode 100644 index b99bddf827..0000000000 --- a/test/spec/retryable-reads/legacy/listCollectionNames-serverErrors.yml +++ /dev/null @@ -1,143 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: [] - -tests: - - - description: "ListCollectionNames succeeds after InterruptedAtShutdown" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: { failCommands: [listCollections], errorCode: 11600 } - operations: - - &retryable_operation - name: listCollectionNames - object: database - expectations: - - &retryable_command_started_event - command_started_event: - command: - listCollections: 1 - - *retryable_command_started_event - - - description: "ListCollectionNames succeeds after InterruptedDueToReplStateChange" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 11602 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionNames succeeds after NotWritablePrimary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 10107 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionNames succeeds after NotPrimaryNoSecondaryOk" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 13435 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionNames succeeds after NotPrimaryOrSecondary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 13436 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionNames succeeds after PrimarySteppedDown" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 189 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionNames succeeds after ShutdownInProgress" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 91 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionNames succeeds after HostNotFound" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 7 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionNames succeeds after HostUnreachable" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 6 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionNames succeeds after NetworkTimeout" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 89 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionNames succeeds after SocketException" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 9001 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionNames fails after two NotWritablePrimary errors" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - data: { failCommands: [listCollections], errorCode: 10107 } - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionNames fails after NotWritablePrimary when retryReads is false" - clientOptions: - retryReads: false - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 10107 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event diff --git a/test/spec/retryable-reads/legacy/listCollectionNames.json b/test/spec/retryable-reads/legacy/listCollectionNames.json deleted file mode 100644 index 73d96a3cf7..0000000000 --- a/test/spec/retryable-reads/legacy/listCollectionNames.json +++ /dev/null @@ -1,150 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [], - "tests": [ - { - "description": "ListCollectionNames succeeds on first attempt", - "operations": [ - { - "name": "listCollectionNames", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionNames succeeds on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listCollectionNames", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionNames fails on first attempt", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listCollectionNames", - "object": "database", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionNames fails on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listCollectionNames", - "object": "database", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/listCollectionNames.yml b/test/spec/retryable-reads/legacy/listCollectionNames.yml deleted file mode 100644 index 434adfbdd1..0000000000 --- a/test/spec/retryable-reads/legacy/listCollectionNames.yml +++ /dev/null @@ -1,59 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: [] - -tests: - - - description: "ListCollectionNames succeeds on first attempt" - operations: - - &retryable_operation - name: listCollectionNames - object: database - expectations: - - &retryable_command_started_event - command_started_event: - command: - listCollections: 1 - - - description: "ListCollectionNames succeeds on second attempt" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: - - listCollections - closeConnection: true - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionNames fails on first attempt" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - - description: "ListCollectionNames fails on second attempt" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - diff --git a/test/spec/retryable-reads/legacy/listCollectionObjects-serverErrors.json b/test/spec/retryable-reads/legacy/listCollectionObjects-serverErrors.json deleted file mode 100644 index ab469dfe30..0000000000 --- a/test/spec/retryable-reads/legacy/listCollectionObjects-serverErrors.json +++ /dev/null @@ -1,502 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [], - "tests": [ - { - "description": "ListCollectionObjects succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 11600 - } - }, - "operations": [ - { - "name": "listCollectionObjects", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionObjects succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 11602 - } - }, - "operations": [ - { - "name": "listCollectionObjects", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionObjects succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listCollectionObjects", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionObjects succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 13435 - } - }, - "operations": [ - { - "name": "listCollectionObjects", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionObjects succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 13436 - } - }, - "operations": [ - { - "name": "listCollectionObjects", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionObjects succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 189 - } - }, - "operations": [ - { - "name": "listCollectionObjects", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionObjects succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 91 - } - }, - "operations": [ - { - "name": "listCollectionObjects", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionObjects succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 7 - } - }, - "operations": [ - { - "name": "listCollectionObjects", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionObjects succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 6 - } - }, - "operations": [ - { - "name": "listCollectionObjects", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionObjects succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 89 - } - }, - "operations": [ - { - "name": "listCollectionObjects", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionObjects succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 9001 - } - }, - "operations": [ - { - "name": "listCollectionObjects", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionObjects fails after two NotWritablePrimary errors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listCollectionObjects", - "object": "database", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionObjects fails after NotWritablePrimary when retryReads is false", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listCollectionObjects", - "object": "database", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/listCollectionObjects-serverErrors.yml b/test/spec/retryable-reads/legacy/listCollectionObjects-serverErrors.yml deleted file mode 100644 index b2ff9ee830..0000000000 --- a/test/spec/retryable-reads/legacy/listCollectionObjects-serverErrors.yml +++ /dev/null @@ -1,148 +0,0 @@ -# listCollectionObjects returns an array of MongoCollection objects. -# Not all drivers support this functionality. For more details, see: -# https://github.com/mongodb/specifications/blob/master/source/enumerate-collections.rst#returning-a-list-of-collection-objects - -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: [] - -tests: - - - description: "ListCollectionObjects succeeds after InterruptedAtShutdown" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: { failCommands: [listCollections], errorCode: 11600 } - operations: - - &retryable_operation - name: listCollectionObjects - object: database - expectations: - - &retryable_command_started_event - command_started_event: - command: - listCollections: 1 - - *retryable_command_started_event - - - description: "ListCollectionObjects succeeds after InterruptedDueToReplStateChange" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 11602 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionObjects succeeds after NotWritablePrimary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 10107 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionObjects succeeds after NotPrimaryNoSecondaryOk" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 13435 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionObjects succeeds after NotPrimaryOrSecondary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 13436 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionObjects succeeds after PrimarySteppedDown" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 189 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionObjects succeeds after ShutdownInProgress" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 91 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionObjects succeeds after HostNotFound" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 7 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionObjects succeeds after HostUnreachable" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 6 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionObjects succeeds after NetworkTimeout" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 89 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionObjects succeeds after SocketException" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 9001 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionObjects fails after two NotWritablePrimary errors" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - data: { failCommands: [listCollections], errorCode: 10107 } - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionObjects fails after NotWritablePrimary when retryReads is false" - clientOptions: - retryReads: false - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 10107 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - diff --git a/test/spec/retryable-reads/legacy/listCollectionObjects.json b/test/spec/retryable-reads/legacy/listCollectionObjects.json deleted file mode 100644 index 1fb0f18437..0000000000 --- a/test/spec/retryable-reads/legacy/listCollectionObjects.json +++ /dev/null @@ -1,150 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [], - "tests": [ - { - "description": "ListCollectionObjects succeeds on first attempt", - "operations": [ - { - "name": "listCollectionObjects", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionObjects succeeds on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listCollectionObjects", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionObjects fails on first attempt", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listCollectionObjects", - "object": "database", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollectionObjects fails on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listCollectionObjects", - "object": "database", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/listCollectionObjects.yml b/test/spec/retryable-reads/legacy/listCollectionObjects.yml deleted file mode 100644 index 4315694850..0000000000 --- a/test/spec/retryable-reads/legacy/listCollectionObjects.yml +++ /dev/null @@ -1,63 +0,0 @@ -# listCollectionObjects returns an array of MongoCollection objects. -# Not all drivers support this functionality. For more details, see: -# https://github.com/mongodb/specifications/blob/master/source/enumerate-collections.rst#returning-a-list-of-collection-objects - -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: [] - -tests: - - - description: "ListCollectionObjects succeeds on first attempt" - operations: - - &retryable_operation - name: listCollectionObjects - object: database - expectations: - - &retryable_command_started_event - command_started_event: - command: - listCollections: 1 - - - description: "ListCollectionObjects succeeds on second attempt" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: - - listCollections - closeConnection: true - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollectionObjects fails on first attempt" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - - description: "ListCollectionObjects fails on second attempt" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - diff --git a/test/spec/retryable-reads/legacy/listCollections-serverErrors.json b/test/spec/retryable-reads/legacy/listCollections-serverErrors.json deleted file mode 100644 index def9ac4595..0000000000 --- a/test/spec/retryable-reads/legacy/listCollections-serverErrors.json +++ /dev/null @@ -1,502 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [], - "tests": [ - { - "description": "ListCollections succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 11600 - } - }, - "operations": [ - { - "name": "listCollections", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollections succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 11602 - } - }, - "operations": [ - { - "name": "listCollections", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollections succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listCollections", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollections succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 13435 - } - }, - "operations": [ - { - "name": "listCollections", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollections succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 13436 - } - }, - "operations": [ - { - "name": "listCollections", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollections succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 189 - } - }, - "operations": [ - { - "name": "listCollections", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollections succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 91 - } - }, - "operations": [ - { - "name": "listCollections", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollections succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 7 - } - }, - "operations": [ - { - "name": "listCollections", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollections succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 6 - } - }, - "operations": [ - { - "name": "listCollections", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollections succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 89 - } - }, - "operations": [ - { - "name": "listCollections", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollections succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 9001 - } - }, - "operations": [ - { - "name": "listCollections", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollections fails after two NotWritablePrimary errors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listCollections", - "object": "database", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollections fails after NotWritablePrimary when retryReads is false", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listCollections", - "object": "database", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/listCollections-serverErrors.yml b/test/spec/retryable-reads/legacy/listCollections-serverErrors.yml deleted file mode 100644 index 94a9495e52..0000000000 --- a/test/spec/retryable-reads/legacy/listCollections-serverErrors.yml +++ /dev/null @@ -1,143 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: [] - -tests: - - - description: "ListCollections succeeds after InterruptedAtShutdown" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: { failCommands: [listCollections], errorCode: 11600 } - operations: - - &retryable_operation - name: listCollections - object: database - expectations: - - &retryable_command_started_event - command_started_event: - command: - listCollections: 1 - - *retryable_command_started_event - - - description: "ListCollections succeeds after InterruptedDueToReplStateChange" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 11602 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollections succeeds after NotWritablePrimary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 10107 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollections succeeds after NotPrimaryNoSecondaryOk" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 13435 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollections succeeds after NotPrimaryOrSecondary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 13436 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollections succeeds after PrimarySteppedDown" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 189 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollections succeeds after ShutdownInProgress" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 91 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollections succeeds after HostNotFound" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 7 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollections succeeds after HostUnreachable" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 6 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollections succeeds after NetworkTimeout" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 89 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollections succeeds after SocketException" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 9001 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollections fails after two NotWritablePrimary errors" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - data: { failCommands: [listCollections], errorCode: 10107 } - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollections fails after NotWritablePrimary when retryReads is false" - clientOptions: - retryReads: false - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listCollections], errorCode: 10107 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event diff --git a/test/spec/retryable-reads/legacy/listCollections.json b/test/spec/retryable-reads/legacy/listCollections.json deleted file mode 100644 index 2427883621..0000000000 --- a/test/spec/retryable-reads/legacy/listCollections.json +++ /dev/null @@ -1,150 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [], - "tests": [ - { - "description": "ListCollections succeeds on first attempt", - "operations": [ - { - "name": "listCollections", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollections succeeds on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listCollections", - "object": "database" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollections fails on first attempt", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listCollections", - "object": "database", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - }, - { - "description": "ListCollections fails on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "listCollections" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listCollections", - "object": "database", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listCollections": 1 - } - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/listCollections.yml b/test/spec/retryable-reads/legacy/listCollections.yml deleted file mode 100644 index 378ff924f4..0000000000 --- a/test/spec/retryable-reads/legacy/listCollections.yml +++ /dev/null @@ -1,59 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: [] - -tests: - - - description: "ListCollections succeeds on first attempt" - operations: - - &retryable_operation - name: listCollections - object: database - expectations: - - &retryable_command_started_event - command_started_event: - command: - listCollections: 1 - - - description: "ListCollections succeeds on second attempt" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: - - listCollections - closeConnection: true - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListCollections fails on first attempt" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - - description: "ListCollections fails on second attempt" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - diff --git a/test/spec/retryable-reads/legacy/listDatabaseNames-serverErrors.json b/test/spec/retryable-reads/legacy/listDatabaseNames-serverErrors.json deleted file mode 100644 index 1dd8e4415a..0000000000 --- a/test/spec/retryable-reads/legacy/listDatabaseNames-serverErrors.json +++ /dev/null @@ -1,502 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [], - "tests": [ - { - "description": "ListDatabaseNames succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 11600 - } - }, - "operations": [ - { - "name": "listDatabaseNames", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseNames succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 11602 - } - }, - "operations": [ - { - "name": "listDatabaseNames", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseNames succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listDatabaseNames", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseNames succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 13435 - } - }, - "operations": [ - { - "name": "listDatabaseNames", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseNames succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 13436 - } - }, - "operations": [ - { - "name": "listDatabaseNames", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseNames succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 189 - } - }, - "operations": [ - { - "name": "listDatabaseNames", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseNames succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 91 - } - }, - "operations": [ - { - "name": "listDatabaseNames", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseNames succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 7 - } - }, - "operations": [ - { - "name": "listDatabaseNames", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseNames succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 6 - } - }, - "operations": [ - { - "name": "listDatabaseNames", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseNames succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 89 - } - }, - "operations": [ - { - "name": "listDatabaseNames", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseNames succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 9001 - } - }, - "operations": [ - { - "name": "listDatabaseNames", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseNames fails after two NotWritablePrimary errors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listDatabaseNames", - "object": "client", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseNames fails after NotWritablePrimary when retryReads is false", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listDatabaseNames", - "object": "client", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/listDatabaseNames-serverErrors.yml b/test/spec/retryable-reads/legacy/listDatabaseNames-serverErrors.yml deleted file mode 100644 index ca6b150944..0000000000 --- a/test/spec/retryable-reads/legacy/listDatabaseNames-serverErrors.yml +++ /dev/null @@ -1,143 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: [] - -tests: - - - description: "ListDatabaseNames succeeds after InterruptedAtShutdown" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: { failCommands: [listDatabases], errorCode: 11600 } - operations: - - &retryable_operation - name: listDatabaseNames - object: client - expectations: - - &retryable_command_started_event - command_started_event: - command: - listDatabases: 1 - - *retryable_command_started_event - - - description: "ListDatabaseNames succeeds after InterruptedDueToReplStateChange" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 11602 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseNames succeeds after NotWritablePrimary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 10107 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseNames succeeds after NotPrimaryNoSecondaryOk" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 13435 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseNames succeeds after NotPrimaryOrSecondary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 13436 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseNames succeeds after PrimarySteppedDown" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 189 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseNames succeeds after ShutdownInProgress" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 91 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseNames succeeds after HostNotFound" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 7 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseNames succeeds after HostUnreachable" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 6 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseNames succeeds after NetworkTimeout" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 89 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseNames succeeds after SocketException" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 9001 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseNames fails after two NotWritablePrimary errors" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - data: { failCommands: [listDatabases], errorCode: 10107 } - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseNames fails after NotWritablePrimary when retryReads is false" - clientOptions: - retryReads: false - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 10107 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event diff --git a/test/spec/retryable-reads/legacy/listDatabaseNames.json b/test/spec/retryable-reads/legacy/listDatabaseNames.json deleted file mode 100644 index b431f57016..0000000000 --- a/test/spec/retryable-reads/legacy/listDatabaseNames.json +++ /dev/null @@ -1,150 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [], - "tests": [ - { - "description": "ListDatabaseNames succeeds on first attempt", - "operations": [ - { - "name": "listDatabaseNames", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseNames succeeds on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listDatabaseNames", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseNames fails on first attempt", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listDatabaseNames", - "object": "client", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseNames fails on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listDatabaseNames", - "object": "client", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/listDatabaseNames.yml b/test/spec/retryable-reads/legacy/listDatabaseNames.yml deleted file mode 100644 index 13e01a48ea..0000000000 --- a/test/spec/retryable-reads/legacy/listDatabaseNames.yml +++ /dev/null @@ -1,59 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: [] - -tests: - - - description: "ListDatabaseNames succeeds on first attempt" - operations: - - &retryable_operation - name: listDatabaseNames - object: client - expectations: - - &retryable_command_started_event - command_started_event: - command: - listDatabases: 1 - - - description: "ListDatabaseNames succeeds on second attempt" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: - - listDatabases - closeConnection: true - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseNames fails on first attempt" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - - description: "ListDatabaseNames fails on second attempt" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - diff --git a/test/spec/retryable-reads/legacy/listDatabaseObjects-serverErrors.json b/test/spec/retryable-reads/legacy/listDatabaseObjects-serverErrors.json deleted file mode 100644 index bc497bb088..0000000000 --- a/test/spec/retryable-reads/legacy/listDatabaseObjects-serverErrors.json +++ /dev/null @@ -1,502 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [], - "tests": [ - { - "description": "ListDatabaseObjects succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 11600 - } - }, - "operations": [ - { - "name": "listDatabaseObjects", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseObjects succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 11602 - } - }, - "operations": [ - { - "name": "listDatabaseObjects", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseObjects succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listDatabaseObjects", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseObjects succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 13435 - } - }, - "operations": [ - { - "name": "listDatabaseObjects", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseObjects succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 13436 - } - }, - "operations": [ - { - "name": "listDatabaseObjects", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseObjects succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 189 - } - }, - "operations": [ - { - "name": "listDatabaseObjects", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseObjects succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 91 - } - }, - "operations": [ - { - "name": "listDatabaseObjects", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseObjects succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 7 - } - }, - "operations": [ - { - "name": "listDatabaseObjects", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseObjects succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 6 - } - }, - "operations": [ - { - "name": "listDatabaseObjects", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseObjects succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 89 - } - }, - "operations": [ - { - "name": "listDatabaseObjects", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseObjects succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 9001 - } - }, - "operations": [ - { - "name": "listDatabaseObjects", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseObjects fails after two NotWritablePrimary errors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listDatabaseObjects", - "object": "client", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseObjects fails after NotWritablePrimary when retryReads is false", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listDatabaseObjects", - "object": "client", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/listDatabaseObjects-serverErrors.yml b/test/spec/retryable-reads/legacy/listDatabaseObjects-serverErrors.yml deleted file mode 100644 index adc8214a3b..0000000000 --- a/test/spec/retryable-reads/legacy/listDatabaseObjects-serverErrors.yml +++ /dev/null @@ -1,148 +0,0 @@ -# listDatabaseObjects returns an array of MongoDatabase objects. -# Not all drivers support this functionality. For more details, see: -# https://github.com/mongodb/specifications/blob/master/source/enumerate-databases.rst#enumerating-mongodatabase-objects - -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: [] - -tests: - - - description: "ListDatabaseObjects succeeds after InterruptedAtShutdown" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: { failCommands: [listDatabases], errorCode: 11600 } - operations: - - &retryable_operation - name: listDatabaseObjects - object: client - expectations: - - &retryable_command_started_event - command_started_event: - command: - listDatabases: 1 - - *retryable_command_started_event - - - description: "ListDatabaseObjects succeeds after InterruptedDueToReplStateChange" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 11602 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseObjects succeeds after NotWritablePrimary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 10107 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseObjects succeeds after NotPrimaryNoSecondaryOk" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 13435 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseObjects succeeds after NotPrimaryOrSecondary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 13436 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseObjects succeeds after PrimarySteppedDown" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 189 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseObjects succeeds after ShutdownInProgress" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 91 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseObjects succeeds after HostNotFound" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 7 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseObjects succeeds after HostUnreachable" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 6 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseObjects succeeds after NetworkTimeout" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 89 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseObjects succeeds after SocketException" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 9001 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseObjects fails after two NotWritablePrimary errors" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - data: { failCommands: [listDatabases], errorCode: 10107 } - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseObjects fails after NotWritablePrimary when retryReads is false" - clientOptions: - retryReads: false - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 10107 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - diff --git a/test/spec/retryable-reads/legacy/listDatabaseObjects.json b/test/spec/retryable-reads/legacy/listDatabaseObjects.json deleted file mode 100644 index 267fe921ca..0000000000 --- a/test/spec/retryable-reads/legacy/listDatabaseObjects.json +++ /dev/null @@ -1,150 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [], - "tests": [ - { - "description": "ListDatabaseObjects succeeds on first attempt", - "operations": [ - { - "name": "listDatabaseObjects", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseObjects succeeds on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listDatabaseObjects", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseObjects fails on first attempt", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listDatabaseObjects", - "object": "client", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabaseObjects fails on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listDatabaseObjects", - "object": "client", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/listDatabaseObjects.yml b/test/spec/retryable-reads/legacy/listDatabaseObjects.yml deleted file mode 100644 index 9ed2c216a5..0000000000 --- a/test/spec/retryable-reads/legacy/listDatabaseObjects.yml +++ /dev/null @@ -1,63 +0,0 @@ -# listDatabaseObjects returns an array of MongoDatabase objects. -# Not all drivers support this functionality. For more details, see: -# https://github.com/mongodb/specifications/blob/master/source/enumerate-databases.rst#enumerating-mongodatabase-objects - -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: [] - -tests: - - - description: "ListDatabaseObjects succeeds on first attempt" - operations: - - &retryable_operation - name: listDatabaseObjects - object: client - expectations: - - &retryable_command_started_event - command_started_event: - command: - listDatabases: 1 - - - description: "ListDatabaseObjects succeeds on second attempt" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: - - listDatabases - closeConnection: true - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabaseObjects fails on first attempt" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - - description: "ListDatabaseObjects fails on second attempt" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - diff --git a/test/spec/retryable-reads/legacy/listDatabases-serverErrors.json b/test/spec/retryable-reads/legacy/listDatabases-serverErrors.json deleted file mode 100644 index ed7bcbc398..0000000000 --- a/test/spec/retryable-reads/legacy/listDatabases-serverErrors.json +++ /dev/null @@ -1,502 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [], - "tests": [ - { - "description": "ListDatabases succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 11600 - } - }, - "operations": [ - { - "name": "listDatabases", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabases succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 11602 - } - }, - "operations": [ - { - "name": "listDatabases", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabases succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listDatabases", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabases succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 13435 - } - }, - "operations": [ - { - "name": "listDatabases", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabases succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 13436 - } - }, - "operations": [ - { - "name": "listDatabases", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabases succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 189 - } - }, - "operations": [ - { - "name": "listDatabases", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabases succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 91 - } - }, - "operations": [ - { - "name": "listDatabases", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabases succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 7 - } - }, - "operations": [ - { - "name": "listDatabases", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabases succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 6 - } - }, - "operations": [ - { - "name": "listDatabases", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabases succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 89 - } - }, - "operations": [ - { - "name": "listDatabases", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabases succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 9001 - } - }, - "operations": [ - { - "name": "listDatabases", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabases fails after two NotWritablePrimary errors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listDatabases", - "object": "client", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabases fails after NotWritablePrimary when retryReads is false", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listDatabases", - "object": "client", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/listDatabases-serverErrors.yml b/test/spec/retryable-reads/legacy/listDatabases-serverErrors.yml deleted file mode 100644 index ac904701de..0000000000 --- a/test/spec/retryable-reads/legacy/listDatabases-serverErrors.yml +++ /dev/null @@ -1,144 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: [] - -tests: - - - description: "ListDatabases succeeds after InterruptedAtShutdown" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: { failCommands: [listDatabases], errorCode: 11600 } - operations: - - &retryable_operation - name: listDatabases - object: client - expectations: - - &retryable_command_started_event - command_started_event: - command: - listDatabases: 1 - - *retryable_command_started_event - - - description: "ListDatabases succeeds after InterruptedDueToReplStateChange" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 11602 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabases succeeds after NotWritablePrimary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 10107 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabases succeeds after NotPrimaryNoSecondaryOk" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 13435 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabases succeeds after NotPrimaryOrSecondary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 13436 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabases succeeds after PrimarySteppedDown" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 189 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabases succeeds after ShutdownInProgress" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 91 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabases succeeds after HostNotFound" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 7 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabases succeeds after HostUnreachable" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 6 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabases succeeds after NetworkTimeout" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 89 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabases succeeds after SocketException" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 9001 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabases fails after two NotWritablePrimary errors" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - data: { failCommands: [listDatabases], errorCode: 10107 } - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabases fails after NotWritablePrimary when retryReads is false" - clientOptions: - retryReads: false - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listDatabases], errorCode: 10107 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - diff --git a/test/spec/retryable-reads/legacy/listDatabases.json b/test/spec/retryable-reads/legacy/listDatabases.json deleted file mode 100644 index 69ef9788f8..0000000000 --- a/test/spec/retryable-reads/legacy/listDatabases.json +++ /dev/null @@ -1,150 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [], - "tests": [ - { - "description": "ListDatabases succeeds on first attempt", - "operations": [ - { - "name": "listDatabases", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabases succeeds on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listDatabases", - "object": "client" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabases fails on first attempt", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listDatabases", - "object": "client", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - }, - { - "description": "ListDatabases fails on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "listDatabases" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listDatabases", - "object": "client", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - }, - { - "command_started_event": { - "command": { - "listDatabases": 1 - } - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/listDatabases.yml b/test/spec/retryable-reads/legacy/listDatabases.yml deleted file mode 100644 index 3eaed913ad..0000000000 --- a/test/spec/retryable-reads/legacy/listDatabases.yml +++ /dev/null @@ -1,59 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: [] - -tests: - - - description: "ListDatabases succeeds on first attempt" - operations: - - &retryable_operation - name: listDatabases - object: client - expectations: - - &retryable_command_started_event - command_started_event: - command: - listDatabases: 1 - - - description: "ListDatabases succeeds on second attempt" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: - - listDatabases - closeConnection: true - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListDatabases fails on first attempt" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - - description: "ListDatabases fails on second attempt" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - diff --git a/test/spec/retryable-reads/legacy/listIndexNames-serverErrors.json b/test/spec/retryable-reads/legacy/listIndexNames-serverErrors.json deleted file mode 100644 index 2d3265ec85..0000000000 --- a/test/spec/retryable-reads/legacy/listIndexNames-serverErrors.json +++ /dev/null @@ -1,527 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [], - "tests": [ - { - "description": "ListIndexNames succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 11600 - } - }, - "operations": [ - { - "name": "listIndexNames", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexNames succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 11602 - } - }, - "operations": [ - { - "name": "listIndexNames", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexNames succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listIndexNames", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexNames succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 13435 - } - }, - "operations": [ - { - "name": "listIndexNames", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexNames succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 13436 - } - }, - "operations": [ - { - "name": "listIndexNames", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexNames succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 189 - } - }, - "operations": [ - { - "name": "listIndexNames", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexNames succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 91 - } - }, - "operations": [ - { - "name": "listIndexNames", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexNames succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 7 - } - }, - "operations": [ - { - "name": "listIndexNames", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexNames succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 6 - } - }, - "operations": [ - { - "name": "listIndexNames", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexNames succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 89 - } - }, - "operations": [ - { - "name": "listIndexNames", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexNames succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 9001 - } - }, - "operations": [ - { - "name": "listIndexNames", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexNames fails after two NotWritablePrimary errors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listIndexNames", - "object": "collection", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexNames fails after NotWritablePrimary when retryReads is false", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listIndexNames", - "object": "collection", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/listIndexNames-serverErrors.yml b/test/spec/retryable-reads/legacy/listIndexNames-serverErrors.yml deleted file mode 100644 index 6fb7e30cbf..0000000000 --- a/test/spec/retryable-reads/legacy/listIndexNames-serverErrors.yml +++ /dev/null @@ -1,144 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: [] - -tests: - - - description: "ListIndexNames succeeds after InterruptedAtShutdown" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: { failCommands: [listIndexes], errorCode: 11600 } - operations: - - &retryable_operation - name: listIndexNames - object: collection - expectations: - - &retryable_command_started_event - command_started_event: - command: - listIndexes: *collection_name - database_name: *database_name - - *retryable_command_started_event - - - description: "ListIndexNames succeeds after InterruptedDueToReplStateChange" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 11602 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexNames succeeds after NotWritablePrimary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 10107 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexNames succeeds after NotPrimaryNoSecondaryOk" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 13435 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexNames succeeds after NotPrimaryOrSecondary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 13436 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexNames succeeds after PrimarySteppedDown" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 189 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexNames succeeds after ShutdownInProgress" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 91 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexNames succeeds after HostNotFound" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 7 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexNames succeeds after HostUnreachable" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 6 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexNames succeeds after NetworkTimeout" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 89 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexNames succeeds after SocketException" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 9001 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexNames fails after two NotWritablePrimary errors" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - data: { failCommands: [listIndexes], errorCode: 10107 } - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexNames fails after NotWritablePrimary when retryReads is false" - clientOptions: - retryReads: false - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 10107 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event diff --git a/test/spec/retryable-reads/legacy/listIndexNames.json b/test/spec/retryable-reads/legacy/listIndexNames.json deleted file mode 100644 index fbdb420f8a..0000000000 --- a/test/spec/retryable-reads/legacy/listIndexNames.json +++ /dev/null @@ -1,156 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [], - "tests": [ - { - "description": "ListIndexNames succeeds on first attempt", - "operations": [ - { - "name": "listIndexNames", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexNames succeeds on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listIndexNames", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexNames fails on first attempt", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listIndexNames", - "object": "collection", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexNames fails on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listIndexNames", - "object": "collection", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/listIndexNames.yml b/test/spec/retryable-reads/legacy/listIndexNames.yml deleted file mode 100644 index 3a73b51e15..0000000000 --- a/test/spec/retryable-reads/legacy/listIndexNames.yml +++ /dev/null @@ -1,60 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: [] - -tests: - - - description: "ListIndexNames succeeds on first attempt" - operations: - - &retryable_operation - name: listIndexNames - object: collection - expectations: - - &retryable_command_started_event - command_started_event: - command: - listIndexes: *collection_name - database_name: *database_name - - - description: "ListIndexNames succeeds on second attempt" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: - - listIndexes - closeConnection: true - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexNames fails on first attempt" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - - description: "ListIndexNames fails on second attempt" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - diff --git a/test/spec/retryable-reads/legacy/listIndexes-serverErrors.json b/test/spec/retryable-reads/legacy/listIndexes-serverErrors.json deleted file mode 100644 index 25c5b0e448..0000000000 --- a/test/spec/retryable-reads/legacy/listIndexes-serverErrors.json +++ /dev/null @@ -1,527 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [], - "tests": [ - { - "description": "ListIndexes succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 11600 - } - }, - "operations": [ - { - "name": "listIndexes", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexes succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 11602 - } - }, - "operations": [ - { - "name": "listIndexes", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexes succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listIndexes", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexes succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 13435 - } - }, - "operations": [ - { - "name": "listIndexes", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexes succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 13436 - } - }, - "operations": [ - { - "name": "listIndexes", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexes succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 189 - } - }, - "operations": [ - { - "name": "listIndexes", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexes succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 91 - } - }, - "operations": [ - { - "name": "listIndexes", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexes succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 7 - } - }, - "operations": [ - { - "name": "listIndexes", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexes succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 6 - } - }, - "operations": [ - { - "name": "listIndexes", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexes succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 89 - } - }, - "operations": [ - { - "name": "listIndexes", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexes succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 9001 - } - }, - "operations": [ - { - "name": "listIndexes", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexes fails after two NotWritablePrimary errors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listIndexes", - "object": "collection", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexes fails after NotWritablePrimary when retryReads is false", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "errorCode": 10107 - } - }, - "operations": [ - { - "name": "listIndexes", - "object": "collection", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/listIndexes-serverErrors.yml b/test/spec/retryable-reads/legacy/listIndexes-serverErrors.yml deleted file mode 100644 index 23f2768e9a..0000000000 --- a/test/spec/retryable-reads/legacy/listIndexes-serverErrors.yml +++ /dev/null @@ -1,145 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: [] - -tests: - - - description: "ListIndexes succeeds after InterruptedAtShutdown" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: { failCommands: [listIndexes], errorCode: 11600 } - operations: - - &retryable_operation - name: listIndexes - object: collection - expectations: - - &retryable_command_started_event - command_started_event: - command: - listIndexes: *collection_name - database_name: *database_name - - *retryable_command_started_event - - - description: "ListIndexes succeeds after InterruptedDueToReplStateChange" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 11602 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexes succeeds after NotWritablePrimary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 10107 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexes succeeds after NotPrimaryNoSecondaryOk" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 13435 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexes succeeds after NotPrimaryOrSecondary" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 13436 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexes succeeds after PrimarySteppedDown" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 189 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexes succeeds after ShutdownInProgress" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 91 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexes succeeds after HostNotFound" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 7 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexes succeeds after HostUnreachable" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 6 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexes succeeds after NetworkTimeout" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 89 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexes succeeds after SocketException" - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 9001 } - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexes fails after two NotWritablePrimary errors" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - data: { failCommands: [listIndexes], errorCode: 10107 } - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexes fails after NotWritablePrimary when retryReads is false" - clientOptions: - retryReads: false - failPoint: - <<: *failCommand_failPoint - data: { failCommands: [listIndexes], errorCode: 10107 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - diff --git a/test/spec/retryable-reads/legacy/listIndexes.json b/test/spec/retryable-reads/legacy/listIndexes.json deleted file mode 100644 index 5cb620ae45..0000000000 --- a/test/spec/retryable-reads/legacy/listIndexes.json +++ /dev/null @@ -1,156 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [], - "tests": [ - { - "description": "ListIndexes succeeds on first attempt", - "operations": [ - { - "name": "listIndexes", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexes succeeds on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listIndexes", - "object": "collection" - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexes fails on first attempt", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listIndexes", - "object": "collection", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "ListIndexes fails on second attempt", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "listIndexes" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "listIndexes", - "object": "collection", - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - }, - { - "command_started_event": { - "command": { - "listIndexes": "coll" - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/listIndexes.yml b/test/spec/retryable-reads/legacy/listIndexes.yml deleted file mode 100644 index 84ba7242a3..0000000000 --- a/test/spec/retryable-reads/legacy/listIndexes.yml +++ /dev/null @@ -1,60 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: [] - -tests: - - - description: "ListIndexes succeeds on first attempt" - operations: - - &retryable_operation - name: listIndexes - object: collection - expectations: - - &retryable_command_started_event - command_started_event: - command: - listIndexes: *collection_name - database_name: *database_name - - - description: "ListIndexes succeeds on second attempt" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: - - listIndexes - closeConnection: true - operations: [*retryable_operation] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - - - description: "ListIndexes fails on first attempt" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: - - &retryable_operation_fails - <<: *retryable_operation - error: true - expectations: - - *retryable_command_started_event - - - description: "ListIndexes fails on second attempt" - failPoint: - <<: *failCommand_failPoint - mode: { times: 2 } - operations: [*retryable_operation_fails] - expectations: - - *retryable_command_started_event - - *retryable_command_started_event - diff --git a/test/spec/retryable-reads/legacy/mapReduce.json b/test/spec/retryable-reads/legacy/mapReduce.json deleted file mode 100644 index 9327a23052..0000000000 --- a/test/spec/retryable-reads/legacy/mapReduce.json +++ /dev/null @@ -1,189 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "single", - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ], - "serverless": "forbid" - } - ], - "database_name": "retryable-reads-tests", - "collection_name": "coll", - "data": [ - { - "_id": 1, - "x": 0 - }, - { - "_id": 2, - "x": 1 - }, - { - "_id": 3, - "x": 2 - } - ], - "tests": [ - { - "description": "MapReduce succeeds with retry on", - "operations": [ - { - "name": "mapReduce", - "object": "collection", - "arguments": { - "map": { - "$code": "function inc() { return emit(0, this.x + 1) }" - }, - "reduce": { - "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" - }, - "out": { - "inline": 1 - } - }, - "result": [ - { - "_id": 0, - "value": 6 - } - ] - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "mapReduce": "coll", - "map": { - "$code": "function inc() { return emit(0, this.x + 1) }" - }, - "reduce": { - "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" - }, - "out": { - "inline": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "MapReduce fails with retry on", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "mapReduce" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "mapReduce", - "object": "collection", - "arguments": { - "map": { - "$code": "function inc() { return emit(0, this.x + 1) }" - }, - "reduce": { - "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" - }, - "out": { - "inline": 1 - } - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "mapReduce": "coll", - "map": { - "$code": "function inc() { return emit(0, this.x + 1) }" - }, - "reduce": { - "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" - }, - "out": { - "inline": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - }, - { - "description": "MapReduce fails with retry off", - "clientOptions": { - "retryReads": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "mapReduce" - ], - "closeConnection": true - } - }, - "operations": [ - { - "name": "mapReduce", - "object": "collection", - "arguments": { - "map": { - "$code": "function inc() { return emit(0, this.x + 1) }" - }, - "reduce": { - "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" - }, - "out": { - "inline": 1 - } - }, - "error": true - } - ], - "expectations": [ - { - "command_started_event": { - "command": { - "mapReduce": "coll", - "map": { - "$code": "function inc() { return emit(0, this.x + 1) }" - }, - "reduce": { - "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" - }, - "out": { - "inline": 1 - } - }, - "database_name": "retryable-reads-tests" - } - } - ] - } - ] -} diff --git a/test/spec/retryable-reads/legacy/mapReduce.yml b/test/spec/retryable-reads/legacy/mapReduce.yml deleted file mode 100644 index def8b37485..0000000000 --- a/test/spec/retryable-reads/legacy/mapReduce.yml +++ /dev/null @@ -1,62 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["single", "replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - # serverless proxy does not support mapReduce operation - serverless: "forbid" - -database_name: &database_name "retryable-reads-tests" -collection_name: &collection_name "coll" - -data: - - {_id: 1, x: 0} - - {_id: 2, x: 1} - - {_id: 3, x: 2} - -tests: - - - description: "MapReduce succeeds with retry on" - operations: - - &operation_succeeds - <<: &operation - name: mapReduce - object: collection - arguments: - map: { $code: "function inc() { return emit(0, this.x + 1) }" } - reduce: { $code: "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" } - out: { inline: 1 } - result: [ { "_id" : 0, "value" : 6 } ] - expectations: - - &command_started_event - command_started_event: - command: - mapReduce: *collection_name - map: { $code: "function inc() { return emit(0, this.x + 1) }" } - reduce: { $code: "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" } - out: { inline: 1 } - database_name: *database_name - - - description: "MapReduce fails with retry on" - failPoint: &failCommand_failPoint - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: [mapReduce] - closeConnection: true - operations: - - &operation_fails - <<: *operation - error: true - expectations: - - *command_started_event - - - description: "MapReduce fails with retry off" - clientOptions: - retryReads: false - failPoint: *failCommand_failPoint - operations: [*operation_fails] - expectations: - - *command_started_event diff --git a/test/spec/retryable-reads/unified/aggregate-merge.json b/test/spec/retryable-reads/unified/aggregate-merge.json new file mode 100644 index 0000000000..96bbd0fc38 --- /dev/null +++ b/test/spec/retryable-reads/unified/aggregate-merge.json @@ -0,0 +1,143 @@ +{ + "description": "aggregate-merge", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "4.1.11" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "Aggregate with $merge does not retry", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + }, + { + "$merge": { + "into": "output-collection" + } + } + ] + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + }, + { + "$merge": { + "into": "output-collection" + } + } + ] + }, + "commandName": "aggregate", + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/aggregate-merge.yml b/test/spec/retryable-reads/unified/aggregate-merge.yml new file mode 100644 index 0000000000..0add82b667 --- /dev/null +++ b/test/spec/retryable-reads/unified/aggregate-merge.yml @@ -0,0 +1,86 @@ +description: aggregate-merge + +schemaVersion: '1.0' + +runOnRequirements: + - + minServerVersion: 4.1.11 + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - + _id: 1 + x: 11 + - + _id: 2 + x: 22 + - + _id: 3 + x: 33 + +tests: + - + description: 'Aggregate with $merge does not retry' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + closeConnection: true + - + object: *collection0 + name: aggregate + arguments: + pipeline: &pipeline + - + $match: + _id: + $gt: 1 + - + $sort: + x: 1 + - + $merge: + into: output-collection + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - + commandStartedEvent: + command: + aggregate: *collection_name + pipeline: *pipeline + commandName: aggregate + databaseName: *database_name diff --git a/test/spec/retryable-reads/unified/aggregate-serverErrors.json b/test/spec/retryable-reads/unified/aggregate-serverErrors.json new file mode 100644 index 0000000000..d39835a5d3 --- /dev/null +++ b/test/spec/retryable-reads/unified/aggregate-serverErrors.json @@ -0,0 +1,1430 @@ +{ + "description": "aggregate-serverErrors", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "Aggregate succeeds after InterruptedAtShutdown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 11600 + } + } + } + }, + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "expectResult": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Aggregate succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 11602 + } + } + } + }, + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "expectResult": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Aggregate succeeds after NotWritablePrimary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "expectResult": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Aggregate succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 13435 + } + } + } + }, + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "expectResult": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Aggregate succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 13436 + } + } + } + }, + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "expectResult": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Aggregate succeeds after PrimarySteppedDown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 189 + } + } + } + }, + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "expectResult": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Aggregate succeeds after ShutdownInProgress", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 91 + } + } + } + }, + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "expectResult": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Aggregate succeeds after HostNotFound", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 7 + } + } + } + }, + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "expectResult": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Aggregate succeeds after HostUnreachable", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 6 + } + } + } + }, + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "expectResult": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Aggregate succeeds after NetworkTimeout", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 89 + } + } + } + }, + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "expectResult": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Aggregate succeeds after SocketException", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 9001 + } + } + } + }, + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "expectResult": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Aggregate fails after two NotWritablePrimary errors", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Aggregate fails after NotWritablePrimary when retryReads is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection1", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/aggregate-serverErrors.yml b/test/spec/retryable-reads/unified/aggregate-serverErrors.yml new file mode 100644 index 0000000000..66a3f2cbbb --- /dev/null +++ b/test/spec/retryable-reads/unified/aggregate-serverErrors.yml @@ -0,0 +1,411 @@ +description: aggregate-serverErrors + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - + _id: 1 + x: 11 + - + _id: 2 + x: 22 + - + _id: 3 + x: 33 + +tests: + - + description: 'Aggregate succeeds after InterruptedAtShutdown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 11600 + - &retryable_operation_succeeds + object: *collection0 + name: aggregate + arguments: + pipeline: + - + $match: + _id: + $gt: 1 + - + $sort: + x: 1 + expectResult: + - + _id: 2 + x: 22 + - + _id: 3 + x: 33 + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + aggregate: *collection_name + pipeline: + - + $match: + _id: { $gt: 1 } + - + $sort: + x: 1 + databaseName: *database_name + - *retryable_command_started_event + - + description: 'Aggregate succeeds after InterruptedDueToReplStateChange' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 11602 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Aggregate succeeds after NotWritablePrimary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 10107 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Aggregate succeeds after NotPrimaryNoSecondaryOk' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 13435 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Aggregate succeeds after NotPrimaryOrSecondary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 13436 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Aggregate succeeds after PrimarySteppedDown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 189 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Aggregate succeeds after ShutdownInProgress' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 91 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Aggregate succeeds after HostNotFound' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 7 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Aggregate succeeds after HostUnreachable' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 6 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Aggregate succeeds after NetworkTimeout' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 89 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Aggregate succeeds after SocketException' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 9001 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Aggregate fails after two NotWritablePrimary errors' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - aggregate + errorCode: 10107 + - &retryable_operation_fails + object: *collection0 + name: aggregate + arguments: + pipeline: + - + $match: + _id: + $gt: 1 + - + $sort: + x: 1 + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Aggregate fails after NotWritablePrimary when retryReads is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 10107 + - <<: *retryable_operation_fails + object: *collection1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/aggregate.json b/test/spec/retryable-reads/unified/aggregate.json new file mode 100644 index 0000000000..2b504c8d49 --- /dev/null +++ b/test/spec/retryable-reads/unified/aggregate.json @@ -0,0 +1,527 @@ +{ + "description": "aggregate", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "Aggregate succeeds on first attempt", + "operations": [ + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "expectResult": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Aggregate succeeds on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "expectResult": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Aggregate fails on first attempt", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection1", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Aggregate fails on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Aggregate with $out does not retry", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + }, + { + "$out": "output-collection" + } + ] + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$sort": { + "x": 1 + } + }, + { + "$out": "output-collection" + } + ] + }, + "commandName": "aggregate", + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/aggregate.yml b/test/spec/retryable-reads/unified/aggregate.yml new file mode 100644 index 0000000000..fa25d1f992 --- /dev/null +++ b/test/spec/retryable-reads/unified/aggregate.yml @@ -0,0 +1,227 @@ +description: aggregate + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - + _id: 1 + x: 11 + - + _id: 2 + x: 22 + - + _id: 3 + x: 33 + +tests: + - + description: 'Aggregate succeeds on first attempt' + operations: + - &retryable_operation_succeeds + object: *collection0 + name: aggregate + arguments: + pipeline: + - + $match: + _id: + $gt: 1 + - + $sort: + x: 1 + expectResult: + - + _id: 2 + x: 22 + - + _id: 3 + x: 33 + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + aggregate: *collection_name + pipeline: + - + $match: + _id: { $gt: 1 } + - + $sort: + x: 1 + databaseName: *database_name + - + description: 'Aggregate succeeds on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + closeConnection: true + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Aggregate fails on first attempt' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - &retryable_operation_fails + object: *collection1 + name: aggregate + arguments: + pipeline: + - + $match: + _id: + $gt: 1 + - + $sort: + x: 1 + expectError: + isError: true + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - + description: 'Aggregate fails on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - aggregate + closeConnection: true + - <<: *retryable_operation_fails + object: *collection0 + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Aggregate with $out does not retry' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: *failCommand_failPoint + - + object: *collection0 + name: aggregate + arguments: + pipeline: + - + $match: + _id: + $gt: 1 + - + $sort: + x: 1 + - + $out: output-collection + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - + commandStartedEvent: + command: + aggregate: *collection_name + pipeline: + - + $match: + _id: { $gt: 1 } + - + $sort: + x: 1 + - + $out: output-collection + commandName: aggregate + databaseName: *database_name diff --git a/test/spec/retryable-reads/unified/changeStreams-client.watch-serverErrors.json b/test/spec/retryable-reads/unified/changeStreams-client.watch-serverErrors.json new file mode 100644 index 0000000000..47375974d2 --- /dev/null +++ b/test/spec/retryable-reads/unified/changeStreams-client.watch-serverErrors.json @@ -0,0 +1,959 @@ +{ + "description": "changeStreams-client.watch-serverErrors", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "serverless": "forbid", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ], + "ignoreCommandMonitoringEvents": [ + "killCursors" + ] + } + } + ], + "tests": [ + { + "description": "client.watch succeeds after InterruptedAtShutdown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 11600 + } + } + } + }, + { + "object": "client0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + } + ] + } + ] + }, + { + "description": "client.watch succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 11602 + } + } + } + }, + { + "object": "client0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + } + ] + } + ] + }, + { + "description": "client.watch succeeds after NotWritablePrimary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "client0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + } + ] + } + ] + }, + { + "description": "client.watch succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 13435 + } + } + } + }, + { + "object": "client0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + } + ] + } + ] + }, + { + "description": "client.watch succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 13436 + } + } + } + }, + { + "object": "client0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + } + ] + } + ] + }, + { + "description": "client.watch succeeds after PrimarySteppedDown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 189 + } + } + } + }, + { + "object": "client0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + } + ] + } + ] + }, + { + "description": "client.watch succeeds after ShutdownInProgress", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 91 + } + } + } + }, + { + "object": "client0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + } + ] + } + ] + }, + { + "description": "client.watch succeeds after HostNotFound", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 7 + } + } + } + }, + { + "object": "client0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + } + ] + } + ] + }, + { + "description": "client.watch succeeds after HostUnreachable", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 6 + } + } + } + }, + { + "object": "client0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + } + ] + } + ] + }, + { + "description": "client.watch succeeds after NetworkTimeout", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 89 + } + } + } + }, + { + "object": "client0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + } + ] + } + ] + }, + { + "description": "client.watch succeeds after SocketException", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 9001 + } + } + } + }, + { + "object": "client0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + } + ] + } + ] + }, + { + "description": "client.watch fails after two NotWritablePrimary errors", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "client0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + } + ] + } + ] + }, + { + "description": "client.watch fails after NotWritablePrimary when retryReads is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ], + "ignoreCommandMonitoringEvents": [ + "killCursors" + ] + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "client1", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/changeStreams-client.watch-serverErrors.yml b/test/spec/retryable-reads/unified/changeStreams-client.watch-serverErrors.yml new file mode 100644 index 0000000000..7b6b8bbdf9 --- /dev/null +++ b/test/spec/retryable-reads/unified/changeStreams-client.watch-serverErrors.yml @@ -0,0 +1,359 @@ +description: changeStreams-client.watch-serverErrors + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - replicaset + - + minServerVersion: 4.1.7 + serverless: forbid + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + ignoreCommandMonitoringEvents: + - killCursors + +tests: + - + description: 'client.watch succeeds after InterruptedAtShutdown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 11600 + - &retryable_operation + object: *client0 + name: createChangeStream + arguments: + pipeline: [] + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + aggregate: 1 + cursor: { } + pipeline: + - + $changeStream: + allChangesForCluster: true + databaseName: admin + - *retryable_command_started_event + - + description: 'client.watch succeeds after InterruptedDueToReplStateChange' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 11602 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'client.watch succeeds after NotWritablePrimary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 10107 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'client.watch succeeds after NotPrimaryNoSecondaryOk' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 13435 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'client.watch succeeds after NotPrimaryOrSecondary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 13436 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'client.watch succeeds after PrimarySteppedDown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 189 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'client.watch succeeds after ShutdownInProgress' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 91 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'client.watch succeeds after HostNotFound' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 7 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'client.watch succeeds after HostUnreachable' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 6 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'client.watch succeeds after NetworkTimeout' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 89 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'client.watch succeeds after SocketException' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 9001 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'client.watch fails after two NotWritablePrimary errors' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - aggregate + errorCode: 10107 + - &retryable_operation_fails + object: *client0 + name: createChangeStream + arguments: + pipeline: [] + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'client.watch fails after NotWritablePrimary when retryReads is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + ignoreCommandMonitoringEvents: + - killCursors + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 10107 + - <<: *retryable_operation_fails + object: *client1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/changeStreams-client.watch.json b/test/spec/retryable-reads/unified/changeStreams-client.watch.json new file mode 100644 index 0000000000..95ddaf921d --- /dev/null +++ b/test/spec/retryable-reads/unified/changeStreams-client.watch.json @@ -0,0 +1,294 @@ +{ + "description": "changeStreams-client.watch", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "serverless": "forbid", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ], + "ignoreCommandMonitoringEvents": [ + "killCursors" + ] + } + } + ], + "tests": [ + { + "description": "client.watch succeeds on first attempt", + "operations": [ + { + "object": "client0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + } + ] + } + ] + }, + { + "description": "client.watch succeeds on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "closeConnection": true + } + } + } + }, + { + "object": "client0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + } + ] + } + ] + }, + { + "description": "client.watch fails on first attempt", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ], + "ignoreCommandMonitoringEvents": [ + "killCursors" + ] + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "closeConnection": true + } + } + } + }, + { + "object": "client1", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + } + ] + } + ] + }, + { + "description": "client.watch fails on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "closeConnection": true + } + } + } + }, + { + "object": "client0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": { + "allChangesForCluster": true + } + } + ] + }, + "databaseName": "admin" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/changeStreams-client.watch.yml b/test/spec/retryable-reads/unified/changeStreams-client.watch.yml new file mode 100644 index 0000000000..2fa3a300bc --- /dev/null +++ b/test/spec/retryable-reads/unified/changeStreams-client.watch.yml @@ -0,0 +1,131 @@ +description: changeStreams-client.watch + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - replicaset + - + minServerVersion: 4.1.7 + serverless: forbid + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + ignoreCommandMonitoringEvents: + - killCursors + +tests: + - + description: 'client.watch succeeds on first attempt' + operations: + - &retryable_operation + object: *client0 + name: createChangeStream + arguments: + pipeline: [] + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + aggregate: 1 + cursor: { } + pipeline: + - + $changeStream: + allChangesForCluster: true + databaseName: admin + - + description: 'client.watch succeeds on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + closeConnection: true + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'client.watch fails on first attempt' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + ignoreCommandMonitoringEvents: + - killCursors + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - &retryable_operation_fails + object: *client1 + name: createChangeStream + arguments: + pipeline: [] + expectError: + isError: true + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - + description: 'client.watch fails on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - aggregate + closeConnection: true + - <<: *retryable_operation_fails + object: *client0 + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/changeStreams-db.coll.watch-serverErrors.json b/test/spec/retryable-reads/unified/changeStreams-db.coll.watch-serverErrors.json new file mode 100644 index 0000000000..589d0a3c37 --- /dev/null +++ b/test/spec/retryable-reads/unified/changeStreams-db.coll.watch-serverErrors.json @@ -0,0 +1,944 @@ +{ + "description": "changeStreams-db.coll.watch-serverErrors", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "serverless": "forbid", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ], + "ignoreCommandMonitoringEvents": [ + "killCursors" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "db.coll.watch succeeds after InterruptedAtShutdown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 11600 + } + } + } + }, + { + "object": "collection0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.coll.watch succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 11602 + } + } + } + }, + { + "object": "collection0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.coll.watch succeeds after NotWritablePrimary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.coll.watch succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 13435 + } + } + } + }, + { + "object": "collection0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.coll.watch succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 13436 + } + } + } + }, + { + "object": "collection0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.coll.watch succeeds after PrimarySteppedDown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 189 + } + } + } + }, + { + "object": "collection0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.coll.watch succeeds after ShutdownInProgress", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 91 + } + } + } + }, + { + "object": "collection0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.coll.watch succeeds after HostNotFound", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 7 + } + } + } + }, + { + "object": "collection0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.coll.watch succeeds after HostUnreachable", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 6 + } + } + } + }, + { + "object": "collection0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.coll.watch succeeds after NetworkTimeout", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 89 + } + } + } + }, + { + "object": "collection0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.coll.watch succeeds after SocketException", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 9001 + } + } + } + }, + { + "object": "collection0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.coll.watch fails after two NotWritablePrimary errors", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.coll.watch fails after NotWritablePrimary when retryReads is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ], + "ignoreCommandMonitoringEvents": [ + "killCursors" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection1", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/changeStreams-db.coll.watch-serverErrors.yml b/test/spec/retryable-reads/unified/changeStreams-db.coll.watch-serverErrors.yml new file mode 100644 index 0000000000..8dc05560bc --- /dev/null +++ b/test/spec/retryable-reads/unified/changeStreams-db.coll.watch-serverErrors.yml @@ -0,0 +1,382 @@ +description: changeStreams-db.coll.watch-serverErrors + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - replicaset + - + minServerVersion: 4.1.7 + serverless: forbid + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + ignoreCommandMonitoringEvents: + - killCursors + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: [] + +tests: + - + description: 'db.coll.watch succeeds after InterruptedAtShutdown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 11600 + - &retryable_operation + object: *collection0 + name: createChangeStream + arguments: + pipeline: [] + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + aggregate: *collection_name + cursor: { } + pipeline: + - + $changeStream: { } + databaseName: *database_name + - *retryable_command_started_event + - + description: 'db.coll.watch succeeds after InterruptedDueToReplStateChange' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 11602 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.coll.watch succeeds after NotWritablePrimary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 10107 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.coll.watch succeeds after NotPrimaryNoSecondaryOk' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 13435 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.coll.watch succeeds after NotPrimaryOrSecondary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 13436 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.coll.watch succeeds after PrimarySteppedDown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 189 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.coll.watch succeeds after ShutdownInProgress' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 91 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.coll.watch succeeds after HostNotFound' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 7 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.coll.watch succeeds after HostUnreachable' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 6 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.coll.watch succeeds after NetworkTimeout' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 89 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.coll.watch succeeds after SocketException' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 9001 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.coll.watch fails after two NotWritablePrimary errors' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - aggregate + errorCode: 10107 + - &retryable_operation_fails + object: *collection0 + name: createChangeStream + arguments: + pipeline: [] + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.coll.watch fails after NotWritablePrimary when retryReads is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + ignoreCommandMonitoringEvents: + - killCursors + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 10107 + - <<: *retryable_operation_fails + object: *collection1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/changeStreams-db.coll.watch.json b/test/spec/retryable-reads/unified/changeStreams-db.coll.watch.json new file mode 100644 index 0000000000..bbea2ffe4f --- /dev/null +++ b/test/spec/retryable-reads/unified/changeStreams-db.coll.watch.json @@ -0,0 +1,314 @@ +{ + "description": "changeStreams-db.coll.watch", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "serverless": "forbid", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ], + "ignoreCommandMonitoringEvents": [ + "killCursors" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "db.coll.watch succeeds on first attempt", + "operations": [ + { + "object": "collection0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.coll.watch succeeds on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.coll.watch fails on first attempt", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection1", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.coll.watch fails on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/changeStreams-db.coll.watch.yml b/test/spec/retryable-reads/unified/changeStreams-db.coll.watch.yml new file mode 100644 index 0000000000..8106382283 --- /dev/null +++ b/test/spec/retryable-reads/unified/changeStreams-db.coll.watch.yml @@ -0,0 +1,152 @@ +description: changeStreams-db.coll.watch + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - replicaset + - + minServerVersion: 4.1.7 + serverless: forbid + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + ignoreCommandMonitoringEvents: + - killCursors + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: [] + +tests: + - + description: 'db.coll.watch succeeds on first attempt' + operations: + - &retryable_operation + object: *collection0 + name: createChangeStream + arguments: + pipeline: [] + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + aggregate: *collection_name + cursor: { } + pipeline: + - + $changeStream: { } + databaseName: *database_name + - + description: 'db.coll.watch succeeds on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + closeConnection: true + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.coll.watch fails on first attempt' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - &retryable_operation_fails + object: *collection1 + name: createChangeStream + arguments: + pipeline: [] + expectError: + isError: true + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - + description: 'db.coll.watch fails on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - aggregate + closeConnection: true + - <<: *retryable_operation_fails + object: *collection0 + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/changeStreams-db.watch-serverErrors.json b/test/spec/retryable-reads/unified/changeStreams-db.watch-serverErrors.json new file mode 100644 index 0000000000..6c12d7ddd8 --- /dev/null +++ b/test/spec/retryable-reads/unified/changeStreams-db.watch-serverErrors.json @@ -0,0 +1,930 @@ +{ + "description": "changeStreams-db.watch-serverErrors", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "serverless": "forbid", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ], + "ignoreCommandMonitoringEvents": [ + "killCursors" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "db.watch succeeds after InterruptedAtShutdown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 11600 + } + } + } + }, + { + "object": "database0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.watch succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 11602 + } + } + } + }, + { + "object": "database0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.watch succeeds after NotWritablePrimary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "database0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.watch succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 13435 + } + } + } + }, + { + "object": "database0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.watch succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 13436 + } + } + } + }, + { + "object": "database0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.watch succeeds after PrimarySteppedDown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 189 + } + } + } + }, + { + "object": "database0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.watch succeeds after ShutdownInProgress", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 91 + } + } + } + }, + { + "object": "database0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.watch succeeds after HostNotFound", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 7 + } + } + } + }, + { + "object": "database0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.watch succeeds after HostUnreachable", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 6 + } + } + } + }, + { + "object": "database0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.watch succeeds after NetworkTimeout", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 89 + } + } + } + }, + { + "object": "database0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.watch succeeds after SocketException", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 9001 + } + } + } + }, + { + "object": "database0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.watch fails after two NotWritablePrimary errors", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "database0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.watch fails after NotWritablePrimary when retryReads is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ], + "ignoreCommandMonitoringEvents": [ + "killCursors" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "database1", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/changeStreams-db.watch-serverErrors.yml b/test/spec/retryable-reads/unified/changeStreams-db.watch-serverErrors.yml new file mode 100644 index 0000000000..a90a802d91 --- /dev/null +++ b/test/spec/retryable-reads/unified/changeStreams-db.watch-serverErrors.yml @@ -0,0 +1,373 @@ +description: changeStreams-db.watch-serverErrors + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - replicaset + - + minServerVersion: 4.1.7 + serverless: forbid + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + ignoreCommandMonitoringEvents: + - killCursors + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + +initialData: + - + collectionName: &collection_name coll + databaseName: *database_name + documents: [] + +tests: + - + description: 'db.watch succeeds after InterruptedAtShutdown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 11600 + - &retryable_operation + object: *database0 + name: createChangeStream + arguments: + pipeline: [] + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + aggregate: 1 + cursor: { } + pipeline: + - + $changeStream: { } + databaseName: *database_name + - *retryable_command_started_event + - + description: 'db.watch succeeds after InterruptedDueToReplStateChange' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 11602 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.watch succeeds after NotWritablePrimary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 10107 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.watch succeeds after NotPrimaryNoSecondaryOk' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 13435 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.watch succeeds after NotPrimaryOrSecondary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 13436 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.watch succeeds after PrimarySteppedDown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 189 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.watch succeeds after ShutdownInProgress' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 91 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.watch succeeds after HostNotFound' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 7 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.watch succeeds after HostUnreachable' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 6 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.watch succeeds after NetworkTimeout' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 89 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.watch succeeds after SocketException' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 9001 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.watch fails after two NotWritablePrimary errors' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - aggregate + errorCode: 10107 + - &retryable_operation_fails + object: *database0 + name: createChangeStream + arguments: + pipeline: [] + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.watch fails after NotWritablePrimary when retryReads is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + ignoreCommandMonitoringEvents: + - killCursors + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 10107 + - <<: *retryable_operation_fails + object: *database1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/changeStreams-db.watch.json b/test/spec/retryable-reads/unified/changeStreams-db.watch.json new file mode 100644 index 0000000000..1b6d911c76 --- /dev/null +++ b/test/spec/retryable-reads/unified/changeStreams-db.watch.json @@ -0,0 +1,303 @@ +{ + "description": "changeStreams-db.watch", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "serverless": "forbid", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ], + "ignoreCommandMonitoringEvents": [ + "killCursors" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "db.watch succeeds on first attempt", + "operations": [ + { + "object": "database0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.watch succeeds on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "closeConnection": true + } + } + } + }, + { + "object": "database0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.watch fails on first attempt", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ], + "ignoreCommandMonitoringEvents": [ + "killCursors" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "closeConnection": true + } + } + } + }, + { + "object": "database1", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "db.watch fails on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "closeConnection": true + } + } + } + }, + { + "object": "database0", + "name": "createChangeStream", + "arguments": { + "pipeline": [] + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": 1, + "cursor": {}, + "pipeline": [ + { + "$changeStream": {} + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/changeStreams-db.watch.yml b/test/spec/retryable-reads/unified/changeStreams-db.watch.yml new file mode 100644 index 0000000000..47cbc0457d --- /dev/null +++ b/test/spec/retryable-reads/unified/changeStreams-db.watch.yml @@ -0,0 +1,145 @@ +description: changeStreams-db.watch + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - replicaset + - + minServerVersion: 4.1.7 + serverless: forbid + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + ignoreCommandMonitoringEvents: + - killCursors + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + +initialData: + - + collectionName: &collection_name coll + databaseName: *database_name + documents: [] + +tests: + - + description: 'db.watch succeeds on first attempt' + operations: + - &retryable_operation + object: *database0 + name: createChangeStream + arguments: + pipeline: [] + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + aggregate: 1 + cursor: { } + pipeline: + - + $changeStream: { } + databaseName: *database_name + - + description: 'db.watch succeeds on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + closeConnection: true + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'db.watch fails on first attempt' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + ignoreCommandMonitoringEvents: + - killCursors + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - &retryable_operation_fails + object: *database1 + name: createChangeStream + arguments: + pipeline: [] + expectError: + isError: true + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - + description: 'db.watch fails on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - aggregate + closeConnection: true + - <<: *retryable_operation_fails + object: *database0 + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/count-serverErrors.json b/test/spec/retryable-reads/unified/count-serverErrors.json new file mode 100644 index 0000000000..c52edfdb98 --- /dev/null +++ b/test/spec/retryable-reads/unified/count-serverErrors.json @@ -0,0 +1,808 @@ +{ + "description": "count-serverErrors", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "Count succeeds after InterruptedAtShutdown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 11600 + } + } + } + }, + { + "object": "collection0", + "name": "count", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Count succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 11602 + } + } + } + }, + { + "object": "collection0", + "name": "count", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Count succeeds after NotWritablePrimary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection0", + "name": "count", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Count succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 13435 + } + } + } + }, + { + "object": "collection0", + "name": "count", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Count succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 13436 + } + } + } + }, + { + "object": "collection0", + "name": "count", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Count succeeds after PrimarySteppedDown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 189 + } + } + } + }, + { + "object": "collection0", + "name": "count", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Count succeeds after ShutdownInProgress", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 91 + } + } + } + }, + { + "object": "collection0", + "name": "count", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Count succeeds after HostNotFound", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 7 + } + } + } + }, + { + "object": "collection0", + "name": "count", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Count succeeds after HostUnreachable", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 6 + } + } + } + }, + { + "object": "collection0", + "name": "count", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Count succeeds after NetworkTimeout", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 89 + } + } + } + }, + { + "object": "collection0", + "name": "count", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Count succeeds after SocketException", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 9001 + } + } + } + }, + { + "object": "collection0", + "name": "count", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Count fails after two NotWritablePrimary errors", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection0", + "name": "count", + "arguments": { + "filter": {} + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Count fails after NotWritablePrimary when retryReads is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection1", + "name": "count", + "arguments": { + "filter": {} + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/count-serverErrors.yml b/test/spec/retryable-reads/unified/count-serverErrors.yml new file mode 100644 index 0000000000..a433aaa87d --- /dev/null +++ b/test/spec/retryable-reads/unified/count-serverErrors.yml @@ -0,0 +1,381 @@ +description: count-serverErrors + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - + _id: 1 + x: 11 + - + _id: 2 + x: 22 + +tests: + - + description: 'Count succeeds after InterruptedAtShutdown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 11600 + - &retryable_operation_succeeds + object: *collection0 + name: count + arguments: + filter: { } + expectResult: 2 + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + count: *collection_name + databaseName: *database_name + - *retryable_command_started_event + - + description: 'Count succeeds after InterruptedDueToReplStateChange' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 11602 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Count succeeds after NotWritablePrimary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 10107 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Count succeeds after NotPrimaryNoSecondaryOk' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 13435 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Count succeeds after NotPrimaryOrSecondary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 13436 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Count succeeds after PrimarySteppedDown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 189 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Count succeeds after ShutdownInProgress' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 91 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Count succeeds after HostNotFound' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 7 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Count succeeds after HostUnreachable' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 6 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Count succeeds after NetworkTimeout' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 89 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Count succeeds after SocketException' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 9001 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Count fails after two NotWritablePrimary errors' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - count + errorCode: 10107 + - &retryable_operation_fails + object: *collection0 + name: count + arguments: + filter: { } + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Count fails after NotWritablePrimary when retryReads is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 10107 + - <<: *retryable_operation_fails + object: *collection1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/count.json b/test/spec/retryable-reads/unified/count.json new file mode 100644 index 0000000000..d5c9a343a9 --- /dev/null +++ b/test/spec/retryable-reads/unified/count.json @@ -0,0 +1,286 @@ +{ + "description": "count", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "Count succeeds on first attempt", + "operations": [ + { + "object": "collection0", + "name": "count", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Count succeeds on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "count", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Count fails on first attempt", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection1", + "name": "count", + "arguments": { + "filter": {} + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Count fails on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "count" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "count", + "arguments": { + "filter": {} + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/count.yml b/test/spec/retryable-reads/unified/count.yml new file mode 100644 index 0000000000..912f7578b4 --- /dev/null +++ b/test/spec/retryable-reads/unified/count.yml @@ -0,0 +1,153 @@ +description: count + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - + _id: 1 + x: 11 + - + _id: 2 + x: 22 + +tests: + - + description: 'Count succeeds on first attempt' + operations: + - &retryable_operation_succeeds + object: *collection0 + name: count + arguments: + filter: { } + expectResult: 2 + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + count: *collection_name + databaseName: *database_name + - + description: 'Count succeeds on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + closeConnection: true + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Count fails on first attempt' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - &retryable_operation_fails + object: *collection1 + name: count + arguments: + filter: { } + expectError: + isError: true + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - + description: 'Count fails on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - count + closeConnection: true + - <<: *retryable_operation_fails + object: *collection0 + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/countDocuments-serverErrors.json b/test/spec/retryable-reads/unified/countDocuments-serverErrors.json new file mode 100644 index 0000000000..fd028b114c --- /dev/null +++ b/test/spec/retryable-reads/unified/countDocuments-serverErrors.json @@ -0,0 +1,1133 @@ +{ + "description": "countDocuments-serverErrors", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "CountDocuments succeeds after InterruptedAtShutdown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 11600 + } + } + } + }, + { + "object": "collection0", + "name": "countDocuments", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "CountDocuments succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 11602 + } + } + } + }, + { + "object": "collection0", + "name": "countDocuments", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "CountDocuments succeeds after NotWritablePrimary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection0", + "name": "countDocuments", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "CountDocuments succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 13435 + } + } + } + }, + { + "object": "collection0", + "name": "countDocuments", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "CountDocuments succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 13436 + } + } + } + }, + { + "object": "collection0", + "name": "countDocuments", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "CountDocuments succeeds after PrimarySteppedDown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 189 + } + } + } + }, + { + "object": "collection0", + "name": "countDocuments", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "CountDocuments succeeds after ShutdownInProgress", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 91 + } + } + } + }, + { + "object": "collection0", + "name": "countDocuments", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "CountDocuments succeeds after HostNotFound", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 7 + } + } + } + }, + { + "object": "collection0", + "name": "countDocuments", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "CountDocuments succeeds after HostUnreachable", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 6 + } + } + } + }, + { + "object": "collection0", + "name": "countDocuments", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "CountDocuments succeeds after NetworkTimeout", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 89 + } + } + } + }, + { + "object": "collection0", + "name": "countDocuments", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "CountDocuments succeeds after SocketException", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 9001 + } + } + } + }, + { + "object": "collection0", + "name": "countDocuments", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "CountDocuments fails after two NotWritablePrimary errors", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection0", + "name": "countDocuments", + "arguments": { + "filter": {} + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "CountDocuments fails after NotWritablePrimary when retryReads is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection1", + "name": "countDocuments", + "arguments": { + "filter": {} + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/countDocuments-serverErrors.yml b/test/spec/retryable-reads/unified/countDocuments-serverErrors.yml new file mode 100644 index 0000000000..2bcca604f2 --- /dev/null +++ b/test/spec/retryable-reads/unified/countDocuments-serverErrors.yml @@ -0,0 +1,386 @@ +description: countDocuments-serverErrors +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - + _id: 1 + x: 11 + - + _id: 2 + x: 22 +tests: + - + description: 'CountDocuments succeeds after InterruptedAtShutdown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 11600 + - &retryable_operation_succeeds + object: *collection0 + name: countDocuments + arguments: + filter: { } + expectResult: 2 + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + aggregate: *collection_name + pipeline: + - + $match: { } + - + $group: + _id: 1 + 'n': { $sum: 1 } + databaseName: *database_name + - *retryable_command_started_event + - + description: 'CountDocuments succeeds after InterruptedDueToReplStateChange' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 11602 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'CountDocuments succeeds after NotWritablePrimary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 10107 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'CountDocuments succeeds after NotPrimaryNoSecondaryOk' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 13435 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'CountDocuments succeeds after NotPrimaryOrSecondary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 13436 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'CountDocuments succeeds after PrimarySteppedDown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 189 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'CountDocuments succeeds after ShutdownInProgress' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 91 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'CountDocuments succeeds after HostNotFound' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 7 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'CountDocuments succeeds after HostUnreachable' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 6 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'CountDocuments succeeds after NetworkTimeout' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 89 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'CountDocuments succeeds after SocketException' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 9001 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'CountDocuments fails after two NotWritablePrimary errors' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - aggregate + errorCode: 10107 + - &retryable_operation_fails + object: *collection0 + name: countDocuments + arguments: + filter: { } + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'CountDocuments fails after NotWritablePrimary when retryReads is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + errorCode: 10107 + - <<: *retryable_operation_fails + object: *collection1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/countDocuments.json b/test/spec/retryable-reads/unified/countDocuments.json new file mode 100644 index 0000000000..e06e89c1ad --- /dev/null +++ b/test/spec/retryable-reads/unified/countDocuments.json @@ -0,0 +1,364 @@ +{ + "description": "countDocuments", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "CountDocuments succeeds on first attempt", + "operations": [ + { + "object": "collection0", + "name": "countDocuments", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "CountDocuments succeeds on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "countDocuments", + "arguments": { + "filter": {} + }, + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "CountDocuments fails on first attempt", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection1", + "name": "countDocuments", + "arguments": { + "filter": {} + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "CountDocuments fails on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "aggregate" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "countDocuments", + "arguments": { + "filter": {} + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "aggregate": "coll", + "pipeline": [ + { + "$match": {} + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/countDocuments.yml b/test/spec/retryable-reads/unified/countDocuments.yml new file mode 100644 index 0000000000..725137deef --- /dev/null +++ b/test/spec/retryable-reads/unified/countDocuments.yml @@ -0,0 +1,158 @@ +description: countDocuments +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - + _id: 1 + x: 11 + - + _id: 2 + x: 22 +tests: + - + description: 'CountDocuments succeeds on first attempt' + operations: + - &retryable_operation_succeeds + object: *collection0 + name: countDocuments + arguments: + filter: { } + expectResult: 2 + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + aggregate: *collection_name + pipeline: + - + $match: { } + - + $group: + _id: 1 + 'n': { $sum: 1 } + databaseName: *database_name + - + description: 'CountDocuments succeeds on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - aggregate + closeConnection: true + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'CountDocuments fails on first attempt' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - &retryable_operation_fails + object: *collection1 + name: countDocuments + arguments: + filter: { } + expectError: + isError: true + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - + description: 'CountDocuments fails on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - aggregate + closeConnection: true + - <<: *retryable_operation_fails + object: *collection0 + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/distinct-serverErrors.json b/test/spec/retryable-reads/unified/distinct-serverErrors.json new file mode 100644 index 0000000000..79d2d5fc31 --- /dev/null +++ b/test/spec/retryable-reads/unified/distinct-serverErrors.json @@ -0,0 +1,1060 @@ +{ + "description": "distinct-serverErrors", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "Distinct succeeds after InterruptedAtShutdown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "distinct" + ], + "errorCode": 11600 + } + } + } + }, + { + "object": "collection0", + "name": "distinct", + "arguments": { + "fieldName": "x", + "filter": { + "_id": { + "$gt": 1 + } + } + }, + "expectResult": [ + 22, + 33 + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Distinct succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "distinct" + ], + "errorCode": 11602 + } + } + } + }, + { + "object": "collection0", + "name": "distinct", + "arguments": { + "fieldName": "x", + "filter": { + "_id": { + "$gt": 1 + } + } + }, + "expectResult": [ + 22, + 33 + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Distinct succeeds after NotWritablePrimary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "distinct" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection0", + "name": "distinct", + "arguments": { + "fieldName": "x", + "filter": { + "_id": { + "$gt": 1 + } + } + }, + "expectResult": [ + 22, + 33 + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Distinct succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "distinct" + ], + "errorCode": 13435 + } + } + } + }, + { + "object": "collection0", + "name": "distinct", + "arguments": { + "fieldName": "x", + "filter": { + "_id": { + "$gt": 1 + } + } + }, + "expectResult": [ + 22, + 33 + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Distinct succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "distinct" + ], + "errorCode": 13436 + } + } + } + }, + { + "object": "collection0", + "name": "distinct", + "arguments": { + "fieldName": "x", + "filter": { + "_id": { + "$gt": 1 + } + } + }, + "expectResult": [ + 22, + 33 + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Distinct succeeds after PrimarySteppedDown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "distinct" + ], + "errorCode": 189 + } + } + } + }, + { + "object": "collection0", + "name": "distinct", + "arguments": { + "fieldName": "x", + "filter": { + "_id": { + "$gt": 1 + } + } + }, + "expectResult": [ + 22, + 33 + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Distinct succeeds after ShutdownInProgress", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "distinct" + ], + "errorCode": 91 + } + } + } + }, + { + "object": "collection0", + "name": "distinct", + "arguments": { + "fieldName": "x", + "filter": { + "_id": { + "$gt": 1 + } + } + }, + "expectResult": [ + 22, + 33 + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Distinct succeeds after HostNotFound", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "distinct" + ], + "errorCode": 7 + } + } + } + }, + { + "object": "collection0", + "name": "distinct", + "arguments": { + "fieldName": "x", + "filter": { + "_id": { + "$gt": 1 + } + } + }, + "expectResult": [ + 22, + 33 + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Distinct succeeds after HostUnreachable", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "distinct" + ], + "errorCode": 6 + } + } + } + }, + { + "object": "collection0", + "name": "distinct", + "arguments": { + "fieldName": "x", + "filter": { + "_id": { + "$gt": 1 + } + } + }, + "expectResult": [ + 22, + 33 + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Distinct succeeds after NetworkTimeout", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "distinct" + ], + "errorCode": 89 + } + } + } + }, + { + "object": "collection0", + "name": "distinct", + "arguments": { + "fieldName": "x", + "filter": { + "_id": { + "$gt": 1 + } + } + }, + "expectResult": [ + 22, + 33 + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Distinct succeeds after SocketException", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "distinct" + ], + "errorCode": 9001 + } + } + } + }, + { + "object": "collection0", + "name": "distinct", + "arguments": { + "fieldName": "x", + "filter": { + "_id": { + "$gt": 1 + } + } + }, + "expectResult": [ + 22, + 33 + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Distinct fails after two NotWritablePrimary errors", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "distinct" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection0", + "name": "distinct", + "arguments": { + "fieldName": "x", + "filter": { + "_id": { + "$gt": 1 + } + } + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Distinct fails after NotWritablePrimary when retryReads is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "distinct" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection1", + "name": "distinct", + "arguments": { + "fieldName": "x", + "filter": { + "_id": { + "$gt": 1 + } + } + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/distinct-serverErrors.yml b/test/spec/retryable-reads/unified/distinct-serverErrors.yml new file mode 100644 index 0000000000..999e0b3fa0 --- /dev/null +++ b/test/spec/retryable-reads/unified/distinct-serverErrors.yml @@ -0,0 +1,396 @@ +description: distinct-serverErrors + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - + _id: 1 + x: 11 + - + _id: 2 + x: 22 + - + _id: 3 + x: 33 + +tests: + - + description: 'Distinct succeeds after InterruptedAtShutdown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - distinct + errorCode: 11600 + - &retryable_operation_succeeds + object: *collection0 + name: distinct + arguments: + fieldName: x + filter: + _id: + $gt: 1 + expectResult: + - 22 + - 33 + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + distinct: *collection_name + key: x + query: + _id: + $gt: 1 + databaseName: *database_name + - *retryable_command_started_event + - + description: 'Distinct succeeds after InterruptedDueToReplStateChange' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - distinct + errorCode: 11602 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Distinct succeeds after NotWritablePrimary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - distinct + errorCode: 10107 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Distinct succeeds after NotPrimaryNoSecondaryOk' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - distinct + errorCode: 13435 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Distinct succeeds after NotPrimaryOrSecondary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - distinct + errorCode: 13436 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Distinct succeeds after PrimarySteppedDown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - distinct + errorCode: 189 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Distinct succeeds after ShutdownInProgress' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - distinct + errorCode: 91 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Distinct succeeds after HostNotFound' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - distinct + errorCode: 7 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Distinct succeeds after HostUnreachable' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - distinct + errorCode: 6 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Distinct succeeds after NetworkTimeout' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - distinct + errorCode: 89 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Distinct succeeds after SocketException' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - distinct + errorCode: 9001 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Distinct fails after two NotWritablePrimary errors' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - distinct + errorCode: 10107 + - &retryable_operation_fails + object: *collection0 + name: distinct + arguments: + fieldName: x + filter: + _id: + $gt: 1 + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Distinct fails after NotWritablePrimary when retryReads is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - distinct + errorCode: 10107 + - <<: *retryable_operation_fails + object: *collection1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/distinct.json b/test/spec/retryable-reads/unified/distinct.json new file mode 100644 index 0000000000..81f1f66e91 --- /dev/null +++ b/test/spec/retryable-reads/unified/distinct.json @@ -0,0 +1,352 @@ +{ + "description": "distinct", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "Distinct succeeds on first attempt", + "operations": [ + { + "object": "collection0", + "name": "distinct", + "arguments": { + "fieldName": "x", + "filter": { + "_id": { + "$gt": 1 + } + } + }, + "expectResult": [ + 22, + 33 + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Distinct succeeds on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "distinct" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "distinct", + "arguments": { + "fieldName": "x", + "filter": { + "_id": { + "$gt": 1 + } + } + }, + "expectResult": [ + 22, + 33 + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Distinct fails on first attempt", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "distinct" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection1", + "name": "distinct", + "arguments": { + "fieldName": "x", + "filter": { + "_id": { + "$gt": 1 + } + } + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Distinct fails on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "distinct" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "distinct", + "arguments": { + "fieldName": "x", + "filter": { + "_id": { + "$gt": 1 + } + } + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "distinct": "coll", + "key": "x", + "query": { + "_id": { + "$gt": 1 + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/distinct.yml b/test/spec/retryable-reads/unified/distinct.yml new file mode 100644 index 0000000000..9b6f1648d7 --- /dev/null +++ b/test/spec/retryable-reads/unified/distinct.yml @@ -0,0 +1,168 @@ +description: distinct + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - + _id: 1 + x: 11 + - + _id: 2 + x: 22 + - + _id: 3 + x: 33 + +tests: + - + description: 'Distinct succeeds on first attempt' + operations: + - &retryable_operation_succeeds + object: *collection0 + name: distinct + arguments: + fieldName: x + filter: + _id: + $gt: 1 + expectResult: + - 22 + - 33 + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + distinct: *collection_name + key: x + query: + _id: + $gt: 1 + databaseName: *database_name + - + description: 'Distinct succeeds on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - distinct + closeConnection: true + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Distinct fails on first attempt' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - &retryable_operation_fails + object: *collection1 + name: distinct + arguments: + fieldName: x + filter: + _id: + $gt: 1 + expectError: + isError: true + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - + description: 'Distinct fails on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - distinct + closeConnection: true + - <<: *retryable_operation_fails + object: *collection0 + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/estimatedDocumentCount-serverErrors.json b/test/spec/retryable-reads/unified/estimatedDocumentCount-serverErrors.json new file mode 100644 index 0000000000..ba983c6cdf --- /dev/null +++ b/test/spec/retryable-reads/unified/estimatedDocumentCount-serverErrors.json @@ -0,0 +1,768 @@ +{ + "description": "estimatedDocumentCount-serverErrors", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "EstimatedDocumentCount succeeds after InterruptedAtShutdown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 11600 + } + } + } + }, + { + "object": "collection0", + "name": "estimatedDocumentCount", + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "EstimatedDocumentCount succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 11602 + } + } + } + }, + { + "object": "collection0", + "name": "estimatedDocumentCount", + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "EstimatedDocumentCount succeeds after NotWritablePrimary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection0", + "name": "estimatedDocumentCount", + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "EstimatedDocumentCount succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 13435 + } + } + } + }, + { + "object": "collection0", + "name": "estimatedDocumentCount", + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "EstimatedDocumentCount succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 13436 + } + } + } + }, + { + "object": "collection0", + "name": "estimatedDocumentCount", + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "EstimatedDocumentCount succeeds after PrimarySteppedDown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 189 + } + } + } + }, + { + "object": "collection0", + "name": "estimatedDocumentCount", + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "EstimatedDocumentCount succeeds after ShutdownInProgress", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 91 + } + } + } + }, + { + "object": "collection0", + "name": "estimatedDocumentCount", + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "EstimatedDocumentCount succeeds after HostNotFound", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 7 + } + } + } + }, + { + "object": "collection0", + "name": "estimatedDocumentCount", + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "EstimatedDocumentCount succeeds after HostUnreachable", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 6 + } + } + } + }, + { + "object": "collection0", + "name": "estimatedDocumentCount", + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "EstimatedDocumentCount succeeds after NetworkTimeout", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 89 + } + } + } + }, + { + "object": "collection0", + "name": "estimatedDocumentCount", + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "EstimatedDocumentCount succeeds after SocketException", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 9001 + } + } + } + }, + { + "object": "collection0", + "name": "estimatedDocumentCount", + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "EstimatedDocumentCount fails after two NotWritablePrimary errors", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection0", + "name": "estimatedDocumentCount", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "EstimatedDocumentCount fails after NotWritablePrimary when retryReads is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection1", + "name": "estimatedDocumentCount", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/estimatedDocumentCount-serverErrors.yml b/test/spec/retryable-reads/unified/estimatedDocumentCount-serverErrors.yml new file mode 100644 index 0000000000..98fa5ec9f7 --- /dev/null +++ b/test/spec/retryable-reads/unified/estimatedDocumentCount-serverErrors.yml @@ -0,0 +1,376 @@ +description: estimatedDocumentCount-serverErrors + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - + _id: 1 + x: 11 + - + _id: 2 + x: 22 + +tests: + - + description: 'EstimatedDocumentCount succeeds after InterruptedAtShutdown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 11600 + - &retryable_operation_succeeds + object: *collection0 + name: estimatedDocumentCount + expectResult: 2 + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + count: *collection_name + databaseName: *database_name + - *retryable_command_started_event + - + description: 'EstimatedDocumentCount succeeds after InterruptedDueToReplStateChange' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 11602 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'EstimatedDocumentCount succeeds after NotWritablePrimary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 10107 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'EstimatedDocumentCount succeeds after NotPrimaryNoSecondaryOk' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 13435 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'EstimatedDocumentCount succeeds after NotPrimaryOrSecondary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 13436 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'EstimatedDocumentCount succeeds after PrimarySteppedDown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 189 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'EstimatedDocumentCount succeeds after ShutdownInProgress' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 91 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'EstimatedDocumentCount succeeds after HostNotFound' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 7 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'EstimatedDocumentCount succeeds after HostUnreachable' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 6 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'EstimatedDocumentCount succeeds after NetworkTimeout' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 89 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'EstimatedDocumentCount succeeds after SocketException' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 9001 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'EstimatedDocumentCount fails after two NotWritablePrimary errors' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - count + errorCode: 10107 + - &retryable_operation_fails + object: *collection0 + name: estimatedDocumentCount + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'EstimatedDocumentCount fails after NotWritablePrimary when retryReads is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + errorCode: 10107 + - <<: *retryable_operation_fails + object: *collection1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/estimatedDocumentCount.json b/test/spec/retryable-reads/unified/estimatedDocumentCount.json new file mode 100644 index 0000000000..75a676b9b6 --- /dev/null +++ b/test/spec/retryable-reads/unified/estimatedDocumentCount.json @@ -0,0 +1,273 @@ +{ + "description": "estimatedDocumentCount", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "EstimatedDocumentCount succeeds on first attempt", + "operations": [ + { + "object": "collection0", + "name": "estimatedDocumentCount", + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "EstimatedDocumentCount succeeds on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "estimatedDocumentCount", + "expectResult": 2 + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "EstimatedDocumentCount fails on first attempt", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "count" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection1", + "name": "estimatedDocumentCount", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "EstimatedDocumentCount fails on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "count" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "estimatedDocumentCount", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "count": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/estimatedDocumentCount.yml b/test/spec/retryable-reads/unified/estimatedDocumentCount.yml new file mode 100644 index 0000000000..a4cac5a64e --- /dev/null +++ b/test/spec/retryable-reads/unified/estimatedDocumentCount.yml @@ -0,0 +1,148 @@ +description: estimatedDocumentCount + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - + _id: 1 + x: 11 + - + _id: 2 + x: 22 + +tests: + - + description: 'EstimatedDocumentCount succeeds on first attempt' + operations: + - &retryable_operation_succeeds + object: *collection0 + name: estimatedDocumentCount + expectResult: 2 + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + count: *collection_name + databaseName: *database_name + - + description: 'EstimatedDocumentCount succeeds on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - count + closeConnection: true + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'EstimatedDocumentCount fails on first attempt' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - &retryable_operation_fails + object: *collection1 + name: estimatedDocumentCount + expectError: + isError: true + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - + description: 'EstimatedDocumentCount fails on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - count + closeConnection: true + - <<: *retryable_operation_fails + object: *collection0 + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/find-serverErrors.json b/test/spec/retryable-reads/unified/find-serverErrors.json new file mode 100644 index 0000000000..ab3dbe45f4 --- /dev/null +++ b/test/spec/retryable-reads/unified/find-serverErrors.json @@ -0,0 +1,1184 @@ +{ + "description": "find-serverErrors", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + }, + { + "_id": 5, + "x": 55 + } + ] + } + ], + "tests": [ + { + "description": "Find succeeds after InterruptedAtShutdown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 11600 + } + } + } + }, + { + "object": "collection0", + "name": "find", + "arguments": { + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "expectResult": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Find succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 11602 + } + } + } + }, + { + "object": "collection0", + "name": "find", + "arguments": { + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "expectResult": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Find succeeds after NotWritablePrimary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection0", + "name": "find", + "arguments": { + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "expectResult": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Find succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 13435 + } + } + } + }, + { + "object": "collection0", + "name": "find", + "arguments": { + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "expectResult": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Find succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 13436 + } + } + } + }, + { + "object": "collection0", + "name": "find", + "arguments": { + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "expectResult": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Find succeeds after PrimarySteppedDown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 189 + } + } + } + }, + { + "object": "collection0", + "name": "find", + "arguments": { + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "expectResult": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Find succeeds after ShutdownInProgress", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 91 + } + } + } + }, + { + "object": "collection0", + "name": "find", + "arguments": { + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "expectResult": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Find succeeds after HostNotFound", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 7 + } + } + } + }, + { + "object": "collection0", + "name": "find", + "arguments": { + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "expectResult": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Find succeeds after HostUnreachable", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 6 + } + } + } + }, + { + "object": "collection0", + "name": "find", + "arguments": { + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "expectResult": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Find succeeds after NetworkTimeout", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 89 + } + } + } + }, + { + "object": "collection0", + "name": "find", + "arguments": { + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "expectResult": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Find succeeds after SocketException", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 9001 + } + } + } + }, + { + "object": "collection0", + "name": "find", + "arguments": { + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "expectResult": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Find fails after two NotWritablePrimary errors", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection0", + "name": "find", + "arguments": { + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Find fails after NotWritablePrimary when retryReads is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection1", + "name": "find", + "arguments": { + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/find-serverErrors.yml b/test/spec/retryable-reads/unified/find-serverErrors.yml new file mode 100644 index 0000000000..039cf25d95 --- /dev/null +++ b/test/spec/retryable-reads/unified/find-serverErrors.yml @@ -0,0 +1,412 @@ +description: find-serverErrors + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - + _id: 1 + x: 11 + - + _id: 2 + x: 22 + - + _id: 3 + x: 33 + - + _id: 4 + x: 44 + - + _id: 5 + x: 55 + +tests: + - + description: 'Find succeeds after InterruptedAtShutdown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 11600 + - &retryable_operation_succeeds + object: *collection0 + name: find + arguments: + filter: { } + sort: + _id: 1 + limit: 4 + expectResult: + - + _id: 1 + x: 11 + - + _id: 2 + x: 22 + - + _id: 3 + x: 33 + - + _id: 4 + x: 44 + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + find: *collection_name + filter: { } + sort: + _id: 1 + limit: 4 + databaseName: *database_name + - *retryable_command_started_event + - + description: 'Find succeeds after InterruptedDueToReplStateChange' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 11602 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Find succeeds after NotWritablePrimary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 10107 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Find succeeds after NotPrimaryNoSecondaryOk' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 13435 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Find succeeds after NotPrimaryOrSecondary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 13436 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Find succeeds after PrimarySteppedDown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 189 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Find succeeds after ShutdownInProgress' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 91 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Find succeeds after HostNotFound' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 7 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Find succeeds after HostUnreachable' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 6 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Find succeeds after NetworkTimeout' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 89 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Find succeeds after SocketException' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 9001 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Find fails after two NotWritablePrimary errors' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - find + errorCode: 10107 + - &retryable_operation_fails + object: *collection0 + name: find + arguments: + filter: { } + sort: + _id: 1 + limit: 4 + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Find fails after NotWritablePrimary when retryReads is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 10107 + - <<: *retryable_operation_fails + object: *collection1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/find.json b/test/spec/retryable-reads/unified/find.json new file mode 100644 index 0000000000..30c4c5e478 --- /dev/null +++ b/test/spec/retryable-reads/unified/find.json @@ -0,0 +1,498 @@ +{ + "description": "find", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + }, + { + "_id": 5, + "x": 55 + } + ] + } + ], + "tests": [ + { + "description": "Find succeeds on first attempt", + "operations": [ + { + "object": "collection0", + "name": "find", + "arguments": { + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "expectResult": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Find succeeds on second attempt with explicit clientOptions", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": true + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection1", + "name": "find", + "arguments": { + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "expectResult": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Find succeeds on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "find", + "arguments": { + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "expectResult": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Find fails on first attempt", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection1", + "name": "find", + "arguments": { + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Find fails on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "find" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "find", + "arguments": { + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": {}, + "sort": { + "_id": 1 + }, + "limit": 4 + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/find.yml b/test/spec/retryable-reads/unified/find.yml new file mode 100644 index 0000000000..bcd98684cc --- /dev/null +++ b/test/spec/retryable-reads/unified/find.yml @@ -0,0 +1,221 @@ +description: find + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - + _id: 1 + x: 11 + - + _id: 2 + x: 22 + - + _id: 3 + x: 33 + - + _id: 4 + x: 44 + - + _id: 5 + x: 55 + +tests: + - + description: 'Find succeeds on first attempt' + operations: + - &retryable_operation_succeeds + object: *collection0 + name: find + arguments: + filter: { } + sort: + _id: 1 + limit: 4 + expectResult: + - + _id: 1 + x: 11 + - + _id: 2 + x: 22 + - + _id: 3 + x: 33 + - + _id: 4 + x: 44 + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + find: *collection_name + filter: { } + sort: + _id: 1 + limit: 4 + databaseName: *database_name + - + description: 'Find succeeds on second attempt with explicit clientOptions' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: true + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + closeConnection: true + - <<: *retryable_operation_succeeds + object: *collection1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Find succeeds on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: *failCommand_failPoint + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Find fails on first attempt' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - &retryable_operation_fails + object: *collection1 + name: find + arguments: + filter: { } + sort: + _id: 1 + limit: 4 + expectError: + isError: true + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - + description: 'Find fails on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - find + closeConnection: true + - <<: *retryable_operation_fails + object: *collection0 + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/findOne-serverErrors.json b/test/spec/retryable-reads/unified/findOne-serverErrors.json new file mode 100644 index 0000000000..7adda1e32b --- /dev/null +++ b/test/spec/retryable-reads/unified/findOne-serverErrors.json @@ -0,0 +1,954 @@ +{ + "description": "findOne-serverErrors", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + }, + { + "_id": 5, + "x": 55 + } + ] + } + ], + "tests": [ + { + "description": "FindOne succeeds after InterruptedAtShutdown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 11600 + } + } + } + }, + { + "object": "collection0", + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "FindOne succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 11602 + } + } + } + }, + { + "object": "collection0", + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "FindOne succeeds after NotWritablePrimary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection0", + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "FindOne succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 13435 + } + } + } + }, + { + "object": "collection0", + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "FindOne succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 13436 + } + } + } + }, + { + "object": "collection0", + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "FindOne succeeds after PrimarySteppedDown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 189 + } + } + } + }, + { + "object": "collection0", + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "FindOne succeeds after ShutdownInProgress", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 91 + } + } + } + }, + { + "object": "collection0", + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "FindOne succeeds after HostNotFound", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 7 + } + } + } + }, + { + "object": "collection0", + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "FindOne succeeds after HostUnreachable", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 6 + } + } + } + }, + { + "object": "collection0", + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "FindOne succeeds after NetworkTimeout", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 89 + } + } + } + }, + { + "object": "collection0", + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "FindOne succeeds after SocketException", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 9001 + } + } + } + }, + { + "object": "collection0", + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "FindOne fails after two NotWritablePrimary errors", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection0", + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "FindOne fails after NotWritablePrimary when retryReads is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection1", + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/findOne-serverErrors.yml b/test/spec/retryable-reads/unified/findOne-serverErrors.yml new file mode 100644 index 0000000000..48e461f11b --- /dev/null +++ b/test/spec/retryable-reads/unified/findOne-serverErrors.yml @@ -0,0 +1,396 @@ +description: findOne-serverErrors + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - + _id: 1 + x: 11 + - + _id: 2 + x: 22 + - + _id: 3 + x: 33 + - + _id: 4 + x: 44 + - + _id: 5 + x: 55 + +tests: + - + description: 'FindOne succeeds after InterruptedAtShutdown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 11600 + - &retryable_operation_succeeds + object: *collection0 + name: findOne + arguments: + filter: + _id: 1 + expectResult: + _id: 1 + x: 11 + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + find: *collection_name + filter: + _id: 1 + databaseName: *database_name + - *retryable_command_started_event + - + description: 'FindOne succeeds after InterruptedDueToReplStateChange' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 11602 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'FindOne succeeds after NotWritablePrimary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 10107 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'FindOne succeeds after NotPrimaryNoSecondaryOk' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 13435 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'FindOne succeeds after NotPrimaryOrSecondary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 13436 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'FindOne succeeds after PrimarySteppedDown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 189 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'FindOne succeeds after ShutdownInProgress' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 91 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'FindOne succeeds after HostNotFound' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 7 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'FindOne succeeds after HostUnreachable' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 6 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'FindOne succeeds after NetworkTimeout' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 89 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'FindOne succeeds after SocketException' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 9001 + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'FindOne fails after two NotWritablePrimary errors' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - find + errorCode: 10107 + - &retryable_operation_fails + object: *collection0 + name: findOne + arguments: + filter: + _id: 1 + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'FindOne fails after NotWritablePrimary when retryReads is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 10107 + - <<: *retryable_operation_fails + object: *collection1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/findOne.json b/test/spec/retryable-reads/unified/findOne.json new file mode 100644 index 0000000000..4314a19e46 --- /dev/null +++ b/test/spec/retryable-reads/unified/findOne.json @@ -0,0 +1,330 @@ +{ + "description": "findOne", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + }, + { + "_id": 5, + "x": 55 + } + ] + } + ], + "tests": [ + { + "description": "FindOne succeeds on first attempt", + "operations": [ + { + "object": "collection0", + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "FindOne succeeds on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "FindOne fails on first attempt", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection1", + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "FindOne fails on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "find" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "coll", + "filter": { + "_id": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/findOne.yml b/test/spec/retryable-reads/unified/findOne.yml new file mode 100644 index 0000000000..e4de9d77f0 --- /dev/null +++ b/test/spec/retryable-reads/unified/findOne.yml @@ -0,0 +1,168 @@ +description: findOne + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - + _id: 1 + x: 11 + - + _id: 2 + x: 22 + - + _id: 3 + x: 33 + - + _id: 4 + x: 44 + - + _id: 5 + x: 55 + +tests: + - + description: 'FindOne succeeds on first attempt' + operations: + - &retryable_operation_succeeds + object: *collection0 + name: findOne + arguments: + filter: + _id: 1 + expectResult: + _id: 1 + x: 11 + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + find: *collection_name + filter: + _id: 1 + databaseName: *database_name + - + description: 'FindOne succeeds on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + closeConnection: true + - *retryable_operation_succeeds + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'FindOne fails on first attempt' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - &retryable_operation_fails + object: *collection1 + name: findOne + arguments: + filter: + _id: 1 + expectError: + isError: true + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - + description: 'FindOne fails on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - find + closeConnection: true + - <<: *retryable_operation_fails + object: *collection0 + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/gridfs-download-serverErrors.json b/test/spec/retryable-reads/unified/gridfs-download-serverErrors.json new file mode 100644 index 0000000000..5bb7eee0b2 --- /dev/null +++ b/test/spec/retryable-reads/unified/gridfs-download-serverErrors.json @@ -0,0 +1,1092 @@ +{ + "description": "gridfs-download-serverErrors", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "bucket": { + "id": "bucket0", + "database": "database0" + } + } + ], + "initialData": [ + { + "collectionName": "fs.files", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "length": 1, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "filename": "abc", + "metadata": {} + } + ] + }, + { + "collectionName": "fs.chunks", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000002" + }, + "files_id": { + "$oid": "000000000000000000000001" + }, + "n": 0, + "data": { + "$binary": { + "base64": "EQ==", + "subType": "00" + } + } + } + ] + } + ], + "tests": [ + { + "description": "Download succeeds after InterruptedAtShutdown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 11600 + } + } + } + }, + { + "object": "bucket0", + "name": "download", + "arguments": { + "id": { + "$oid": "000000000000000000000001" + } + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Download succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 11602 + } + } + } + }, + { + "object": "bucket0", + "name": "download", + "arguments": { + "id": { + "$oid": "000000000000000000000001" + } + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Download succeeds after NotWritablePrimary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "bucket0", + "name": "download", + "arguments": { + "id": { + "$oid": "000000000000000000000001" + } + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Download succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 13435 + } + } + } + }, + { + "object": "bucket0", + "name": "download", + "arguments": { + "id": { + "$oid": "000000000000000000000001" + } + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Download succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 13436 + } + } + } + }, + { + "object": "bucket0", + "name": "download", + "arguments": { + "id": { + "$oid": "000000000000000000000001" + } + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Download succeeds after PrimarySteppedDown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 189 + } + } + } + }, + { + "object": "bucket0", + "name": "download", + "arguments": { + "id": { + "$oid": "000000000000000000000001" + } + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Download succeeds after ShutdownInProgress", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 91 + } + } + } + }, + { + "object": "bucket0", + "name": "download", + "arguments": { + "id": { + "$oid": "000000000000000000000001" + } + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Download succeeds after HostNotFound", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 7 + } + } + } + }, + { + "object": "bucket0", + "name": "download", + "arguments": { + "id": { + "$oid": "000000000000000000000001" + } + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Download succeeds after HostUnreachable", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 6 + } + } + } + }, + { + "object": "bucket0", + "name": "download", + "arguments": { + "id": { + "$oid": "000000000000000000000001" + } + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Download succeeds after NetworkTimeout", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 89 + } + } + } + }, + { + "object": "bucket0", + "name": "download", + "arguments": { + "id": { + "$oid": "000000000000000000000001" + } + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Download succeeds after SocketException", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 9001 + } + } + } + }, + { + "object": "bucket0", + "name": "download", + "arguments": { + "id": { + "$oid": "000000000000000000000001" + } + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Download fails after two NotWritablePrimary errors", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "bucket0", + "name": "download", + "arguments": { + "id": { + "$oid": "000000000000000000000001" + } + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Download fails after NotWritablePrimary when retryReads is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "bucket": { + "id": "bucket1", + "database": "database1" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "bucket1", + "name": "download", + "arguments": { + "id": { + "$oid": "000000000000000000000001" + } + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/gridfs-download-serverErrors.yml b/test/spec/retryable-reads/unified/gridfs-download-serverErrors.yml new file mode 100644 index 0000000000..b7942f6f51 --- /dev/null +++ b/test/spec/retryable-reads/unified/gridfs-download-serverErrors.yml @@ -0,0 +1,421 @@ +description: gridfs-download-serverErrors + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + bucket: + id: &bucket0 bucket0 + database: *database0 + +initialData: + - + collectionName: &files_collection_name fs.files + databaseName: *database_name + documents: + - + _id: + $oid: '000000000000000000000001' + length: 1 + chunkSize: 4 + uploadDate: + $date: '1970-01-01T00:00:00.000Z' + filename: abc + metadata: { } + - + collectionName: &chunks_collection_name fs.chunks + databaseName: *database_name + documents: + - + _id: + $oid: '000000000000000000000002' + files_id: + $oid: '000000000000000000000001' + 'n': 0 + data: + $binary: + base64: EQ== # hex: 11 + subType: '00' + +tests: + - + description: 'Download succeeds after InterruptedAtShutdown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 11600 + - &retryable_operation + object: *bucket0 + name: download + arguments: + id: + $oid: '000000000000000000000001' + expectResult: + $$matchesHexBytes: "11" + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + find: *files_collection_name + filter: + _id: + $oid: '000000000000000000000001' + databaseName: *database_name + - *retryable_command_started_event + - &find_chunks_command_started_event + commandStartedEvent: + command: + find: *chunks_collection_name + # Avoid checking additional fields since the exact query may + # differ among drivers. expectResult is sufficient to assert + # correctness. + databaseName: *database_name + - + description: 'Download succeeds after InterruptedDueToReplStateChange' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 11602 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'Download succeeds after NotWritablePrimary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 10107 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'Download succeeds after NotPrimaryNoSecondaryOk' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 13435 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'Download succeeds after NotPrimaryOrSecondary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 13436 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'Download succeeds after PrimarySteppedDown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 189 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'Download succeeds after ShutdownInProgress' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 91 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'Download succeeds after HostNotFound' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 7 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'Download succeeds after HostUnreachable' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 6 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'Download succeeds after NetworkTimeout' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 89 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'Download succeeds after SocketException' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 9001 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'Download fails after two NotWritablePrimary errors' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - find + errorCode: 10107 + - &retryable_operation_fails + object: *bucket0 + name: download + arguments: + id: + $oid: '000000000000000000000001' + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'Download fails after NotWritablePrimary when retryReads is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - + bucket: + id: &bucket1 bucket1 + database: *database1 + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 10107 + - <<: *retryable_operation_fails + object: *bucket1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/gridfs-download.json b/test/spec/retryable-reads/unified/gridfs-download.json new file mode 100644 index 0000000000..69fe8ff7c8 --- /dev/null +++ b/test/spec/retryable-reads/unified/gridfs-download.json @@ -0,0 +1,367 @@ +{ + "description": "gridfs-download", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "bucket": { + "id": "bucket0", + "database": "database0" + } + } + ], + "initialData": [ + { + "collectionName": "fs.files", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "length": 1, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "filename": "abc", + "metadata": {} + } + ] + }, + { + "collectionName": "fs.chunks", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000002" + }, + "files_id": { + "$oid": "000000000000000000000001" + }, + "n": 0, + "data": { + "$binary": { + "base64": "EQ==", + "subType": "00" + } + } + } + ] + } + ], + "tests": [ + { + "description": "Download succeeds on first attempt", + "operations": [ + { + "object": "bucket0", + "name": "download", + "arguments": { + "id": { + "$oid": "000000000000000000000001" + } + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Download succeeds on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "closeConnection": true + } + } + } + }, + { + "object": "bucket0", + "name": "download", + "arguments": { + "id": { + "$oid": "000000000000000000000001" + } + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Download fails on first attempt", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "bucket": { + "id": "bucket1", + "database": "database1" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "closeConnection": true + } + } + } + }, + { + "object": "bucket1", + "name": "download", + "arguments": { + "id": { + "$oid": "000000000000000000000001" + } + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "Download fails on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "find" + ], + "closeConnection": true + } + } + } + }, + { + "object": "bucket0", + "name": "download", + "arguments": { + "id": { + "$oid": "000000000000000000000001" + } + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "_id": { + "$oid": "000000000000000000000001" + } + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/gridfs-download.yml b/test/spec/retryable-reads/unified/gridfs-download.yml new file mode 100644 index 0000000000..8164e7e826 --- /dev/null +++ b/test/spec/retryable-reads/unified/gridfs-download.yml @@ -0,0 +1,184 @@ +description: gridfs-download + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + bucket: + id: &bucket0 bucket0 + database: *database0 + +initialData: + - + collectionName: &files_collection_name fs.files + databaseName: *database_name + documents: + - + _id: + $oid: '000000000000000000000001' + length: 1 + chunkSize: 4 + uploadDate: + $date: '1970-01-01T00:00:00.000Z' + filename: abc + metadata: { } + - + collectionName: &chunks_collection_name fs.chunks + databaseName: *database_name + documents: + - + _id: + $oid: '000000000000000000000002' + files_id: + $oid: '000000000000000000000001' + 'n': 0 + data: + $binary: + base64: EQ== # hex: 11 + subType: '00' + +tests: + - + description: 'Download succeeds on first attempt' + operations: + - &retryable_operation + object: *bucket0 + name: download + arguments: + id: + $oid: '000000000000000000000001' + expectResult: + $$matchesHexBytes: "11" + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + find: *files_collection_name + filter: + _id: + $oid: '000000000000000000000001' + databaseName: *database_name + - &find_chunks_command_started_event + commandStartedEvent: + command: + find: *chunks_collection_name + # Avoid checking additional fields since the exact query may + # differ among drivers. expectResult is sufficient to assert + # correctness. + databaseName: *database_name + - + description: 'Download succeeds on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + closeConnection: true + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'Download fails on first attempt' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - + bucket: + id: &bucket1 bucket1 + database: *database1 + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - &retryable_operation_fails + object: *bucket1 + name: download + arguments: + id: + $oid: '000000000000000000000001' + expectError: + isError: true + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - + description: 'Download fails on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - find + closeConnection: true + - <<: *retryable_operation_fails + object: *bucket0 + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/gridfs-downloadByName-serverErrors.json b/test/spec/retryable-reads/unified/gridfs-downloadByName-serverErrors.json new file mode 100644 index 0000000000..35f7e1e563 --- /dev/null +++ b/test/spec/retryable-reads/unified/gridfs-downloadByName-serverErrors.json @@ -0,0 +1,1016 @@ +{ + "description": "gridfs-downloadByName-serverErrors", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "bucket": { + "id": "bucket0", + "database": "database0" + } + } + ], + "initialData": [ + { + "collectionName": "fs.files", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "length": 1, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "filename": "abc", + "metadata": {} + } + ] + }, + { + "collectionName": "fs.chunks", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000002" + }, + "files_id": { + "$oid": "000000000000000000000001" + }, + "n": 0, + "data": { + "$binary": { + "base64": "EQ==", + "subType": "00" + } + } + } + ] + } + ], + "tests": [ + { + "description": "DownloadByName succeeds after InterruptedAtShutdown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 11600 + } + } + } + }, + { + "object": "bucket0", + "name": "downloadByName", + "arguments": { + "filename": "abc" + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "DownloadByName succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 11602 + } + } + } + }, + { + "object": "bucket0", + "name": "downloadByName", + "arguments": { + "filename": "abc" + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "DownloadByName succeeds after NotWritablePrimary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "bucket0", + "name": "downloadByName", + "arguments": { + "filename": "abc" + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "DownloadByName succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 13435 + } + } + } + }, + { + "object": "bucket0", + "name": "downloadByName", + "arguments": { + "filename": "abc" + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "DownloadByName succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 13436 + } + } + } + }, + { + "object": "bucket0", + "name": "downloadByName", + "arguments": { + "filename": "abc" + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "DownloadByName succeeds after PrimarySteppedDown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 189 + } + } + } + }, + { + "object": "bucket0", + "name": "downloadByName", + "arguments": { + "filename": "abc" + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "DownloadByName succeeds after ShutdownInProgress", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 91 + } + } + } + }, + { + "object": "bucket0", + "name": "downloadByName", + "arguments": { + "filename": "abc" + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "DownloadByName succeeds after HostNotFound", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 7 + } + } + } + }, + { + "object": "bucket0", + "name": "downloadByName", + "arguments": { + "filename": "abc" + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "DownloadByName succeeds after HostUnreachable", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 6 + } + } + } + }, + { + "object": "bucket0", + "name": "downloadByName", + "arguments": { + "filename": "abc" + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "DownloadByName succeeds after NetworkTimeout", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 89 + } + } + } + }, + { + "object": "bucket0", + "name": "downloadByName", + "arguments": { + "filename": "abc" + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "DownloadByName succeeds after SocketException", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 9001 + } + } + } + }, + { + "object": "bucket0", + "name": "downloadByName", + "arguments": { + "filename": "abc" + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "DownloadByName fails after two NotWritablePrimary errors", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "bucket0", + "name": "downloadByName", + "arguments": { + "filename": "abc" + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "DownloadByName fails after NotWritablePrimary when retryReads is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "bucket": { + "id": "bucket1", + "database": "database1" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "bucket1", + "name": "downloadByName", + "arguments": { + "filename": "abc" + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/gridfs-downloadByName-serverErrors.yml b/test/spec/retryable-reads/unified/gridfs-downloadByName-serverErrors.yml new file mode 100644 index 0000000000..04d1c809d9 --- /dev/null +++ b/test/spec/retryable-reads/unified/gridfs-downloadByName-serverErrors.yml @@ -0,0 +1,418 @@ +description: gridfs-downloadByName-serverErrors + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + bucket: + id: &bucket0 bucket0 + database: *database0 + +initialData: + - + collectionName: &files_collection_name fs.files + databaseName: *database_name + documents: + - + _id: + $oid: '000000000000000000000001' + length: 1 + chunkSize: 4 + uploadDate: + $date: '1970-01-01T00:00:00.000Z' + filename: abc + metadata: { } + - + collectionName: &chunks_collection_name fs.chunks + databaseName: *database_name + documents: + - + _id: + $oid: '000000000000000000000002' + files_id: + $oid: '000000000000000000000001' + 'n': 0 + data: + $binary: + base64: EQ== # hex: 11 + subType: '00' + +tests: + - + description: 'DownloadByName succeeds after InterruptedAtShutdown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 11600 + - &retryable_operation + object: *bucket0 + name: downloadByName + arguments: + filename: abc + expectResult: + $$matchesHexBytes: "11" + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + find: *files_collection_name + filter: + filename: abc + databaseName: *database_name + - *retryable_command_started_event + - &find_chunks_command_started_event + commandStartedEvent: + command: + find: *chunks_collection_name + # Avoid checking additional fields since the exact query may + # differ among drivers. expectResult is sufficient to assert + # correctness. + databaseName: *database_name + - + description: 'DownloadByName succeeds after InterruptedDueToReplStateChange' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 11602 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'DownloadByName succeeds after NotWritablePrimary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 10107 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'DownloadByName succeeds after NotPrimaryNoSecondaryOk' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 13435 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'DownloadByName succeeds after NotPrimaryOrSecondary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 13436 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'DownloadByName succeeds after PrimarySteppedDown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 189 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'DownloadByName succeeds after ShutdownInProgress' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 91 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'DownloadByName succeeds after HostNotFound' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 7 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'DownloadByName succeeds after HostUnreachable' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 6 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'DownloadByName succeeds after NetworkTimeout' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 89 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'DownloadByName succeeds after SocketException' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 9001 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'DownloadByName fails after two NotWritablePrimary errors' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - find + errorCode: 10107 + - &retryable_operation_fails + object: *bucket0 + name: downloadByName + arguments: + filename: abc + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'DownloadByName fails after NotWritablePrimary when retryReads is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - + bucket: + id: &bucket1 bucket1 + database: *database1 + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + errorCode: 10107 + - <<: *retryable_operation_fails + object: *bucket1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/gridfs-downloadByName.json b/test/spec/retryable-reads/unified/gridfs-downloadByName.json new file mode 100644 index 0000000000..c3fa873396 --- /dev/null +++ b/test/spec/retryable-reads/unified/gridfs-downloadByName.json @@ -0,0 +1,347 @@ +{ + "description": "gridfs-downloadByName", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "bucket": { + "id": "bucket0", + "database": "database0" + } + } + ], + "initialData": [ + { + "collectionName": "fs.files", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "length": 1, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "filename": "abc", + "metadata": {} + } + ] + }, + { + "collectionName": "fs.chunks", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000002" + }, + "files_id": { + "$oid": "000000000000000000000001" + }, + "n": 0, + "data": { + "$binary": { + "base64": "EQ==", + "subType": "00" + } + } + } + ] + } + ], + "tests": [ + { + "description": "DownloadByName succeeds on first attempt", + "operations": [ + { + "object": "bucket0", + "name": "downloadByName", + "arguments": { + "filename": "abc" + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "DownloadByName succeeds on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "closeConnection": true + } + } + } + }, + { + "object": "bucket0", + "name": "downloadByName", + "arguments": { + "filename": "abc" + }, + "expectResult": { + "$$matchesHexBytes": "11" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.chunks" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "DownloadByName fails on first attempt", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "bucket": { + "id": "bucket1", + "database": "database1" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "find" + ], + "closeConnection": true + } + } + } + }, + { + "object": "bucket1", + "name": "downloadByName", + "arguments": { + "filename": "abc" + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "DownloadByName fails on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "find" + ], + "closeConnection": true + } + } + } + }, + { + "object": "bucket0", + "name": "downloadByName", + "arguments": { + "filename": "abc" + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "find": "fs.files", + "filter": { + "filename": "abc" + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/gridfs-downloadByName.yml b/test/spec/retryable-reads/unified/gridfs-downloadByName.yml new file mode 100644 index 0000000000..403c4c29c7 --- /dev/null +++ b/test/spec/retryable-reads/unified/gridfs-downloadByName.yml @@ -0,0 +1,180 @@ +description: gridfs-downloadByName + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + bucket: + id: &bucket0 bucket0 + database: *database0 + +initialData: + - + collectionName: &files_collection_name fs.files + databaseName: *database_name + documents: + - + _id: + $oid: '000000000000000000000001' + length: 1 + chunkSize: 4 + uploadDate: + $date: '1970-01-01T00:00:00.000Z' + filename: abc + metadata: { } + - + collectionName: &chunks_collection_name fs.chunks + databaseName: *database_name + documents: + - + _id: + $oid: '000000000000000000000002' + files_id: + $oid: '000000000000000000000001' + 'n': 0 + data: + $binary: + base64: EQ== # hex: 11 + subType: '00' +tests: + - + description: 'DownloadByName succeeds on first attempt' + operations: + - &retryable_operation + object: *bucket0 + name: downloadByName + arguments: + filename: abc + expectResult: + $$matchesHexBytes: "11" + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + find: *files_collection_name + filter: + filename: abc + databaseName: *database_name + - &find_chunks_command_started_event + commandStartedEvent: + command: + find: *chunks_collection_name + # Avoid checking additional fields since the exact query may + # differ among drivers. expectResult is sufficient to assert + # correctness. + databaseName: *database_name + - + description: 'DownloadByName succeeds on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - find + closeConnection: true + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - *find_chunks_command_started_event + - + description: 'DownloadByName fails on first attempt' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - + bucket: + id: &bucket1 bucket1 + database: *database1 + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - &retryable_operation_fails + object: *bucket1 + name: downloadByName + arguments: + filename: abc + expectError: + isError: true + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - + description: 'DownloadByName fails on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - find + closeConnection: true + - <<: *retryable_operation_fails + object: *bucket0 + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/handshakeError.yml b/test/spec/retryable-reads/unified/handshakeError.yml index 90e6947dd1..f2b1ec982c 100644 --- a/test/spec/retryable-reads/unified/handshakeError.yml +++ b/test/spec/retryable-reads/unified/handshakeError.yml @@ -1,6 +1,9 @@ +# Tests in this file are generated from handshakeError.yml.template. + description: "retryable reads handshake failures" -schemaVersion: "1.3" +# 1.4 is required for "serverless: forbid". +schemaVersion: "1.4" runOnRequirements: - minServerVersion: "4.2" @@ -9,16 +12,20 @@ runOnRequirements: createEntities: - client: - id: &client0 client0 + id: &client client useMultipleMongoses: false - observeEvents: [commandStartedEvent, connectionCheckOutStartedEvent] + observeEvents: + - connectionCheckOutStartedEvent + - commandStartedEvent + - commandSucceededEvent + - commandFailedEvent - database: - id: &database0 database0 - client: *client0 - databaseName: &databaseName retryable-handshake-tests + id: &database database + client: *client + databaseName: &databaseName retryable-reads-handshake-tests - collection: - id: &collection0 collection0 - database: *database0 + id: &collection collection + database: *database collectionName: &collectionName coll initialData: @@ -30,100 +37,1306 @@ initialData: - { _id: 3, x: 33 } tests: - - description: "find succeeds after retryable handshake network error" + # Because setting a failPoint creates a connection in the connection pool, run + # a ping operation that fails immediately after the failPoint operation in + # order to discard the connection before running the actual operation to be + # tested. The saslContinue command is used to avoid SDAM errors. + # + # Description of events: + # - Failpoint operation. + # - Creates a connection in the connection pool that must be closed. + # - Ping operation. + # - Triggers failpoint (first time). + # - Closes the connection made by the fail point operation. + # - Test operation. + # - New connection is created. + # - Triggers failpoint (second time). + # - Tests whether operation successfully retries the handshake and succeeds. + + - description: "client.listDatabases succeeds after retryable handshake network error" operations: - - name: failPoint # fail the next connection establishment + - name: failPoint object: testRunner arguments: - client: *client0 + client: *client failPoint: configureFailPoint: failCommand mode: { times: 2 } data: - # use saslContinue here to avoid SDAM errors - # this failPoint itself will create a usable connection in the connection pool - # so we run a ping (that also fails) in order to discard the connection - # before testing our read operation "find" - failCommands: [saslContinue, ping] + failCommands: [ping, saslContinue] closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: listDatabases + object: *client + arguments: + filter: {} + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: listDatabases + - commandSucceededEvent: + commandName: listDatabases + - description: "client.listDatabases succeeds after retryable handshake server error (ShutdownInProgress)" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true - name: runCommand - object: *database0 + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: listDatabases + object: *client arguments: - commandName: ping - command: { ping: 1 } - expectError: - isError: true + filter: {} + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: listDatabases + - commandSucceededEvent: + commandName: listDatabases - - name: find - object: *collection0 + - description: "client.listDatabaseNames succeeds after retryable handshake network error" + operations: + - name: failPoint + object: testRunner arguments: - filter: { _id: 2 } - expectResult: [{ _id: 2, x: 22 }] + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: listDatabaseNames + object: *client + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: listDatabases + - commandSucceededEvent: + commandName: listDatabases + - description: "client.listDatabaseNames succeeds after retryable handshake server error (ShutdownInProgress)" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: listDatabaseNames + object: *client expectEvents: - - client: *client0 + - client: *client eventType: cmap events: - { connectionCheckOutStartedEvent: {} } - { connectionCheckOutStartedEvent: {} } - { connectionCheckOutStartedEvent: {} } - { connectionCheckOutStartedEvent: {} } - - client: *client0 + - client: *client events: - commandStartedEvent: - command: - ping: 1 + command: { ping: 1 } databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: listDatabases + - commandSucceededEvent: + commandName: listDatabases + + - description: "client.createChangeStream succeeds after retryable handshake network error" + runOnRequirements: + - serverless: forbid + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: createChangeStream + object: *client + arguments: + pipeline: [] + saveResultAsEntity: changeStream + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: - commandStartedEvent: - command: - find: *collectionName - filter: { _id: 2 } + command: { ping: 1 } databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: aggregate + - commandSucceededEvent: + commandName: aggregate - - description: "find succeeds after retryable handshake network error (ShutdownInProgress)" + - description: "client.createChangeStream succeeds after retryable handshake server error (ShutdownInProgress)" + runOnRequirements: + - serverless: forbid operations: - - name: failPoint # fail the next connection establishment + - name: failPoint object: testRunner arguments: - client: *client0 + client: *client failPoint: configureFailPoint: failCommand mode: { times: 2 } data: - failCommands: [saslContinue, ping] - errorCode: 91 # ShutdownInProgress + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: createChangeStream + object: *client + arguments: + pipeline: [] + saveResultAsEntity: changeStream + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: aggregate + - commandSucceededEvent: + commandName: aggregate + - description: "database.aggregate succeeds after retryable handshake network error" + runOnRequirements: + - serverless: forbid + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true - name: runCommand - object: *database0 + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: aggregate + object: *database arguments: - commandName: ping - command: { ping: 1 } - expectError: - isError: true + pipeline: [ { $listLocalSessions: {} }, { $limit: 1 } ] + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: aggregate + - commandSucceededEvent: + commandName: aggregate - - name: find - object: *collection0 + - description: "database.aggregate succeeds after retryable handshake server error (ShutdownInProgress)" + runOnRequirements: + - serverless: forbid + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: aggregate + object: *database + arguments: + pipeline: [ { $listLocalSessions: {} }, { $limit: 1 } ] + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: aggregate + - commandSucceededEvent: + commandName: aggregate + + - description: "database.listCollections succeeds after retryable handshake network error" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: listCollections + object: *database + arguments: + filter: {} + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: listCollections + - commandSucceededEvent: + commandName: listCollections + + - description: "database.listCollections succeeds after retryable handshake server error (ShutdownInProgress)" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: listCollections + object: *database + arguments: + filter: {} + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: listCollections + - commandSucceededEvent: + commandName: listCollections + + - description: "database.listCollectionNames succeeds after retryable handshake network error" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: listCollectionNames + object: *database + arguments: + filter: {} + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: listCollections + - commandSucceededEvent: + commandName: listCollections + + - description: "database.listCollectionNames succeeds after retryable handshake server error (ShutdownInProgress)" + operations: + - name: failPoint + object: testRunner arguments: - filter: { _id: 2 } - expectResult: [{ _id: 2, x: 22 }] + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: listCollectionNames + object: *database + arguments: + filter: {} + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: listCollections + - commandSucceededEvent: + commandName: listCollections + - description: "database.createChangeStream succeeds after retryable handshake network error" + runOnRequirements: + - serverless: forbid + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: createChangeStream + object: *database + arguments: + pipeline: [] + saveResultAsEntity: changeStream expectEvents: - - client: *client0 + - client: *client eventType: cmap events: - { connectionCheckOutStartedEvent: {} } - { connectionCheckOutStartedEvent: {} } - { connectionCheckOutStartedEvent: {} } - { connectionCheckOutStartedEvent: {} } - - client: *client0 + - client: *client events: - commandStartedEvent: - command: - ping: 1 + command: { ping: 1 } databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: aggregate + - commandSucceededEvent: + commandName: aggregate + + - description: "database.createChangeStream succeeds after retryable handshake server error (ShutdownInProgress)" + runOnRequirements: + - serverless: forbid + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: createChangeStream + object: *database + arguments: + pipeline: [] + saveResultAsEntity: changeStream + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: - commandStartedEvent: - command: - find: *collectionName - filter: { _id: 2 } + command: { ping: 1 } databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: aggregate + - commandSucceededEvent: + commandName: aggregate + + - description: "collection.aggregate succeeds after retryable handshake network error" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: aggregate + object: *collection + arguments: + pipeline: [] + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: aggregate + - commandSucceededEvent: + commandName: aggregate + + - description: "collection.aggregate succeeds after retryable handshake server error (ShutdownInProgress)" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: aggregate + object: *collection + arguments: + pipeline: [] + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: aggregate + - commandSucceededEvent: + commandName: aggregate + + - description: "collection.countDocuments succeeds after retryable handshake network error" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: countDocuments + object: *collection + arguments: + filter: {} + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: aggregate + - commandSucceededEvent: + commandName: aggregate + + - description: "collection.countDocuments succeeds after retryable handshake server error (ShutdownInProgress)" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: countDocuments + object: *collection + arguments: + filter: {} + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: aggregate + - commandSucceededEvent: + commandName: aggregate + + - description: "collection.estimatedDocumentCount succeeds after retryable handshake network error" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: estimatedDocumentCount + object: *collection + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: count + - commandSucceededEvent: + commandName: count + + - description: "collection.estimatedDocumentCount succeeds after retryable handshake server error (ShutdownInProgress)" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: estimatedDocumentCount + object: *collection + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: count + - commandSucceededEvent: + commandName: count + + - description: "collection.distinct succeeds after retryable handshake network error" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: distinct + object: *collection + arguments: + fieldName: x + filter: {} + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: distinct + - commandSucceededEvent: + commandName: distinct + + - description: "collection.distinct succeeds after retryable handshake server error (ShutdownInProgress)" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: distinct + object: *collection + arguments: + fieldName: x + filter: {} + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: distinct + - commandSucceededEvent: + commandName: distinct + + - description: "collection.find succeeds after retryable handshake network error" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: find + object: *collection + arguments: + filter: {} + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: find + - commandSucceededEvent: + commandName: find + + - description: "collection.find succeeds after retryable handshake server error (ShutdownInProgress)" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: find + object: *collection + arguments: + filter: {} + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: find + - commandSucceededEvent: + commandName: find + + - description: "collection.findOne succeeds after retryable handshake network error" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: findOne + object: *collection + arguments: + filter: {} + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: find + - commandSucceededEvent: + commandName: find + + - description: "collection.findOne succeeds after retryable handshake server error (ShutdownInProgress)" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: findOne + object: *collection + arguments: + filter: {} + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: find + - commandSucceededEvent: + commandName: find + + - description: "collection.listIndexes succeeds after retryable handshake network error" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: listIndexes + object: *collection + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: listIndexes + - commandSucceededEvent: + commandName: listIndexes + + - description: "collection.listIndexes succeeds after retryable handshake server error (ShutdownInProgress)" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: listIndexes + object: *collection + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: listIndexes + - commandSucceededEvent: + commandName: listIndexes + + - description: "collection.listIndexNames succeeds after retryable handshake network error" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: listIndexNames + object: *collection + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: listIndexes + - commandSucceededEvent: + commandName: listIndexes + + - description: "collection.listIndexNames succeeds after retryable handshake server error (ShutdownInProgress)" + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: listIndexNames + object: *collection + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: listIndexes + - commandSucceededEvent: + commandName: listIndexes + + - description: "collection.createChangeStream succeeds after retryable handshake network error" + runOnRequirements: + - serverless: forbid + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: createChangeStream + object: *collection + arguments: + pipeline: [] + saveResultAsEntity: changeStream + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: aggregate + - commandSucceededEvent: + commandName: aggregate + + - description: "collection.createChangeStream succeeds after retryable handshake server error (ShutdownInProgress)" + runOnRequirements: + - serverless: forbid + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: createChangeStream + object: *collection + arguments: + pipeline: [] + saveResultAsEntity: changeStream + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: aggregate + - commandSucceededEvent: + commandName: aggregate diff --git a/test/spec/retryable-reads/unified/listCollectionNames-serverErrors.json b/test/spec/retryable-reads/unified/listCollectionNames-serverErrors.json new file mode 100644 index 0000000000..162dd4cee0 --- /dev/null +++ b/test/spec/retryable-reads/unified/listCollectionNames-serverErrors.json @@ -0,0 +1,710 @@ +{ + "description": "listCollectionNames-serverErrors", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "ListCollectionNames succeeds after InterruptedAtShutdown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 11600 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionNames succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 11602 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionNames succeeds after NotWritablePrimary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionNames succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 13435 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionNames succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 13436 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionNames succeeds after PrimarySteppedDown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 189 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionNames succeeds after ShutdownInProgress", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 91 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionNames succeeds after HostNotFound", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 7 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionNames succeeds after HostUnreachable", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 6 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionNames succeeds after NetworkTimeout", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 89 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionNames succeeds after SocketException", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 9001 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionNames fails after two NotWritablePrimary errors", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionNames", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionNames fails after NotWritablePrimary when retryReads is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "database1", + "name": "listCollectionNames", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/listCollectionNames-serverErrors.yml b/test/spec/retryable-reads/unified/listCollectionNames-serverErrors.yml new file mode 100644 index 0000000000..bba0407d99 --- /dev/null +++ b/test/spec/retryable-reads/unified/listCollectionNames-serverErrors.yml @@ -0,0 +1,360 @@ +description: listCollectionNames-serverErrors + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + +initialData: + - + collectionName: &collection_name coll + databaseName: *database_name + documents: [] + +tests: + - + description: 'ListCollectionNames succeeds after InterruptedAtShutdown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 11600 + - &retryable_operation + object: *database0 + name: listCollectionNames + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + listCollections: 1 + - *retryable_command_started_event + - + description: 'ListCollectionNames succeeds after InterruptedDueToReplStateChange' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 11602 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionNames succeeds after NotWritablePrimary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 10107 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionNames succeeds after NotPrimaryNoSecondaryOk' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 13435 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionNames succeeds after NotPrimaryOrSecondary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 13436 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionNames succeeds after PrimarySteppedDown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 189 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionNames succeeds after ShutdownInProgress' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 91 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionNames succeeds after HostNotFound' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 7 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionNames succeeds after HostUnreachable' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 6 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionNames succeeds after NetworkTimeout' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 89 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionNames succeeds after SocketException' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 9001 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionNames fails after two NotWritablePrimary errors' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - listCollections + errorCode: 10107 + - &retryable_operation_fails + object: *database0 + name: listCollectionNames + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionNames fails after NotWritablePrimary when retryReads is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 10107 + - <<: *retryable_operation_fails + object: *database1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/listCollectionNames.json b/test/spec/retryable-reads/unified/listCollectionNames.json new file mode 100644 index 0000000000..0fe575f7a6 --- /dev/null +++ b/test/spec/retryable-reads/unified/listCollectionNames.json @@ -0,0 +1,243 @@ +{ + "description": "listCollectionNames", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "ListCollectionNames succeeds on first attempt", + "operations": [ + { + "object": "database0", + "name": "listCollectionNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionNames succeeds on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "closeConnection": true + } + } + } + }, + { + "object": "database0", + "name": "listCollectionNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionNames fails on first attempt", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "closeConnection": true + } + } + } + }, + { + "object": "database1", + "name": "listCollectionNames", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionNames fails on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "closeConnection": true + } + } + } + }, + { + "object": "database0", + "name": "listCollectionNames", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/listCollectionNames.yml b/test/spec/retryable-reads/unified/listCollectionNames.yml new file mode 100644 index 0000000000..7522f1d093 --- /dev/null +++ b/test/spec/retryable-reads/unified/listCollectionNames.yml @@ -0,0 +1,132 @@ +description: listCollectionNames + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + +initialData: + - + collectionName: &collection_name coll + databaseName: *database_name + documents: [] + +tests: + - + description: 'ListCollectionNames succeeds on first attempt' + operations: + - &retryable_operation + object: *database0 + name: listCollectionNames + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + listCollections: 1 + - + description: 'ListCollectionNames succeeds on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + closeConnection: true + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionNames fails on first attempt' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - &retryable_operation_fails + object: *database1 + name: listCollectionNames + expectError: + isError: true + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - + description: 'ListCollectionNames fails on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - listCollections + closeConnection: true + - <<: *retryable_operation_fails + object: *database0 + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/listCollectionObjects-serverErrors.json b/test/spec/retryable-reads/unified/listCollectionObjects-serverErrors.json new file mode 100644 index 0000000000..8b9d582c10 --- /dev/null +++ b/test/spec/retryable-reads/unified/listCollectionObjects-serverErrors.json @@ -0,0 +1,710 @@ +{ + "description": "listCollectionObjects-serverErrors", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "ListCollectionObjects succeeds after InterruptedAtShutdown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 11600 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionObjects succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 11602 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionObjects succeeds after NotWritablePrimary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionObjects succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 13435 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionObjects succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 13436 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionObjects succeeds after PrimarySteppedDown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 189 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionObjects succeeds after ShutdownInProgress", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 91 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionObjects succeeds after HostNotFound", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 7 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionObjects succeeds after HostUnreachable", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 6 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionObjects succeeds after NetworkTimeout", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 89 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionObjects succeeds after SocketException", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 9001 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionObjects fails after two NotWritablePrimary errors", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "database0", + "name": "listCollectionObjects", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionObjects fails after NotWritablePrimary when retryReads is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "database1", + "name": "listCollectionObjects", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/listCollectionObjects-serverErrors.yml b/test/spec/retryable-reads/unified/listCollectionObjects-serverErrors.yml new file mode 100644 index 0000000000..758c6165de --- /dev/null +++ b/test/spec/retryable-reads/unified/listCollectionObjects-serverErrors.yml @@ -0,0 +1,364 @@ +# listCollectionObjects returns an array of MongoCollection objects. +# Not all drivers support this functionality. For more details, see: +# https://github.com/mongodb/specifications/blob/v1/source/enumerate-collections.rst#returning-a-list-of-collection-objects + +description: listCollectionObjects-serverErrors + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + +initialData: + - + collectionName: &collection_name coll + databaseName: *database_name + documents: [] + +tests: + - + description: 'ListCollectionObjects succeeds after InterruptedAtShutdown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 11600 + - &retryable_operation + object: *database0 + name: listCollectionObjects + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + listCollections: 1 + - *retryable_command_started_event + - + description: 'ListCollectionObjects succeeds after InterruptedDueToReplStateChange' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 11602 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionObjects succeeds after NotWritablePrimary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 10107 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionObjects succeeds after NotPrimaryNoSecondaryOk' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 13435 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionObjects succeeds after NotPrimaryOrSecondary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 13436 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionObjects succeeds after PrimarySteppedDown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 189 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionObjects succeeds after ShutdownInProgress' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 91 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionObjects succeeds after HostNotFound' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 7 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionObjects succeeds after HostUnreachable' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 6 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionObjects succeeds after NetworkTimeout' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 89 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionObjects succeeds after SocketException' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 9001 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionObjects fails after two NotWritablePrimary errors' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - listCollections + errorCode: 10107 + - &retryable_operation_fails + object: *database0 + name: listCollectionObjects + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionObjects fails after NotWritablePrimary when retryReads is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 10107 + - <<: *retryable_operation_fails + object: *database1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/listCollectionObjects.json b/test/spec/retryable-reads/unified/listCollectionObjects.json new file mode 100644 index 0000000000..9cdbb69276 --- /dev/null +++ b/test/spec/retryable-reads/unified/listCollectionObjects.json @@ -0,0 +1,243 @@ +{ + "description": "listCollectionObjects", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "ListCollectionObjects succeeds on first attempt", + "operations": [ + { + "object": "database0", + "name": "listCollectionObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionObjects succeeds on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "closeConnection": true + } + } + } + }, + { + "object": "database0", + "name": "listCollectionObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionObjects fails on first attempt", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "closeConnection": true + } + } + } + }, + { + "object": "database1", + "name": "listCollectionObjects", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollectionObjects fails on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "closeConnection": true + } + } + } + }, + { + "object": "database0", + "name": "listCollectionObjects", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/listCollectionObjects.yml b/test/spec/retryable-reads/unified/listCollectionObjects.yml new file mode 100644 index 0000000000..93da6bd85e --- /dev/null +++ b/test/spec/retryable-reads/unified/listCollectionObjects.yml @@ -0,0 +1,136 @@ +# listCollectionObjects returns an array of MongoCollection objects. +# Not all drivers support this functionality. For more details, see: +# https://github.com/mongodb/specifications/blob/v1/source/enumerate-collections.rst#returning-a-list-of-collection-objects + +description: listCollectionObjects + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + +initialData: + - + collectionName: &collection_name coll + databaseName: *database_name + documents: [] + +tests: + - + description: 'ListCollectionObjects succeeds on first attempt' + operations: + - &retryable_operation + object: *database0 + name: listCollectionObjects + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + listCollections: 1 + - + description: 'ListCollectionObjects succeeds on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + closeConnection: true + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollectionObjects fails on first attempt' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - &retryable_operation_fails + object: *database1 + name: listCollectionObjects + expectError: + isError: true + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - + description: 'ListCollectionObjects fails on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - listCollections + closeConnection: true + - <<: *retryable_operation_fails + object: *database0 + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event \ No newline at end of file diff --git a/test/spec/retryable-reads/unified/listCollections-serverErrors.json b/test/spec/retryable-reads/unified/listCollections-serverErrors.json new file mode 100644 index 0000000000..171fe7457f --- /dev/null +++ b/test/spec/retryable-reads/unified/listCollections-serverErrors.json @@ -0,0 +1,710 @@ +{ + "description": "listCollections-serverErrors", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "ListCollections succeeds after InterruptedAtShutdown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 11600 + } + } + } + }, + { + "object": "database0", + "name": "listCollections" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollections succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 11602 + } + } + } + }, + { + "object": "database0", + "name": "listCollections" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollections succeeds after NotWritablePrimary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "database0", + "name": "listCollections" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollections succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 13435 + } + } + } + }, + { + "object": "database0", + "name": "listCollections" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollections succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 13436 + } + } + } + }, + { + "object": "database0", + "name": "listCollections" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollections succeeds after PrimarySteppedDown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 189 + } + } + } + }, + { + "object": "database0", + "name": "listCollections" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollections succeeds after ShutdownInProgress", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 91 + } + } + } + }, + { + "object": "database0", + "name": "listCollections" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollections succeeds after HostNotFound", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 7 + } + } + } + }, + { + "object": "database0", + "name": "listCollections" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollections succeeds after HostUnreachable", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 6 + } + } + } + }, + { + "object": "database0", + "name": "listCollections" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollections succeeds after NetworkTimeout", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 89 + } + } + } + }, + { + "object": "database0", + "name": "listCollections" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollections succeeds after SocketException", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 9001 + } + } + } + }, + { + "object": "database0", + "name": "listCollections" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollections fails after two NotWritablePrimary errors", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "database0", + "name": "listCollections", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollections fails after NotWritablePrimary when retryReads is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "database1", + "name": "listCollections", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/listCollections-serverErrors.yml b/test/spec/retryable-reads/unified/listCollections-serverErrors.yml new file mode 100644 index 0000000000..12fb42f02a --- /dev/null +++ b/test/spec/retryable-reads/unified/listCollections-serverErrors.yml @@ -0,0 +1,360 @@ +description: listCollections-serverErrors + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + +initialData: + - + collectionName: &collection_name coll + databaseName: *database_name + documents: [] + +tests: + - + description: 'ListCollections succeeds after InterruptedAtShutdown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 11600 + - &retryable_operation + object: *database0 + name: listCollections + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + listCollections: 1 + - *retryable_command_started_event + - + description: 'ListCollections succeeds after InterruptedDueToReplStateChange' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 11602 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollections succeeds after NotWritablePrimary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 10107 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollections succeeds after NotPrimaryNoSecondaryOk' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 13435 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollections succeeds after NotPrimaryOrSecondary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 13436 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollections succeeds after PrimarySteppedDown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 189 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollections succeeds after ShutdownInProgress' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 91 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollections succeeds after HostNotFound' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 7 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollections succeeds after HostUnreachable' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 6 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollections succeeds after NetworkTimeout' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 89 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollections succeeds after SocketException' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 9001 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollections fails after two NotWritablePrimary errors' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - listCollections + errorCode: 10107 + - &retryable_operation_fails + object: *database0 + name: listCollections + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollections fails after NotWritablePrimary when retryReads is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + errorCode: 10107 + - <<: *retryable_operation_fails + object: *database1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/listCollections.json b/test/spec/retryable-reads/unified/listCollections.json new file mode 100644 index 0000000000..b6152f9ce5 --- /dev/null +++ b/test/spec/retryable-reads/unified/listCollections.json @@ -0,0 +1,243 @@ +{ + "description": "listCollections", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "ListCollections succeeds on first attempt", + "operations": [ + { + "object": "database0", + "name": "listCollections" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollections succeeds on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "closeConnection": true + } + } + } + }, + { + "object": "database0", + "name": "listCollections" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollections fails on first attempt", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "closeConnection": true + } + } + } + }, + { + "object": "database1", + "name": "listCollections", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListCollections fails on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "listCollections" + ], + "closeConnection": true + } + } + } + }, + { + "object": "database0", + "name": "listCollections", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listCollections": 1 + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/listCollections.yml b/test/spec/retryable-reads/unified/listCollections.yml new file mode 100644 index 0000000000..1dcfe1ef48 --- /dev/null +++ b/test/spec/retryable-reads/unified/listCollections.yml @@ -0,0 +1,132 @@ +description: listCollections + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + +initialData: + - + collectionName: &collection_name coll + databaseName: *database_name + documents: [] + +tests: + - + description: 'ListCollections succeeds on first attempt' + operations: + - &retryable_operation + object: *database0 + name: listCollections + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + listCollections: 1 + - + description: 'ListCollections succeeds on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listCollections + closeConnection: true + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListCollections fails on first attempt' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - &retryable_operation_fails + object: *database1 + name: listCollections + expectError: + isError: true + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - + description: 'ListCollections fails on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - listCollections + closeConnection: true + - <<: *retryable_operation_fails + object: *database0 + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/listDatabaseNames-serverErrors.json b/test/spec/retryable-reads/unified/listDatabaseNames-serverErrors.json new file mode 100644 index 0000000000..489ff0ad51 --- /dev/null +++ b/test/spec/retryable-reads/unified/listDatabaseNames-serverErrors.json @@ -0,0 +1,696 @@ +{ + "description": "listDatabaseNames-serverErrors", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "ListDatabaseNames succeeds after InterruptedAtShutdown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 11600 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseNames succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 11602 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseNames succeeds after NotWritablePrimary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseNames succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 13435 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseNames succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 13436 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseNames succeeds after PrimarySteppedDown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 189 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseNames succeeds after ShutdownInProgress", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 91 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseNames succeeds after HostNotFound", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 7 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseNames succeeds after HostUnreachable", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 6 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseNames succeeds after NetworkTimeout", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 89 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseNames succeeds after SocketException", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 9001 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseNames fails after two NotWritablePrimary errors", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseNames", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseNames fails after NotWritablePrimary when retryReads is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "client1", + "name": "listDatabaseNames", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/listDatabaseNames-serverErrors.yml b/test/spec/retryable-reads/unified/listDatabaseNames-serverErrors.yml new file mode 100644 index 0000000000..36db2a1907 --- /dev/null +++ b/test/spec/retryable-reads/unified/listDatabaseNames-serverErrors.yml @@ -0,0 +1,351 @@ +description: listDatabaseNames-serverErrors + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + +initialData: + - + collectionName: &collection_name coll + databaseName: &database_name retryable-reads-tests + documents: [] + +tests: + - + description: 'ListDatabaseNames succeeds after InterruptedAtShutdown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 11600 + - &retryable_operation + object: *client0 + name: listDatabaseNames + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + listDatabases: 1 + - *retryable_command_started_event + - + description: 'ListDatabaseNames succeeds after InterruptedDueToReplStateChange' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 11602 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseNames succeeds after NotWritablePrimary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 10107 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseNames succeeds after NotPrimaryNoSecondaryOk' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 13435 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseNames succeeds after NotPrimaryOrSecondary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 13436 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseNames succeeds after PrimarySteppedDown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 189 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseNames succeeds after ShutdownInProgress' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 91 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseNames succeeds after HostNotFound' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 7 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseNames succeeds after HostUnreachable' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 6 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseNames succeeds after NetworkTimeout' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 89 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseNames succeeds after SocketException' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 9001 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseNames fails after two NotWritablePrimary errors' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - listDatabases + errorCode: 10107 + - &retryable_operation_fails + object: *client0 + name: listDatabaseNames + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseNames fails after NotWritablePrimary when retryReads is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 10107 + - <<: *retryable_operation_fails + object: *client1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/listDatabaseNames.json b/test/spec/retryable-reads/unified/listDatabaseNames.json new file mode 100644 index 0000000000..5590f39a51 --- /dev/null +++ b/test/spec/retryable-reads/unified/listDatabaseNames.json @@ -0,0 +1,229 @@ +{ + "description": "listDatabaseNames", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "ListDatabaseNames succeeds on first attempt", + "operations": [ + { + "object": "client0", + "name": "listDatabaseNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseNames succeeds on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "closeConnection": true + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseNames fails on first attempt", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "closeConnection": true + } + } + } + }, + { + "object": "client1", + "name": "listDatabaseNames", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseNames fails on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "closeConnection": true + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseNames", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/listDatabaseNames.yml b/test/spec/retryable-reads/unified/listDatabaseNames.yml new file mode 100644 index 0000000000..d80e7d6ebf --- /dev/null +++ b/test/spec/retryable-reads/unified/listDatabaseNames.yml @@ -0,0 +1,123 @@ +description: listDatabaseNames + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + +initialData: + - + collectionName: &collection_name coll + databaseName: &database_name retryable-reads-tests + documents: [] + +tests: + - + description: 'ListDatabaseNames succeeds on first attempt' + operations: + - &retryable_operation + object: *client0 + name: listDatabaseNames + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + listDatabases: 1 + - + description: 'ListDatabaseNames succeeds on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + closeConnection: true + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseNames fails on first attempt' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - &retryable_operation_fails + object: *client1 + name: listDatabaseNames + expectError: + isError: true + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - + description: 'ListDatabaseNames fails on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - listDatabases + closeConnection: true + - <<: *retryable_operation_fails + object: *client0 + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/listDatabaseObjects-serverErrors.json b/test/spec/retryable-reads/unified/listDatabaseObjects-serverErrors.json new file mode 100644 index 0000000000..56f9f36236 --- /dev/null +++ b/test/spec/retryable-reads/unified/listDatabaseObjects-serverErrors.json @@ -0,0 +1,696 @@ +{ + "description": "listDatabaseObjects-serverErrors", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "ListDatabaseObjects succeeds after InterruptedAtShutdown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 11600 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseObjects succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 11602 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseObjects succeeds after NotWritablePrimary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseObjects succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 13435 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseObjects succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 13436 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseObjects succeeds after PrimarySteppedDown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 189 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseObjects succeeds after ShutdownInProgress", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 91 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseObjects succeeds after HostNotFound", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 7 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseObjects succeeds after HostUnreachable", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 6 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseObjects succeeds after NetworkTimeout", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 89 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseObjects succeeds after SocketException", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 9001 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseObjects fails after two NotWritablePrimary errors", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseObjects", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseObjects fails after NotWritablePrimary when retryReads is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "client1", + "name": "listDatabaseObjects", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/listDatabaseObjects-serverErrors.yml b/test/spec/retryable-reads/unified/listDatabaseObjects-serverErrors.yml new file mode 100644 index 0000000000..06815e1e8b --- /dev/null +++ b/test/spec/retryable-reads/unified/listDatabaseObjects-serverErrors.yml @@ -0,0 +1,355 @@ +# listDatabaseObjects returns an array of MongoDatabase objects. +# Not all drivers support this functionality. For more details, see: +# https://github.com/mongodb/specifications/blob/v1/source/enumerate-databases.rst#enumerating-mongodatabase-objects + +description: listDatabaseObjects-serverErrors + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + +initialData: + - + collectionName: &collection_name coll + databaseName: &database_name retryable-reads-tests + documents: [] + +tests: + - + description: 'ListDatabaseObjects succeeds after InterruptedAtShutdown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 11600 + - &retryable_operation + object: *client0 + name: listDatabaseObjects + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + listDatabases: 1 + - *retryable_command_started_event + - + description: 'ListDatabaseObjects succeeds after InterruptedDueToReplStateChange' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 11602 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseObjects succeeds after NotWritablePrimary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 10107 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseObjects succeeds after NotPrimaryNoSecondaryOk' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 13435 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseObjects succeeds after NotPrimaryOrSecondary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 13436 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseObjects succeeds after PrimarySteppedDown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 189 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseObjects succeeds after ShutdownInProgress' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 91 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseObjects succeeds after HostNotFound' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 7 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseObjects succeeds after HostUnreachable' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 6 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseObjects succeeds after NetworkTimeout' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 89 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseObjects succeeds after SocketException' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 9001 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseObjects fails after two NotWritablePrimary errors' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - listDatabases + errorCode: 10107 + - &retryable_operation_fails + object: *client0 + name: listDatabaseObjects + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseObjects fails after NotWritablePrimary when retryReads is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 10107 + - <<: *retryable_operation_fails + object: *client1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/listDatabaseObjects.json b/test/spec/retryable-reads/unified/listDatabaseObjects.json new file mode 100644 index 0000000000..46b1511d46 --- /dev/null +++ b/test/spec/retryable-reads/unified/listDatabaseObjects.json @@ -0,0 +1,229 @@ +{ + "description": "listDatabaseObjects", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "ListDatabaseObjects succeeds on first attempt", + "operations": [ + { + "object": "client0", + "name": "listDatabaseObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseObjects succeeds on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "closeConnection": true + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseObjects" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseObjects fails on first attempt", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "closeConnection": true + } + } + } + }, + { + "object": "client1", + "name": "listDatabaseObjects", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabaseObjects fails on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "closeConnection": true + } + } + } + }, + { + "object": "client0", + "name": "listDatabaseObjects", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/listDatabaseObjects.yml b/test/spec/retryable-reads/unified/listDatabaseObjects.yml new file mode 100644 index 0000000000..3c94b6cca5 --- /dev/null +++ b/test/spec/retryable-reads/unified/listDatabaseObjects.yml @@ -0,0 +1,127 @@ +# listDatabaseObjects returns an array of MongoDatabase objects. +# Not all drivers support this functionality. For more details, see: +# https://github.com/mongodb/specifications/blob/v1/source/enumerate-databases.rst#enumerating-mongodatabase-objects + +description: listDatabaseObjects + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + +initialData: + - + collectionName: &collection_name coll + databaseName: &database_name retryable-reads-tests + documents: [] + +tests: + - + description: 'ListDatabaseObjects succeeds on first attempt' + operations: + - &retryable_operation + object: *client0 + name: listDatabaseObjects + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + listDatabases: 1 + - + description: 'ListDatabaseObjects succeeds on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + closeConnection: true + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabaseObjects fails on first attempt' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - &retryable_operation_fails + object: *client1 + name: listDatabaseObjects + expectError: + isError: true + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - + description: 'ListDatabaseObjects fails on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - listDatabases + closeConnection: true + - <<: *retryable_operation_fails + object: *client0 + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event \ No newline at end of file diff --git a/test/spec/retryable-reads/unified/listDatabases-serverErrors.json b/test/spec/retryable-reads/unified/listDatabases-serverErrors.json new file mode 100644 index 0000000000..09b935a59f --- /dev/null +++ b/test/spec/retryable-reads/unified/listDatabases-serverErrors.json @@ -0,0 +1,696 @@ +{ + "description": "listDatabases-serverErrors", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "ListDatabases succeeds after InterruptedAtShutdown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 11600 + } + } + } + }, + { + "object": "client0", + "name": "listDatabases" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabases succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 11602 + } + } + } + }, + { + "object": "client0", + "name": "listDatabases" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabases succeeds after NotWritablePrimary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "client0", + "name": "listDatabases" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabases succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 13435 + } + } + } + }, + { + "object": "client0", + "name": "listDatabases" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabases succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 13436 + } + } + } + }, + { + "object": "client0", + "name": "listDatabases" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabases succeeds after PrimarySteppedDown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 189 + } + } + } + }, + { + "object": "client0", + "name": "listDatabases" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabases succeeds after ShutdownInProgress", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 91 + } + } + } + }, + { + "object": "client0", + "name": "listDatabases" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabases succeeds after HostNotFound", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 7 + } + } + } + }, + { + "object": "client0", + "name": "listDatabases" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabases succeeds after HostUnreachable", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 6 + } + } + } + }, + { + "object": "client0", + "name": "listDatabases" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabases succeeds after NetworkTimeout", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 89 + } + } + } + }, + { + "object": "client0", + "name": "listDatabases" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabases succeeds after SocketException", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 9001 + } + } + } + }, + { + "object": "client0", + "name": "listDatabases" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabases fails after two NotWritablePrimary errors", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "client0", + "name": "listDatabases", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabases fails after NotWritablePrimary when retryReads is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "client1", + "name": "listDatabases", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/listDatabases-serverErrors.yml b/test/spec/retryable-reads/unified/listDatabases-serverErrors.yml new file mode 100644 index 0000000000..1a236bde39 --- /dev/null +++ b/test/spec/retryable-reads/unified/listDatabases-serverErrors.yml @@ -0,0 +1,351 @@ +description: listDatabases-serverErrors + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + +initialData: + - + collectionName: &collection_name coll + databaseName: &database_name retryable-reads-tests + documents: [] + +tests: + - + description: 'ListDatabases succeeds after InterruptedAtShutdown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 11600 + - &retryable_operation + object: *client0 + name: listDatabases + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + listDatabases: 1 + - *retryable_command_started_event + - + description: 'ListDatabases succeeds after InterruptedDueToReplStateChange' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 11602 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabases succeeds after NotWritablePrimary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 10107 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabases succeeds after NotPrimaryNoSecondaryOk' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 13435 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabases succeeds after NotPrimaryOrSecondary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 13436 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabases succeeds after PrimarySteppedDown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 189 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabases succeeds after ShutdownInProgress' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 91 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabases succeeds after HostNotFound' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 7 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabases succeeds after HostUnreachable' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 6 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabases succeeds after NetworkTimeout' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 89 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabases succeeds after SocketException' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 9001 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabases fails after two NotWritablePrimary errors' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - listDatabases + errorCode: 10107 + - &retryable_operation_fails + object: *client0 + name: listDatabases + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabases fails after NotWritablePrimary when retryReads is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + errorCode: 10107 + - <<: *retryable_operation_fails + object: *client1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/listDatabases.json b/test/spec/retryable-reads/unified/listDatabases.json new file mode 100644 index 0000000000..4cf5eccc7b --- /dev/null +++ b/test/spec/retryable-reads/unified/listDatabases.json @@ -0,0 +1,229 @@ +{ + "description": "listDatabases", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "ListDatabases succeeds on first attempt", + "operations": [ + { + "object": "client0", + "name": "listDatabases" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabases succeeds on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "closeConnection": true + } + } + } + }, + { + "object": "client0", + "name": "listDatabases" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabases fails on first attempt", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "closeConnection": true + } + } + } + }, + { + "object": "client1", + "name": "listDatabases", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + }, + { + "description": "ListDatabases fails on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "listDatabases" + ], + "closeConnection": true + } + } + } + }, + { + "object": "client0", + "name": "listDatabases", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + }, + { + "commandStartedEvent": { + "command": { + "listDatabases": 1 + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/listDatabases.yml b/test/spec/retryable-reads/unified/listDatabases.yml new file mode 100644 index 0000000000..743e4a4830 --- /dev/null +++ b/test/spec/retryable-reads/unified/listDatabases.yml @@ -0,0 +1,123 @@ +description: listDatabases + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + +initialData: + - + collectionName: &collection_name coll + databaseName: &database_name retryable-reads-tests + documents: [] + +tests: + - + description: 'ListDatabases succeeds on first attempt' + operations: + - &retryable_operation + object: *client0 + name: listDatabases + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + listDatabases: 1 + - + description: 'ListDatabases succeeds on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listDatabases + closeConnection: true + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListDatabases fails on first attempt' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - &retryable_operation_fails + object: *client1 + name: listDatabases + expectError: + isError: true + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - + description: 'ListDatabases fails on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - listDatabases + closeConnection: true + - <<: *retryable_operation_fails + object: *client0 + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event \ No newline at end of file diff --git a/test/spec/retryable-reads/unified/listIndexNames-serverErrors.json b/test/spec/retryable-reads/unified/listIndexNames-serverErrors.json new file mode 100644 index 0000000000..7b98111480 --- /dev/null +++ b/test/spec/retryable-reads/unified/listIndexNames-serverErrors.json @@ -0,0 +1,749 @@ +{ + "description": "listIndexNames-serverErrors", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "ListIndexNames succeeds after InterruptedAtShutdown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 11600 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexNames succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 11602 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexNames succeeds after NotWritablePrimary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexNames succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 13435 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexNames succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 13436 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexNames succeeds after PrimarySteppedDown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 189 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexNames succeeds after ShutdownInProgress", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 91 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexNames succeeds after HostNotFound", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 7 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexNames succeeds after HostUnreachable", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 6 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexNames succeeds after NetworkTimeout", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 89 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexNames succeeds after SocketException", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 9001 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexNames fails after two NotWritablePrimary errors", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexNames", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexNames fails after NotWritablePrimary when retryReads is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection1", + "name": "listIndexNames", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/listIndexNames-serverErrors.yml b/test/spec/retryable-reads/unified/listIndexNames-serverErrors.yml new file mode 100644 index 0000000000..aa217bbdcc --- /dev/null +++ b/test/spec/retryable-reads/unified/listIndexNames-serverErrors.yml @@ -0,0 +1,370 @@ +description: listIndexNames-serverErrors + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: [] + +tests: + - + description: 'ListIndexNames succeeds after InterruptedAtShutdown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 11600 + - &retryable_operation + object: *collection0 + name: listIndexNames + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + listIndexes: *collection_name + databaseName: *database_name + - *retryable_command_started_event + - + description: 'ListIndexNames succeeds after InterruptedDueToReplStateChange' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 11602 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexNames succeeds after NotWritablePrimary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 10107 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexNames succeeds after NotPrimaryNoSecondaryOk' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 13435 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexNames succeeds after NotPrimaryOrSecondary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 13436 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexNames succeeds after PrimarySteppedDown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 189 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexNames succeeds after ShutdownInProgress' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 91 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexNames succeeds after HostNotFound' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 7 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexNames succeeds after HostUnreachable' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 6 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexNames succeeds after NetworkTimeout' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 89 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexNames succeeds after SocketException' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 9001 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexNames fails after two NotWritablePrimary errors' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - listIndexes + errorCode: 10107 + - &retryable_operation_fails + object: *collection0 + name: listIndexNames + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexNames fails after NotWritablePrimary when retryReads is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 10107 + - <<: *retryable_operation_fails + object: *collection1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/listIndexNames.json b/test/spec/retryable-reads/unified/listIndexNames.json new file mode 100644 index 0000000000..c5fe967ff5 --- /dev/null +++ b/test/spec/retryable-reads/unified/listIndexNames.json @@ -0,0 +1,263 @@ +{ + "description": "listIndexNames", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "ListIndexNames succeeds on first attempt", + "operations": [ + { + "object": "collection0", + "name": "listIndexNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexNames succeeds on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "listIndexNames" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexNames fails on first attempt", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection1", + "name": "listIndexNames", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexNames fails on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "listIndexNames", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/listIndexNames.yml b/test/spec/retryable-reads/unified/listIndexNames.yml new file mode 100644 index 0000000000..f18c223c49 --- /dev/null +++ b/test/spec/retryable-reads/unified/listIndexNames.yml @@ -0,0 +1,142 @@ +description: listIndexNames + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: [] + +tests: + - + description: 'ListIndexNames succeeds on first attempt' + operations: + - &retryable_operation + object: *collection0 + name: listIndexNames + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + listIndexes: *collection_name + databaseName: *database_name + - + description: 'ListIndexNames succeeds on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + closeConnection: true + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexNames fails on first attempt' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - &retryable_operation_fails + object: *collection1 + name: listIndexNames + expectError: + isError: true + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - + description: 'ListIndexNames fails on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - listIndexes + closeConnection: true + - <<: *retryable_operation_fails + object: *collection0 + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/listIndexes-serverErrors.json b/test/spec/retryable-reads/unified/listIndexes-serverErrors.json new file mode 100644 index 0000000000..0110a0acd0 --- /dev/null +++ b/test/spec/retryable-reads/unified/listIndexes-serverErrors.json @@ -0,0 +1,749 @@ +{ + "description": "listIndexes-serverErrors", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "ListIndexes succeeds after InterruptedAtShutdown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 11600 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexes" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexes succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 11602 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexes" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexes succeeds after NotWritablePrimary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexes" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexes succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 13435 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexes" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexes succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 13436 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexes" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexes succeeds after PrimarySteppedDown", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 189 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexes" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexes succeeds after ShutdownInProgress", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 91 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexes" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexes succeeds after HostNotFound", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 7 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexes" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexes succeeds after HostUnreachable", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 6 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexes" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexes succeeds after NetworkTimeout", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 89 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexes" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexes succeeds after SocketException", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 9001 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexes" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexes fails after two NotWritablePrimary errors", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection0", + "name": "listIndexes", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexes fails after NotWritablePrimary when retryReads is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "errorCode": 10107 + } + } + } + }, + { + "object": "collection1", + "name": "listIndexes", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/listIndexes-serverErrors.yml b/test/spec/retryable-reads/unified/listIndexes-serverErrors.yml new file mode 100644 index 0000000000..964def3d10 --- /dev/null +++ b/test/spec/retryable-reads/unified/listIndexes-serverErrors.yml @@ -0,0 +1,370 @@ +description: listIndexes-serverErrors + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: [] + +tests: + - + description: 'ListIndexes succeeds after InterruptedAtShutdown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 11600 + - &retryable_operation + object: *collection0 + name: listIndexes + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + listIndexes: *collection_name + databaseName: *database_name + - *retryable_command_started_event + - + description: 'ListIndexes succeeds after InterruptedDueToReplStateChange' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 11602 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexes succeeds after NotWritablePrimary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 10107 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexes succeeds after NotPrimaryNoSecondaryOk' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 13435 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexes succeeds after NotPrimaryOrSecondary' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 13436 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexes succeeds after PrimarySteppedDown' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 189 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexes succeeds after ShutdownInProgress' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 91 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexes succeeds after HostNotFound' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 7 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexes succeeds after HostUnreachable' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 6 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexes succeeds after NetworkTimeout' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 89 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexes succeeds after SocketException' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 9001 + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexes fails after two NotWritablePrimary errors' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - listIndexes + errorCode: 10107 + - &retryable_operation_fails + object: *collection0 + name: listIndexes + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexes fails after NotWritablePrimary when retryReads is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + errorCode: 10107 + - <<: *retryable_operation_fails + object: *collection1 + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event diff --git a/test/spec/retryable-reads/unified/listIndexes.json b/test/spec/retryable-reads/unified/listIndexes.json new file mode 100644 index 0000000000..2560e4961c --- /dev/null +++ b/test/spec/retryable-reads/unified/listIndexes.json @@ -0,0 +1,263 @@ +{ + "description": "listIndexes", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "ListIndexes succeeds on first attempt", + "operations": [ + { + "object": "collection0", + "name": "listIndexes" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexes succeeds on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "listIndexes" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexes fails on first attempt", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection1", + "name": "listIndexes", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "ListIndexes fails on second attempt", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "listIndexes" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "listIndexes", + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "listIndexes": "coll" + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/listIndexes.yml b/test/spec/retryable-reads/unified/listIndexes.yml new file mode 100644 index 0000000000..9f3932a938 --- /dev/null +++ b/test/spec/retryable-reads/unified/listIndexes.yml @@ -0,0 +1,142 @@ +description: listIndexes + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: [] + +tests: + - + description: 'ListIndexes succeeds on first attempt' + operations: + - &retryable_operation + object: *collection0 + name: listIndexes + expectEvents: + - + client: *client0 + events: + - &retryable_command_started_event + commandStartedEvent: + command: + listIndexes: *collection_name + databaseName: *database_name + - + description: 'ListIndexes succeeds on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - listIndexes + closeConnection: true + - *retryable_operation + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event + - + description: 'ListIndexes fails on first attempt' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - &retryable_operation_fails + object: *collection1 + name: listIndexes + expectError: + isError: true + expectEvents: + - + client: *client1 + events: + - *retryable_command_started_event + - + description: 'ListIndexes fails on second attempt' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: + - listIndexes + closeConnection: true + - <<: *retryable_operation_fails + object: *collection0 + expectEvents: + - + client: *client0 + events: + - *retryable_command_started_event + - *retryable_command_started_event \ No newline at end of file diff --git a/test/spec/retryable-reads/unified/mapReduce.json b/test/spec/retryable-reads/unified/mapReduce.json new file mode 100644 index 0000000000..745c0ef001 --- /dev/null +++ b/test/spec/retryable-reads/unified/mapReduce.json @@ -0,0 +1,284 @@ +{ + "description": "mapReduce", + "schemaVersion": "1.9", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "single", + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "serverless": "forbid", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-reads-tests", + "documents": [ + { + "_id": 1, + "x": 0 + }, + { + "_id": 2, + "x": 1 + }, + { + "_id": 3, + "x": 2 + } + ] + } + ], + "tests": [ + { + "description": "MapReduce succeeds with retry on", + "operations": [ + { + "object": "collection0", + "name": "mapReduce", + "arguments": { + "map": { + "$code": "function inc() { return emit(0, this.x + 1) }" + }, + "reduce": { + "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" + }, + "out": { + "inline": 1 + } + }, + "expectResult": [ + { + "_id": 0, + "value": 6 + } + ] + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "mapReduce": "coll", + "map": { + "$code": "function inc() { return emit(0, this.x + 1) }" + }, + "reduce": { + "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" + }, + "out": { + "inline": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "MapReduce fails with retry on", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "mapReduce" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "mapReduce", + "arguments": { + "map": { + "$code": "function inc() { return emit(0, this.x + 1) }" + }, + "reduce": { + "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" + }, + "out": { + "inline": 1 + } + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "mapReduce": "coll", + "map": { + "$code": "function inc() { return emit(0, this.x + 1) }" + }, + "reduce": { + "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" + }, + "out": { + "inline": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + }, + { + "description": "MapReduce fails with retry off", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryReads": false + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-reads-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "mapReduce" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection1", + "name": "mapReduce", + "arguments": { + "map": { + "$code": "function inc() { return emit(0, this.x + 1) }" + }, + "reduce": { + "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" + }, + "out": { + "inline": 1 + } + }, + "expectError": { + "isError": true + } + } + ], + "expectEvents": [ + { + "client": "client1", + "events": [ + { + "commandStartedEvent": { + "command": { + "mapReduce": "coll", + "map": { + "$code": "function inc() { return emit(0, this.x + 1) }" + }, + "reduce": { + "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" + }, + "out": { + "inline": 1 + } + }, + "databaseName": "retryable-reads-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-reads/unified/mapReduce.yml b/test/spec/retryable-reads/unified/mapReduce.yml new file mode 100644 index 0000000000..10e88e9168 --- /dev/null +++ b/test/spec/retryable-reads/unified/mapReduce.yml @@ -0,0 +1,153 @@ +description: mapReduce + +schemaVersion: '1.9' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: + - single + - replicaset + - + minServerVersion: 4.1.7 + # serverless proxy does not support mapReduce operation + serverless: forbid + topologies: + - sharded + - load-balanced + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: + - commandStartedEvent + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-reads-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - + _id: 1 + x: 0 + - + _id: 2 + x: 1 + - + _id: 3 + x: 2 + +tests: + - + description: 'MapReduce succeeds with retry on' + operations: + - &operation_succeeds + object: *collection0 + name: mapReduce + arguments: + map: + $code: 'function inc() { return emit(0, this.x + 1) }' + reduce: + $code: 'function sum(key, values) { return values.reduce((acc, x) => acc + x); }' + out: + inline: 1 + expectResult: + - + _id: 0 + value: 6 + expectEvents: + - + client: *client0 + events: + - &command_started_event + commandStartedEvent: + command: + mapReduce: *collection_name + map: + $code: 'function inc() { return emit(0, this.x + 1) }' + reduce: + $code: 'function sum(key, values) { return values.reduce((acc, x) => acc + x); }' + out: + inline: 1 + databaseName: *database_name + - + description: 'MapReduce fails with retry on' + operations: + - + object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: &failCommand_failPoint + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: + - mapReduce + closeConnection: true + - &operation_fails + object: *collection0 + name: mapReduce + arguments: + map: + $code: 'function inc() { return emit(0, this.x + 1) }' + reduce: + $code: 'function sum(key, values) { return values.reduce((acc, x) => acc + x); }' + out: + inline: 1 + expectError: + isError: true + expectEvents: + - + client: *client0 + events: + - *command_started_event + - + description: 'MapReduce fails with retry off' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryReads: false + observeEvents: + - commandStartedEvent + - database: + id: &database1 database1 + client: *client1 + databaseName: *database_name + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collection_name + - + object: testRunner + name: failPoint + arguments: + client: *client1 + failPoint: *failCommand_failPoint + - <<: *operation_fails + object: *collection1 + expectEvents: + - + client: *client1 + events: + - *command_started_event diff --git a/test/spec/retryable-writes/README.md b/test/spec/retryable-writes/README.md new file mode 100644 index 0000000000..e883ca368d --- /dev/null +++ b/test/spec/retryable-writes/README.md @@ -0,0 +1,341 @@ +# Retryable Write Tests + +## Introduction + +The YAML and JSON files in this directory are platform-independent tests meant to exercise a driver's implementation of +retryable writes. These tests utilize the [Unified Test Format](../../unified-test-format/unified-test-format.md). + +Several prose tests, which are not easily expressed in YAML, are also presented in this file. Those tests will need to +be manually implemented by each driver. + +Tests will require a MongoClient created with options defined in the tests. Integration tests will require a running +MongoDB cluster with server versions 3.6.0 or later. The `{setFeatureCompatibilityVersion: 3.6}` admin command will also +need to have been executed to enable support for retryable writes on the cluster. Some tests may have more stringent +version requirements depending on the fail points used. + +## Use as Integration Tests + +Integration tests are expressed in YAML and can be run against a replica set or sharded cluster as denoted by the +top-level `runOn` field. Tests that rely on the `onPrimaryTransactionalWrite` fail point cannot be run against a sharded +cluster because the fail point is not supported by mongos. + +The tests exercise the following scenarios: + +- Single-statement write operations + - Each test expecting a write result will encounter at-most one network error for the write command. Retry attempts + should return without error and allow operation to succeed. Observation of the collection state will assert that the + write occurred at-most once. + - Each test expecting an error will encounter successive network errors for the write command. Observation of the + collection state will assert that the write was never committed on the server. +- Multi-statement write operations + - Each test expecting a write result will encounter at-most one network error for some write command(s) in the batch. + Retry attempts should return without error and allow the batch to ultimately succeed. Observation of the collection + state will assert that each write occurred at-most once. + - Each test expecting an error will encounter successive network errors for some write command in the batch. The batch + will ultimately fail with an error, but observation of the collection state will assert that the failing write was + never committed on the server. We may observe that earlier writes in the batch occurred at-most once. + +We cannot test a scenario where the first and second attempts both encounter network errors but the write does actually +commit during one of those attempts. This is because (1) the fail point only triggers when a write would be committed +and (2) the skip and times options are mutually exclusive. That said, such a test would mainly assert the server's +correctness for at-most once semantics and is not essential to assert driver correctness. + +## Split Batch Tests + +The YAML tests specify bulk write operations that are split by command type (e.g. sequence of insert, update, and delete +commands). Multi-statement write operations may also be split due to `maxWriteBatchSize`, `maxBsonObjectSize`, or +`maxMessageSizeBytes`. + +For instance, an insertMany operation with five 10 MiB documents executed using OP_MSG payload type 0 (i.e. entire +command in one document) would be split into five insert commands in order to respect the 16 MiB `maxBsonObjectSize` +limit. The same insertMany operation executed using OP_MSG payload type 1 (i.e. command arguments pulled out into a +separate payload vector) would be split into two insert commands in order to respect the 48 MB `maxMessageSizeBytes` +limit. + +Noting when a driver might split operations, the `onPrimaryTransactionalWrite` fail point's `skip` option may be used to +control when the fail point first triggers. Once triggered, the fail point will transition to the `alwaysOn` state until +disabled. Driver authors should also note that the server attempts to process all documents in a single insert command +within a single commit (i.e. one insert command with five documents may only trigger the fail point once). This behavior +is unique to insert commands (each statement in an update and delete command is processed independently). + +If testing an insert that is split into two commands, a `skip` of one will allow the fail point to trigger on the second +insert command (because all documents in the first command will be processed in the same commit). When testing an update +or delete that is split into two commands, the `skip` should be set to the number of statements in the first command to +allow the fail point to trigger on the second command. + +## Command Construction Tests + +Drivers should also assert that command documents are properly constructed with or without a transaction ID, depending +on whether the write operation is supported. +[Command Logging and Monitoring](../../command-logging-and-monitoring/command-logging-and-monitoring.rst) may be used to +check for the presence of a `txnNumber` field in the command document. Note that command documents may always include an +`lsid` field per the [Driver Session](../../sessions/driver-sessions.md) specification. + +These tests may be run against both a replica set and shard cluster. + +Drivers should test that transaction IDs are never included in commands for unsupported write operations: + +- Write commands with unacknowledged write concerns (e.g. `{w: 0}`) +- Unsupported single-statement write operations + - `updateMany()` + - `deleteMany()` +- Unsupported multi-statement write operations + - `bulkWrite()` that includes `UpdateMany` or `DeleteMany` +- Unsupported write commands + - `aggregate` with write stage (e.g. `$out`, `$merge`) + +Drivers should test that transactions IDs are always included in commands for supported write operations: + +- Supported single-statement write operations + - `insertOne()` + - `updateOne()` + - `replaceOne()` + - `deleteOne()` + - `findOneAndDelete()` + - `findOneAndReplace()` + - `findOneAndUpdate()` +- Supported multi-statement write operations + - `insertMany()` with `ordered=true` + - `insertMany()` with `ordered=false` + - `bulkWrite()` with `ordered=true` (no `UpdateMany` or `DeleteMany`) + - `bulkWrite()` with `ordered=false` (no `UpdateMany` or `DeleteMany`) + +## Prose Tests + +The following tests ensure that retryable writes work properly with replica sets and sharded clusters. + +### 1. Test that retryable writes raise an exception when using the MMAPv1 storage engine. + +For this test, execute a write operation, such as `insertOne`, which should generate an exception. Assert that the error +message is the replacement error message: + +``` +This MongoDB deployment does not support retryable writes. Please add +retryWrites=false to your connection string. +``` + +and the error code is 20. + +> [!NOTE] +> Drivers that rely on `serverStatus` to determine the storage engine in use MAY skip this test for sharded clusters, +> since `mongos` does not report this information in its `serverStatus` response. + +### 2. Test that drivers properly retry after encountering PoolClearedErrors. + +This test MUST be implemented by any driver that implements the CMAP specification. + +This test requires MongoDB 4.3.4+ for both the `errorLabels` and `blockConnection` fail point options. + +1. Create a client with maxPoolSize=1 and retryWrites=true. If testing against a sharded deployment, be sure to connect + to only a single mongos. + +2. Enable the following failpoint: + + ```javascript + { + configureFailPoint: "failCommand", + mode: { times: 1 }, + data: { + failCommands: ["insert"], + errorCode: 91, + blockConnection: true, + blockTimeMS: 1000, + errorLabels: ["RetryableWriteError"] + } + } + ``` + +3. Start two threads and attempt to perform an `insertOne` simultaneously on both. + +4. Verify that both `insertOne` attempts succeed. + +5. Via CMAP monitoring, assert that the first check out succeeds. + +6. Via CMAP monitoring, assert that a PoolClearedEvent is then emitted. + +7. Via CMAP monitoring, assert that the second check out then fails due to a connection error. + +8. Via Command Monitoring, assert that exactly three `insert` CommandStartedEvents were observed in total. + +9. Disable the failpoint. + +### 3. Test that drivers return the original error after encountering a WriteConcernError with a RetryableWriteError label. + +This test MUST: + +- be implemented by any driver that implements the Command Monitoring specification, +- only run against replica sets as mongos does not propagate the NoWritesPerformed label to the drivers. +- be run against server versions 6.0 and above. + +Additionally, this test requires drivers to set a fail point after an `insertOne` operation but before the subsequent +retry. Drivers that are unable to set a failCommand after the CommandSucceededEvent SHOULD use mocking or write a unit +test to cover the same sequence of events. + +1. Create a client with `retryWrites=true`. + +2. Configure a fail point with error code `91` (ShutdownInProgress): + + ```javascript + { + configureFailPoint: "failCommand", + mode: {times: 1}, + data: { + failCommands: ["insert"], + errorLabels: ["RetryableWriteError"], + writeConcernError: { code: 91 } + } + } + ``` + +3. Via the command monitoring CommandSucceededEvent, configure a fail point with error code `10107` (NotWritablePrimary) + and a NoWritesPerformed label: + + ```javascript + { + configureFailPoint: "failCommand", + mode: {times: 1}, + data: { + failCommands: ["insert"], + errorCode: 10107, + errorLabels: ["RetryableWriteError", "NoWritesPerformed"] + } + } + ``` + + Drivers SHOULD only configure the `10107` fail point command if the the succeeded event is for the `91` error + configured in step 2. + +4. Attempt an `insertOne` operation on any record for any database and collection. For the resulting error, assert that + the associated error code is `91`. + +5. Disable the fail point: + + ```javascript + { + configureFailPoint: "failCommand", + mode: "off" + } + ``` + +### 4. Test that in a sharded cluster writes are retried on a different mongos when one is available. + +This test MUST be executed against a sharded cluster that has at least two mongos instances, supports +`retryWrites=true`, has enabled the `configureFailPoint` command, and supports the `errorLabels` field (MongoDB 4.3.1+). + +> [!NOTE] +> This test cannot reliably distinguish "retry on a different mongos due to server deprioritization" (the behavior +> intended to be tested) from "retry on a different mongos due to normal SDAM randomized suitable server selection". +> Verify relevant code paths are correctly executed by the tests using external means such as a logging, debugger, code +> coverage tool, etc. + +1. Create two clients `s0` and `s1` that each connect to a single mongos from the sharded cluster. They must not connect + to the same mongos. + +2. Configure the following fail point for both `s0` and `s1`: + + ```javascript + { + configureFailPoint: "failCommand", + mode: { times: 1 }, + data: { + failCommands: ["insert"], + errorCode: 6, + errorLabels: ["RetryableWriteError"] + } + } + ``` + +3. Create a client `client` with `retryWrites=true` that connects to the cluster using the same two mongoses as `s0` and + `s1`. + +4. Enable failed command event monitoring for `client`. + +5. Execute an `insert` command with `client`. Assert that the command failed. + +6. Assert that two failed command events occurred. Assert that the failed command events occurred on different mongoses. + +7. Disable the fail points on both `s0` and `s1`. + +### 5. Test that in a sharded cluster writes are retried on the same mongos when no others are available. + +This test MUST be executed against a sharded cluster that supports `retryWrites=true`, has enabled the +`configureFailPoint` command, and supports the `errorLabels` field (MongoDB 4.3.1+). + +Note: this test cannot reliably distinguish "retry on a different mongos due to server deprioritization" (the behavior +intended to be tested) from "retry on a different mongos due to normal SDAM behavior of randomized suitable server +selection". Verify relevant code paths are correctly executed by the tests using external means such as a logging, +debugger, code coverage tool, etc. + +1. Create a client `s0` that connects to a single mongos from the cluster. + +2. Configure the following fail point for `s0`: + + ```javascript + { + configureFailPoint: "failCommand", + mode: { times: 1 }, + data: { + failCommands: ["insert"], + errorCode: 6, + errorLabels: ["RetryableWriteError"], + closeConnection: true + } + } + ``` + +3. Create a client `client` with `directConnection=false` (when not set by default) and `retryWrites=true` that connects + to the cluster using the same single mongos as `s0`. + +4. Enable succeeded and failed command event monitoring for `client`. + +5. Execute an `insert` command with `client`. Assert that the command succeeded. + +6. Assert that exactly one failed command event and one succeeded command event occurred. Assert that both events + occurred on the same mongos. + +7. Disable the fail point on `s0`. + +## Changelog + +- 2024-05-30: Migrated from reStructuredText to Markdown. + +- 2024-02-27: Convert legacy retryable writes tests to unified format. + +- 2024-02-21: Update prose test 4 and 5 to workaround SDAM behavior preventing\ + execution of deprioritization code + paths. + +- 2024-01-05: Fix typo in prose test title. + +- 2024-01-03: Note server version requirements for fail point options and revise\ + tests to specify the `errorLabels` + option at the top-level instead of within `writeConcernError`. + +- 2023-08-26: Add prose tests for retrying in a sharded cluster. + +- 2022-08-30: Add prose test verifying correct error handling for errors with\ + the NoWritesPerformed label, which is to + return the original error. + +- 2022-04-22: Clarifications to `serverless` and `useMultipleMongoses`. + +- 2021-08-27: Add `serverless` to `runOn`. Clarify behavior of\ + `useMultipleMongoses` for `LoadBalanced` topologies. + +- 2021-04-23: Add `load-balanced` to test topology requirements. + +- 2021-03-24: Add prose test verifying `PoolClearedErrors` are retried. + +- 2019-10-21: Add `errorLabelsContain` and `errorLabelsContain` fields to\ + `result` + +- 2019-08-07: Add Prose Tests section + +- 2019-06-07: Mention $merge stage for aggregate alongside $out + +- 2019-03-01: Add top-level `runOn` field to denote server version and/or\ + topology requirements requirements for the + test file. Removes the `minServerVersion` and `maxServerVersion` top-level fields, which are now expressed within + `runOn` elements. + + Add test-level `useMultipleMongoses` field. diff --git a/test/spec/retryable-writes/README.rst b/test/spec/retryable-writes/README.rst deleted file mode 100644 index 5ddfb6a2d0..0000000000 --- a/test/spec/retryable-writes/README.rst +++ /dev/null @@ -1,487 +0,0 @@ -===================== -Retryable Write Tests -===================== - -.. contents:: - ----- - -Introduction -============ - -Tests in this directory are platform-independent tests that drivers can use to -prove their conformance to the Retryable Writes specification. - -Tests in the ``unified`` directory are implemented in the -`Unified Test Format <../../unified-test-format/unified-test-format.rst>`__. - -Tests in the ``legacy`` directory should be executed as described below. - -Several prose tests, which are not easily expressed in YAML, are also presented -in this file. Those tests will need to be manually implemented by each driver. - -Tests will require a MongoClient created with options defined in the tests. -Integration tests will require a running MongoDB cluster with server versions -3.6.0 or later. The ``{setFeatureCompatibilityVersion: 3.6}`` admin command -will also need to have been executed to enable support for retryable writes on -the cluster. Some tests may have more stringent version requirements depending -on the fail points used. - -Server Fail Point -================= - -onPrimaryTransactionalWrite ---------------------------- - -Some tests depend on a server fail point, ``onPrimaryTransactionalWrite``, which -allows us to force a network error before the server would return a write result -to the client. The fail point also allows control whether the server will -successfully commit the write via its ``failBeforeCommitExceptionCode`` option. -Keep in mind that the fail point only triggers for transaction writes (i.e. write -commands including ``txnNumber`` and ``lsid`` fields). See `SERVER-29606`_ for -more information. - -.. _SERVER-29606: https://jira.mongodb.org/browse/SERVER-29606 - -The fail point may be configured like so:: - - db.runCommand({ - configureFailPoint: "onPrimaryTransactionalWrite", - mode: , - data: - }); - -``mode`` is a generic fail point option and may be assigned a string or document -value. The string values ``"alwaysOn"`` and ``"off"`` may be used to enable or -disable the fail point, respectively. A document may be used to specify either -``times`` or ``skip``, which are mutually exclusive: - -- ``{ times: }`` may be used to limit the number of times the fail - point may trigger before transitioning to ``"off"``. -- ``{ skip: }`` may be used to defer the first trigger of a fail - point, after which it will transition to ``"alwaysOn"``. - -The ``data`` option is a document that may be used to specify options that -control the fail point's behavior. As noted in `SERVER-29606`_, -``onPrimaryTransactionalWrite`` supports the following ``data`` options, which -may be combined if desired: - -- ``closeConnection``: Boolean option, which defaults to ``true``. If ``true``, - the connection on which the write is executed will be closed before a result - can be returned. -- ``failBeforeCommitExceptionCode``: Integer option, which is unset by default. - If set, the specified exception code will be thrown and the write will not be - committed. If unset, the write will be allowed to commit. - -failCommand ------------ - -Some tests depend on a server fail point, ``failCommand``, which allows the -client to force the server to return an error. Unlike -``onPrimaryTransactionalWrite``, ``failCommand`` does not allow the client to -directly control whether the server will commit the operation (execution of the -write depends on whether the ``closeConnection`` and/or ``errorCode`` options -are specified). See: `failCommand <../../transactions/tests#failcommand>`_ in -the Transactions spec test suite for more information. - -Disabling Fail Points after Test Execution ------------------------------------------- - -After each test that configures a fail point, drivers should disable the fail -point to avoid spurious failures in subsequent tests. The fail point may be -disabled like so:: - - db.runCommand({ - configureFailPoint: , - mode: "off" - }); - -Speeding Up Tests -================= - -See `Speeding Up Tests <../../retryable-reads/tests/README.rst#speeding-up-tests>`_ in the retryable reads spec tests. - -Use as Integration Tests -======================== - -Integration tests are expressed in YAML and can be run against a replica set or -sharded cluster as denoted by the top-level ``runOn`` field. Tests that rely on -the ``onPrimaryTransactionalWrite`` fail point cannot be run against a sharded -cluster because the fail point is not supported by mongos. - -The tests exercise the following scenarios: - -- Single-statement write operations - - - Each test expecting a write result will encounter at-most one network error - for the write command. Retry attempts should return without error and allow - operation to succeed. Observation of the collection state will assert that - the write occurred at-most once. - - - Each test expecting an error will encounter successive network errors for - the write command. Observation of the collection state will assert that the - write was never committed on the server. - -- Multi-statement write operations - - - Each test expecting a write result will encounter at-most one network error - for some write command(s) in the batch. Retry attempts should return without - error and allow the batch to ultimately succeed. Observation of the - collection state will assert that each write occurred at-most once. - - - Each test expecting an error will encounter successive network errors for - some write command in the batch. The batch will ultimately fail with an - error, but observation of the collection state will assert that the failing - write was never committed on the server. We may observe that earlier writes - in the batch occurred at-most once. - -We cannot test a scenario where the first and second attempts both encounter -network errors but the write does actually commit during one of those attempts. -This is because (1) the fail point only triggers when a write would be committed -and (2) the skip and times options are mutually exclusive. That said, such a -test would mainly assert the server's correctness for at-most once semantics and -is not essential to assert driver correctness. - -Test Format ------------ - -Each YAML file has the following keys: - -- ``runOn`` (optional): An array of server version and/or topology requirements - for which the tests can be run. If the test environment satisfies one or more - of these requirements, the tests may be executed; otherwise, this file should - be skipped. If this field is omitted, the tests can be assumed to have no - particular requirements and should be executed. Each element will have some or - all of the following fields: - - - ``minServerVersion`` (optional): The minimum server version (inclusive) - required to successfully run the tests. If this field is omitted, it should - be assumed that there is no lower bound on the required server version. - - - ``maxServerVersion`` (optional): The maximum server version (inclusive) - against which the tests can be run successfully. If this field is omitted, - it should be assumed that there is no upper bound on the required server - version. - - - ``topology`` (optional): An array of server topologies against which the - tests can be run successfully. Valid topologies are "single", - "replicaset", "sharded", and "load-balanced". If this field is omitted, - the default is all topologies (i.e. ``["single", "replicaset", "sharded", - "load-balanced"]``). - - - ``serverless``: (optional): Whether or not the test should be run on Atlas - Serverless instances. Valid values are "require", "forbid", and "allow". If - "require", the test MUST only be run on Atlas Serverless instances. If - "forbid", the test MUST NOT be run on Atlas Serverless instances. If omitted - or "allow", this option has no effect. - - The test runner MUST be informed whether or not Atlas Serverless is being - used in order to determine if this requirement is met (e.g. through an - environment variable or configuration option). - - Note: the Atlas Serverless proxy imitates mongos, so the test runner is not - capable of determining if Atlas Serverless is in use by issuing commands - such as ``buildInfo`` or ``hello``. Furthermore, connections to Atlas - Serverless use a load balancer, so the topology will appear as - "load-balanced". - -- ``data``: The data that should exist in the collection under test before each - test run. - -- ``tests``: An array of tests that are to be run independently of each other. - Each test will have some or all of the following fields: - - - ``description``: The name of the test. - - - ``clientOptions``: Parameters to pass to MongoClient(). - - - ``useMultipleMongoses`` (optional): If ``true``, and the topology type is - ``Sharded``, the MongoClient for this test should be initialized with multiple - mongos seed addresses. If ``false`` or omitted, only a single mongos address - should be specified. - - If ``true``, the topology type is ``LoadBalanced``, and Atlas Serverless is - not being used, the MongoClient for this test should be initialized with the - URI of the load balancer fronting multiple servers. If ``false`` or omitted, - the MongoClient for this test should be initialized with the URI of the load - balancer fronting a single server. - - ``useMultipleMongoses`` only affects ``Sharded`` and ``LoadBalanced`` - topologies (excluding Atlas Serverless). - - - ``failPoint`` (optional): The ``configureFailPoint`` command document to run - to configure a fail point on the primary server. Drivers must ensure that - ``configureFailPoint`` is the first field in the command. This option and - ``useMultipleMongoses: true`` are mutually exclusive. - - - ``operation``: Document describing the operation to be executed. The - operation should be executed through a collection object derived from a - client that has been created with ``clientOptions``. The operation will have - some or all of the following fields: - - - ``name``: The name of the operation as defined in the CRUD specification. - - - ``arguments``: The names and values of arguments from the CRUD - specification. - - - ``outcome``: Document describing the return value and/or expected state of - the collection after the operation is executed. This will have some or all - of the following fields: - - - ``error``: If ``true``, the test should expect an error or exception. Note - that some drivers may report server-side errors as a write error within a - write result object. - - - ``result``: The return value from the operation. This will correspond to - an operation's result object as defined in the CRUD specification. This - field may be omitted if ``error`` is ``true``. If this field is present - and ``error`` is ``true`` (generally for multi-statement tests), the - result reports information about operations that succeeded before an - unrecoverable failure. In that case, drivers may choose to check the - result object if their BulkWriteException (or equivalent) provides access - to a write result object. - - - ``errorLabelsContain``: A list of error label strings that the - error is expected to have. - - - ``errorLabelsOmit``: A list of error label strings that the - error is expected not to have. - - - ``collection``: - - - ``name`` (optional): The name of the collection to verify. If this isn't - present then use the collection under test. - - - ``data``: The data that should exist in the collection after the - operation has been run. - -Split Batch Tests -================= - -The YAML tests specify bulk write operations that are split by command type -(e.g. sequence of insert, update, and delete commands). Multi-statement write -operations may also be split due to ``maxWriteBatchSize``, -``maxBsonObjectSize``, or ``maxMessageSizeBytes``. - -For instance, an insertMany operation with five 10 MiB documents executed using -OP_MSG payload type 0 (i.e. entire command in one document) would be split into -five insert commands in order to respect the 16 MiB ``maxBsonObjectSize`` limit. -The same insertMany operation executed using OP_MSG payload type 1 (i.e. command -arguments pulled out into a separate payload vector) would be split into two -insert commands in order to respect the 48 MB ``maxMessageSizeBytes`` limit. - -Noting when a driver might split operations, the ``onPrimaryTransactionalWrite`` -fail point's ``skip`` option may be used to control when the fail point first -triggers. Once triggered, the fail point will transition to the ``alwaysOn`` -state until disabled. Driver authors should also note that the server attempts -to process all documents in a single insert command within a single commit (i.e. -one insert command with five documents may only trigger the fail point once). -This behavior is unique to insert commands (each statement in an update and -delete command is processed independently). - -If testing an insert that is split into two commands, a ``skip`` of one will -allow the fail point to trigger on the second insert command (because all -documents in the first command will be processed in the same commit). When -testing an update or delete that is split into two commands, the ``skip`` should -be set to the number of statements in the first command to allow the fail point -to trigger on the second command. - -Command Construction Tests -========================== - -Drivers should also assert that command documents are properly constructed with -or without a transaction ID, depending on whether the write operation is -supported. `Command Logging and Monitoring`_ may be used to check for the presence of a -``txnNumber`` field in the command document. Note that command documents may -always include an ``lsid`` field per the `Driver Session`_ specification. - -.. _Command Logging and Monitoring: ../../command-logging-and-monitoring/command-logging-and-monitoring.rst -.. _Driver Session: ../../sessions/driver-sessions.rst - -These tests may be run against both a replica set and shard cluster. - -Drivers should test that transaction IDs are never included in commands for -unsupported write operations: - -* Write commands with unacknowledged write concerns (e.g. ``{w: 0}``) - -* Unsupported single-statement write operations - - - ``updateMany()`` - - ``deleteMany()`` - -* Unsupported multi-statement write operations - - - ``bulkWrite()`` that includes ``UpdateMany`` or ``DeleteMany`` - -* Unsupported write commands - - - ``aggregate`` with write stage (e.g. ``$out``, ``$merge``) - -Drivers should test that transactions IDs are always included in commands for -supported write operations: - -* Supported single-statement write operations - - - ``insertOne()`` - - ``updateOne()`` - - ``replaceOne()`` - - ``deleteOne()`` - - ``findOneAndDelete()`` - - ``findOneAndReplace()`` - - ``findOneAndUpdate()`` - -* Supported multi-statement write operations - - - ``insertMany()`` with ``ordered=true`` - - ``insertMany()`` with ``ordered=false`` - - ``bulkWrite()`` with ``ordered=true`` (no ``UpdateMany`` or ``DeleteMany``) - - ``bulkWrite()`` with ``ordered=false`` (no ``UpdateMany`` or ``DeleteMany``) - -Prose Tests -=========== - -The following tests ensure that retryable writes work properly with replica sets -and sharded clusters. - -#. Test that retryable writes raise an exception when using the MMAPv1 storage - engine. For this test, execute a write operation, such as ``insertOne``, - which should generate an exception. Assert that the error message is the - replacement error message:: - - This MongoDB deployment does not support retryable writes. Please add - retryWrites=false to your connection string. - - and the error code is 20. - - **Note**: Drivers that rely on ``serverStatus`` to determine the storage engine - in use MAY skip this test for sharded clusters, since ``mongos`` does not report - this information in its ``serverStatus`` response. - -#. Test that drivers properly retry after encountering PoolClearedErrors. This - test MUST be implemented by any driver that implements the CMAP - specification. This test requires MongoDB 4.2.9+ for ``blockConnection`` support in the failpoint. - - 1. Create a client with maxPoolSize=1 and retryWrites=true. If testing - against a sharded deployment, be sure to connect to only a single mongos. - - 2. Enable the following failpoint:: - - { - configureFailPoint: "failCommand", - mode: { times: 1 }, - data: { - failCommands: ["insert"], - errorCode: 91, - blockConnection: true, - blockTimeMS: 1000, - errorLabels: ["RetryableWriteError"] - } - } - - 3. Start two threads and attempt to perform an ``insertOne`` simultaneously on both. - - 4. Verify that both ``insertOne`` attempts succeed. - - 5. Via CMAP monitoring, assert that the first check out succeeds. - - 6. Via CMAP monitoring, assert that a PoolClearedEvent is then emitted. - - 7. Via CMAP monitoring, assert that the second check out then fails due to a - connection error. - - 8. Via Command Monitoring, assert that exactly three ``insert`` - CommandStartedEvents were observed in total. - - 9. Disable the failpoint. - -#. Test that drivers return the original error after encountering a - WriteConcernError with a RetryableWriteError label. This test MUST - - 1. be implemented by any driver that implements the Command Monitoring - specification, - - 2. only run against replica sets as mongos does not propagate the - NoWritesPerformed label to the drivers. - - 3. be run against server versions 6.0 and above. - - Additionally, this test requires drivers to set a fail point after an - ``insertOne`` operation but before the subsequent retry. Drivers that are - unable to set a failCommand after the CommandSucceededEvent SHOULD use - mocking or write a unit test to cover the same sequence of events. - - - 1. Create a client with ``retryWrites=true``. - - 2. Configure a fail point with error code ``91`` (ShutdownInProgress):: - - db.adminCommand({ - configureFailPoint: "failCommand", - mode: {times: 1}, - data: { - writeConcernError: { - code: 91, - errorLabels: ["RetryableWriteError"], - }, - failCommands: ["insert"], - }, - }); - - 3. Via the command monitoring CommandSucceededEvent, configure a fail point - with error code ``10107`` (NotWritablePrimary) and a NoWritesPerformed - label:: - - db.adminCommand({ - configureFailPoint: "failCommand", - mode: {times: 1}, - data: { - errorCode: 10107, - errorLabels: ["RetryableWriteError", "NoWritesPerformed"], - failCommands: ["insert"], - }, - }); - - Drivers SHOULD only configure the ``10107`` fail point command if the the - succeeded event is for the ``91`` error configured in step 2. - - 4. Attempt an ``insertOne`` operation on any record for any database and - collection. For the resulting error, assert that the associated error code - is ``91``. - - 5. Disable the fail point:: - - db.adminCommand({ - configureFailPoint: "failCommand", - mode: "off", - }) - -Changelog -========= - -:2022-08-30: Add prose test verifying correct error handling for errors with - the NoWritesPerformed label, which is to return the original - error. - -:2022-04-22: Clarifications to ``serverless`` and ``useMultipleMongoses``. - -:2021-08-27: Add ``serverless`` to ``runOn``. Clarify behavior of - ``useMultipleMongoses`` for ``LoadBalanced`` topologies. - -:2021-04-23: Add ``load-balanced`` to test topology requirements. - -:2021-03-24: Add prose test verifying ``PoolClearedErrors`` are retried. - -:2019-10-21: Add ``errorLabelsContain`` and ``errorLabelsContain`` fields to - ``result`` - -:2019-08-07: Add Prose Tests section - -:2019-06-07: Mention $merge stage for aggregate alongside $out - -:2019-03-01: Add top-level ``runOn`` field to denote server version and/or - topology requirements requirements for the test file. Removes the - ``minServerVersion`` and ``maxServerVersion`` top-level fields, - which are now expressed within ``runOn`` elements. - - Add test-level ``useMultipleMongoses`` field. diff --git a/test/spec/retryable-writes/legacy/bulkWrite-errorLabels.json b/test/spec/retryable-writes/legacy/bulkWrite-errorLabels.json deleted file mode 100644 index 66c3ecb336..0000000000 --- a/test/spec/retryable-writes/legacy/bulkWrite-errorLabels.json +++ /dev/null @@ -1,183 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.3.1", - "topology": [ - "replicaset", - "sharded", - "load-balanced" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "BulkWrite succeeds with RetryableWriteError from server", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "update" - ], - "errorCode": 112, - "errorLabels": [ - "RetryableWriteError" - ] - } - }, - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 1 - } - } - }, - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 2 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "deletedCount": 1, - "insertedCount": 1, - "insertedIds": { - "1": 3 - }, - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [ - { - "_id": 2, - "x": 23 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "BulkWrite fails if server does not return RetryableWriteError", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "update" - ], - "errorCode": 11600, - "errorLabels": [] - } - }, - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 1 - } - } - }, - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 2 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsOmit": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/bulkWrite-errorLabels.yml b/test/spec/retryable-writes/legacy/bulkWrite-errorLabels.yml deleted file mode 100644 index fb9d7e47e0..0000000000 --- a/test/spec/retryable-writes/legacy/bulkWrite-errorLabels.yml +++ /dev/null @@ -1,77 +0,0 @@ -runOn: - - minServerVersion: "4.3.1" - topology: ["replicaset", "sharded", "load-balanced"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - description: "BulkWrite succeeds with RetryableWriteError from server" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["update"] - errorCode: 112 # WriteConflict, not a retryable error code - errorLabels: ["RetryableWriteError"] # Override server behavior: send RetryableWriteError label with non-retryable error code - operation: - name: "bulkWrite" - arguments: - requests: - - name: "deleteOne" - arguments: - filter: { _id: 1 } - - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - - name: "updateOne" - arguments: - filter: { _id: 2 } - update: { $inc: { x: 1 } } - options: { ordered: true } - outcome: # Driver retries operation and it succeeds - result: - deletedCount: 1 - insertedCount: 1 - insertedIds: { 1: 3 } - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - upsertedIds: {} - collection: - data: - - { _id: 2, x: 23 } - - { _id: 3, x: 33 } - - - description: "BulkWrite fails if server does not return RetryableWriteError" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["update"] - errorCode: 11600 # InterruptedAtShutdown, normally a retryable error code - errorLabels: [] # Override server behavior: do not send RetryableWriteError label with retryable code - operation: - name: "bulkWrite" - arguments: - requests: - - name: "deleteOne" - arguments: - filter: { _id: 1 } - - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - - name: "updateOne" - arguments: - filter: { _id: 2 } - update: { $inc: { x: 1 } } - options: { ordered: true } - outcome: - error: true # Driver does not retry operation because there was no RetryableWriteError label on response - result: - errorLabelsOmit: ["RetryableWriteError"] - collection: - data: - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } diff --git a/test/spec/retryable-writes/legacy/bulkWrite-serverErrors.json b/test/spec/retryable-writes/legacy/bulkWrite-serverErrors.json deleted file mode 100644 index 1e6cc74c05..0000000000 --- a/test/spec/retryable-writes/legacy/bulkWrite-serverErrors.json +++ /dev/null @@ -1,273 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "BulkWrite succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "update" - ], - "errorCode": 189, - "errorLabels": [ - "RetryableWriteError" - ] - } - }, - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 1 - } - } - }, - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 2 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "deletedCount": 1, - "insertedCount": 1, - "insertedIds": { - "1": 3 - }, - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [ - { - "_id": 2, - "x": 23 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "BulkWrite succeeds after WriteConcernError ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorLabels": [ - "RetryableWriteError" - ], - "writeConcernError": { - "code": 91, - "errmsg": "Replication is being shut down" - } - } - }, - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 1 - } - } - }, - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 2 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "deletedCount": 1, - "insertedCount": 1, - "insertedIds": { - "1": 3 - }, - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [ - { - "_id": 2, - "x": 23 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "BulkWrite fails with a RetryableWriteError label after two connection failures", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "update" - ], - "closeConnection": true - } - }, - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 1 - } - } - }, - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 2 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsContain": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/bulkWrite-serverErrors.yml b/test/spec/retryable-writes/legacy/bulkWrite-serverErrors.yml deleted file mode 100644 index 6ca6540f61..0000000000 --- a/test/spec/retryable-writes/legacy/bulkWrite-serverErrors.yml +++ /dev/null @@ -1,130 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "BulkWrite succeeds after PrimarySteppedDown" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["update"] - errorCode: 189 - errorLabels: ["RetryableWriteError"] - operation: - name: "bulkWrite" - arguments: - requests: - - - name: "deleteOne" - arguments: - filter: { _id: 1 } - - - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - - - name: "updateOne" - arguments: - filter: { _id: 2 } - update: { $inc: { x : 1 }} - options: { ordered: true } - outcome: - result: - deletedCount: 1 - insertedCount: 1 - insertedIds: { 1: 3 } - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - upsertedIds: { } - collection: - data: - - { _id: 2, x: 23 } - - { _id: 3, x: 33 } - - - description: "BulkWrite succeeds after WriteConcernError ShutdownInProgress" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorLabels: ["RetryableWriteError"] - writeConcernError: - code: 91 - errmsg: Replication is being shut down - operation: - name: "bulkWrite" - arguments: - requests: - - - name: "deleteOne" - arguments: - filter: { _id: 1 } - - - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - - - name: "updateOne" - arguments: - filter: { _id: 2 } - update: { $inc: { x : 1 }} - options: { ordered: true } - outcome: - result: - deletedCount: 1 - insertedCount: 1 - insertedIds: { 1: 3 } - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - upsertedIds: { } - collection: - data: - - { _id: 2, x: 23 } - - { _id: 3, x: 33 } - - - - description: "BulkWrite fails with a RetryableWriteError label after two connection failures" - failPoint: - configureFailPoint: failCommand - mode: { times: 2 } - data: - failCommands: ["update"] - closeConnection: true - operation: - name: "bulkWrite" - arguments: - requests: - - - name: "deleteOne" - arguments: - filter: { _id: 1 } - - - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - - - name: "updateOne" - arguments: - filter: { _id: 2 } - update: { $inc: { x : 1 }} - options: { ordered: true } - outcome: - error: true - result: - errorLabelsContain: ["RetryableWriteError"] - collection: - data: - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } diff --git a/test/spec/retryable-writes/legacy/bulkWrite.json b/test/spec/retryable-writes/legacy/bulkWrite.json deleted file mode 100644 index 72a8d01893..0000000000 --- a/test/spec/retryable-writes/legacy/bulkWrite.json +++ /dev/null @@ -1,806 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "3.6", - "topology": [ - "replicaset" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - } - ], - "tests": [ - { - "description": "First command is retried", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - } - }, - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 2, - "x": 22 - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 2 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 1 - } - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "deletedCount": 1, - "insertedCount": 1, - "insertedIds": { - "0": 2 - }, - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [ - { - "_id": 2, - "x": 23 - } - ] - } - } - }, - { - "description": "All commands are retried", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 7 - } - }, - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 2, - "x": 22 - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 2 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 4, - "x": 44 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "upsert": true - } - }, - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 5, - "x": 55 - } - } - }, - { - "name": "replaceOne", - "arguments": { - "filter": { - "_id": 3 - }, - "replacement": { - "_id": 3, - "x": 333 - } - } - }, - { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 1 - } - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "deletedCount": 1, - "insertedCount": 3, - "insertedIds": { - "0": 2, - "2": 3, - "4": 5 - }, - "matchedCount": 2, - "modifiedCount": 2, - "upsertedCount": 1, - "upsertedIds": { - "3": 4 - } - }, - "collection": { - "data": [ - { - "_id": 2, - "x": 23 - }, - { - "_id": 3, - "x": 333 - }, - { - "_id": 4, - "x": 45 - }, - { - "_id": 5, - "x": 55 - } - ] - } - } - }, - { - "description": "Both commands are retried after their first statement fails", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 2 - } - }, - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 2, - "x": 22 - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 2 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "deletedCount": 0, - "insertedCount": 1, - "insertedIds": { - "0": 2 - }, - "matchedCount": 2, - "modifiedCount": 2, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 12 - }, - { - "_id": 2, - "x": 23 - } - ] - } - } - }, - { - "description": "Second command is retried after its second statement fails", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "skip": 2 - } - }, - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 2, - "x": 22 - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 2 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "deletedCount": 0, - "insertedCount": 1, - "insertedIds": { - "0": 2 - }, - "matchedCount": 2, - "modifiedCount": 2, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 12 - }, - { - "_id": 2, - "x": 23 - } - ] - } - } - }, - { - "description": "BulkWrite with unordered execution", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - } - }, - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 2, - "x": 22 - } - } - }, - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - } - ], - "options": { - "ordered": false - } - } - }, - "outcome": { - "result": { - "deletedCount": 0, - "insertedCount": 2, - "insertedIds": { - "0": 2, - "1": 3 - }, - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "First insertOne is never committed", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 2 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 2, - "x": 22 - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 2 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 1 - } - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "error": true, - "result": { - "deletedCount": 0, - "insertedCount": 0, - "insertedIds": {}, - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - } - ] - } - } - }, - { - "description": "Second updateOne is never committed", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "skip": 1 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 2, - "x": 22 - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 2 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 1 - } - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "error": true, - "result": { - "deletedCount": 0, - "insertedCount": 1, - "insertedIds": { - "0": 2 - }, - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "Third updateOne is never committed", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "skip": 2 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 2, - "x": 22 - } - } - }, - { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 2 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "error": true, - "result": { - "deletedCount": 0, - "insertedCount": 1, - "insertedIds": { - "1": 2 - }, - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 12 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "Single-document write following deleteMany is retried", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "deleteMany", - "arguments": { - "filter": { - "x": 11 - } - } - }, - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 2, - "x": 22 - } - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "deletedCount": 1, - "insertedCount": 1, - "insertedIds": { - "1": 2 - }, - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [ - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "Single-document write following updateMany is retried", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "bulkWrite", - "arguments": { - "requests": [ - { - "name": "updateMany", - "arguments": { - "filter": { - "x": 11 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - { - "name": "insertOne", - "arguments": { - "document": { - "_id": 2, - "x": 22 - } - } - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "deletedCount": 0, - "insertedCount": 1, - "insertedIds": { - "1": 2 - }, - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0, - "upsertedIds": {} - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 12 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/bulkWrite.yml b/test/spec/retryable-writes/legacy/bulkWrite.yml deleted file mode 100644 index 939dacf772..0000000000 --- a/test/spec/retryable-writes/legacy/bulkWrite.yml +++ /dev/null @@ -1,396 +0,0 @@ -runOn: - - - minServerVersion: "3.6" - topology: ["replicaset"] - -data: - - { _id: 1, x: 11 } - -tests: - - - description: "First command is retried" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - operation: - name: "bulkWrite" - arguments: - requests: - - - name: "insertOne" - arguments: - document: { _id: 2, x: 22 } - - - name: "updateOne" - arguments: - filter: { _id: 2 } - update: { $inc: { x : 1 }} - - - name: "deleteOne" - arguments: - filter: { _id: 1 } - options: { ordered: true } - outcome: - result: - deletedCount: 1 - insertedCount: 1 - insertedIds: { 0: 2 } - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - upsertedIds: { } - collection: - data: - - { _id: 2, x: 23 } - - - # Write operations in this ordered batch are intentionally sequenced so - # that each write command consists of a single statement, which will - # fail on the first attempt and succeed on the second, retry attempt. - description: "All commands are retried" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 7 } - operation: - name: "bulkWrite" - arguments: - requests: - - - name: "insertOne" - arguments: - document: { _id: 2, x: 22 } - - - name: "updateOne" - arguments: - filter: { _id: 2 } - update: { $inc: { x : 1 }} - - - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - - - name: "updateOne" - arguments: - filter: { _id: 4, x: 44 } - update: { $inc: { x : 1 }} - upsert: true - - - name: "insertOne" - arguments: - document: { _id: 5, x: 55 } - - - name: "replaceOne" - arguments: - filter: { _id: 3 } - replacement: { _id: 3, x: 333 } - - - name: "deleteOne" - arguments: - filter: { _id: 1 } - options: { ordered: true } - outcome: - result: - deletedCount: 1 - insertedCount: 3 - insertedIds: { 0: 2, 2: 3, 4: 5 } - matchedCount: 2 - modifiedCount: 2 - upsertedCount: 1 - upsertedIds: { 3: 4 } - collection: - data: - - { _id: 2, x: 23 } - - { _id: 3, x: 333 } - - { _id: 4, x: 45 } - - { _id: 5, x: 55 } - - - description: "Both commands are retried after their first statement fails" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 2 } - operation: - name: "bulkWrite" - arguments: - requests: - - - name: "insertOne" - arguments: - document: { _id: 2, x: 22 } - - - name: "updateOne" - arguments: - filter: { _id: 1 } - update: { $inc: { x : 1 }} - - - name: "updateOne" - arguments: - filter: { _id: 2 } - update: { $inc: { x : 1 }} - options: { ordered: true } - outcome: - result: - deletedCount: 0 - insertedCount: 1 - insertedIds: { 0: 2 } - matchedCount: 2 - modifiedCount: 2 - upsertedCount: 0 - upsertedIds: { } - collection: - data: - - { _id: 1, x: 12 } - - { _id: 2, x: 23 } - - - description: "Second command is retried after its second statement fails" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { skip: 2 } - operation: - name: "bulkWrite" - arguments: - requests: - - - name: "insertOne" - arguments: - document: { _id: 2, x: 22 } - - - name: "updateOne" - arguments: - filter: { _id: 1 } - update: { $inc: { x : 1 }} - - - name: "updateOne" - arguments: - filter: { _id: 2 } - update: { $inc: { x : 1 }} - options: { ordered: true } - outcome: - result: - deletedCount: 0 - insertedCount: 1 - insertedIds: { 0: 2 } - matchedCount: 2 - modifiedCount: 2 - upsertedCount: 0 - upsertedIds: { } - collection: - data: - - { _id: 1, x: 12 } - - { _id: 2, x: 23 } - - - description: "BulkWrite with unordered execution" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - operation: - name: "bulkWrite" - arguments: - requests: - - - name: "insertOne" - arguments: - document: { _id: 2, x: 22 } - - - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - options: { ordered: false } - outcome: - result: - deletedCount: 0 - insertedCount: 2 - insertedIds: { 0: 2, 1: 3 } - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 0 - upsertedIds: { } - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "First insertOne is never committed" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 2 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "bulkWrite" - arguments: - requests: - - - name: "insertOne" - arguments: - document: { _id: 2, x: 22 } - - - name: "updateOne" - arguments: - filter: { _id: 2 } - update: { $inc: { x : 1 }} - - - name: "deleteOne" - arguments: - filter: { _id: 1 } - options: { ordered: true } - outcome: - error: true - result: - deletedCount: 0 - insertedCount: 0 - insertedIds: { } - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 0 - upsertedIds: { } - collection: - data: - - { _id: 1, x: 11 } - - - description: "Second updateOne is never committed" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { skip: 1 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "bulkWrite" - arguments: - requests: - - - name: "insertOne" - arguments: - document: { _id: 2, x: 22 } - - - name: "updateOne" - arguments: - filter: { _id: 2 } - update: { $inc: { x : 1 }} - - - name: "deleteOne" - arguments: - filter: { _id: 1 } - options: { ordered: true } - outcome: - error: true - result: - deletedCount: 0 - insertedCount: 1 - insertedIds: { 0: 2 } - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 0 - upsertedIds: { } - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - - description: "Third updateOne is never committed" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { skip: 2 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "bulkWrite" - arguments: - requests: - - - name: "updateOne" - arguments: - filter: { _id: 1 } - update: { $inc: { x : 1 }} - - - name: "insertOne" - arguments: - document: { _id: 2, x: 22 } - - - name: "updateOne" - arguments: - filter: { _id: 2 } - update: { $inc: { x : 1 }} - options: { ordered: true } - outcome: - error: true - result: - deletedCount: 0 - insertedCount: 1 - insertedIds: { 1: 2 } - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - upsertedIds: { } - collection: - data: - - { _id: 1, x: 12 } - - { _id: 2, x: 22 } - - - # The onPrimaryTransactionalWrite fail point only triggers for write - # operations that include a transaction ID. Therefore, it will not - # affect the initial deleteMany and will trigger once (and only once) - # for the first insertOne attempt. - description: "Single-document write following deleteMany is retried" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "bulkWrite" - arguments: - requests: - - - name: "deleteMany" - arguments: - filter: { x: 11 } - - - name: "insertOne" - arguments: - document: { _id: 2, x: 22 } - options: { ordered: true } - outcome: - result: - deletedCount: 1 - insertedCount: 1 - insertedIds: { 1: 2 } - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 0 - upsertedIds: { } - collection: - data: - - { _id: 2, x: 22 } - - - # The onPrimaryTransactionalWrite fail point only triggers for write - # operations that include a transaction ID. Therefore, it will not - # affect the initial updateMany and will trigger once (and only once) - # for the first insertOne attempt. - description: "Single-document write following updateMany is retried" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "bulkWrite" - arguments: - requests: - - - name: "updateMany" - arguments: - filter: { x: 11 } - update: { $inc: { x : 1 }} - - - name: "insertOne" - arguments: - document: { _id: 2, x: 22 } - options: { ordered: true } - outcome: - result: - deletedCount: 0 - insertedCount: 1 - insertedIds: { 1: 2 } - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - upsertedIds: { } - collection: - data: - - { _id: 1, x: 12 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/legacy/deleteMany.json b/test/spec/retryable-writes/legacy/deleteMany.json deleted file mode 100644 index faa21c44f1..0000000000 --- a/test/spec/retryable-writes/legacy/deleteMany.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "3.6", - "topology": [ - "replicaset", - "sharded", - "load-balanced" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "DeleteMany ignores retryWrites", - "useMultipleMongoses": true, - "operation": { - "name": "deleteMany", - "arguments": { - "filter": {} - } - }, - "outcome": { - "result": { - "deletedCount": 2 - }, - "collection": { - "data": [] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/deleteMany.yml b/test/spec/retryable-writes/legacy/deleteMany.yml deleted file mode 100644 index 4743953fff..0000000000 --- a/test/spec/retryable-writes/legacy/deleteMany.yml +++ /dev/null @@ -1,22 +0,0 @@ -runOn: - - - minServerVersion: "3.6" - topology: ["replicaset", "sharded", "load-balanced"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "DeleteMany ignores retryWrites" - useMultipleMongoses: true - operation: - name: "deleteMany" - arguments: - filter: { } - outcome: - result: - deletedCount: 2 - collection: - data: [] diff --git a/test/spec/retryable-writes/legacy/deleteOne-errorLabels.json b/test/spec/retryable-writes/legacy/deleteOne-errorLabels.json deleted file mode 100644 index c14692fd1a..0000000000 --- a/test/spec/retryable-writes/legacy/deleteOne-errorLabels.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.3.1", - "topology": [ - "replicaset", - "sharded", - "load-balanced" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "DeleteOne succeeds with RetryableWriteError from server", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "delete" - ], - "errorCode": 112, - "errorLabels": [ - "RetryableWriteError" - ] - } - }, - "operation": { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 1 - } - } - }, - "outcome": { - "result": { - "deletedCount": 1 - }, - "collection": { - "data": [ - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "DeleteOne fails if server does not return RetryableWriteError", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "delete" - ], - "errorCode": 11600, - "errorLabels": [] - } - }, - "operation": { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 1 - } - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsOmit": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/deleteOne-errorLabels.yml b/test/spec/retryable-writes/legacy/deleteOne-errorLabels.yml deleted file mode 100644 index 9ee5c7426e..0000000000 --- a/test/spec/retryable-writes/legacy/deleteOne-errorLabels.yml +++ /dev/null @@ -1,48 +0,0 @@ -runOn: - - minServerVersion: "4.3.1" - topology: ["replicaset", "sharded", "load-balanced"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - description: "DeleteOne succeeds with RetryableWriteError from server" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["delete"] - errorCode: 112 # WriteConflict, not a retryable error code - errorLabels: ["RetryableWriteError"] # Override server behavior: send RetryableWriteError label with non-retryable error code - operation: - name: "deleteOne" - arguments: - filter: { _id: 1 } - outcome: # Driver retries operation and it succeeds - result: - deletedCount: 1 - collection: - data: - - { _id: 2, x: 22 } - - - description: "DeleteOne fails if server does not return RetryableWriteError" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["delete"] - errorCode: 11600 # InterruptedAtShutdown, normally a retryable error code - errorLabels: [] # Override server behavior: do not send RetryableWriteError label with retryable code - operation: - name: "deleteOne" - arguments: - filter: { _id: 1 } - outcome: - error: true # Driver does not retry operation because there was no RetryableWriteError label on response - result: - errorLabelsOmit: ["RetryableWriteError"] - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/legacy/deleteOne-serverErrors.json b/test/spec/retryable-writes/legacy/deleteOne-serverErrors.json deleted file mode 100644 index a1a27838de..0000000000 --- a/test/spec/retryable-writes/legacy/deleteOne-serverErrors.json +++ /dev/null @@ -1,153 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "DeleteOne succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "delete" - ], - "errorCode": 189, - "errorLabels": [ - "RetryableWriteError" - ] - } - }, - "operation": { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 1 - } - } - }, - "outcome": { - "result": { - "deletedCount": 1 - }, - "collection": { - "data": [ - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "DeleteOne succeeds after WriteConcernError ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "delete" - ], - "errorLabels": [ - "RetryableWriteError" - ], - "writeConcernError": { - "code": 91, - "errmsg": "Replication is being shut down" - } - } - }, - "operation": { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 1 - } - } - }, - "outcome": { - "result": { - "deletedCount": 1 - }, - "collection": { - "data": [ - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "DeleteOne fails with RetryableWriteError label after two connection failures", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "delete" - ], - "closeConnection": true - } - }, - "operation": { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 1 - } - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsContain": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/deleteOne-serverErrors.yml b/test/spec/retryable-writes/legacy/deleteOne-serverErrors.yml deleted file mode 100644 index f4c98c919b..0000000000 --- a/test/spec/retryable-writes/legacy/deleteOne-serverErrors.yml +++ /dev/null @@ -1,73 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "DeleteOne succeeds after PrimarySteppedDown" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["delete"] - errorCode: 189 - errorLabels: ["RetryableWriteError"] - operation: - name: "deleteOne" - arguments: - filter: { _id: 1 } - outcome: - result: - deletedCount: 1 - collection: - data: - - { _id: 2, x: 22 } - - - description: "DeleteOne succeeds after WriteConcernError ShutdownInProgress" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["delete"] - errorLabels: ["RetryableWriteError"] - writeConcernError: - code: 91 - errmsg: Replication is being shut down - operation: - name: "deleteOne" - arguments: - filter: { _id: 1 } - outcome: - result: - deletedCount: 1 - collection: - data: - - { _id: 2, x: 22 } - - - description: "DeleteOne fails with RetryableWriteError label after two connection failures" - failPoint: - configureFailPoint: failCommand - mode: { times: 2 } - data: - failCommands: ["delete"] - closeConnection: true - operation: - name: "deleteOne" - arguments: - filter: { _id: 1 } - outcome: - error: true - result: - errorLabelsContain: ["RetryableWriteError"] - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/legacy/deleteOne.json b/test/spec/retryable-writes/legacy/deleteOne.json deleted file mode 100644 index 592937aced..0000000000 --- a/test/spec/retryable-writes/legacy/deleteOne.json +++ /dev/null @@ -1,120 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "3.6", - "topology": [ - "replicaset" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "DeleteOne is committed on first attempt", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - } - }, - "operation": { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 1 - } - } - }, - "outcome": { - "result": { - "deletedCount": 1 - }, - "collection": { - "data": [ - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "DeleteOne is not committed on first attempt", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 1 - } - } - }, - "outcome": { - "result": { - "deletedCount": 1 - }, - "collection": { - "data": [ - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "DeleteOne is never committed", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 2 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "deleteOne", - "arguments": { - "filter": { - "_id": 1 - } - } - }, - "outcome": { - "error": true, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/deleteOne.yml b/test/spec/retryable-writes/legacy/deleteOne.yml deleted file mode 100644 index b15c991cda..0000000000 --- a/test/spec/retryable-writes/legacy/deleteOne.yml +++ /dev/null @@ -1,57 +0,0 @@ -runOn: - - - minServerVersion: "3.6" - topology: ["replicaset"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "DeleteOne is committed on first attempt" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - operation: - name: "deleteOne" - arguments: - filter: { _id: 1 } - outcome: - result: - deletedCount: 1 - collection: - data: - - { _id: 2, x: 22 } - - - description: "DeleteOne is not committed on first attempt" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "deleteOne" - arguments: - filter: { _id: 1 } - outcome: - result: - deletedCount: 1 - collection: - data: - - { _id: 2, x: 22 } - - - description: "DeleteOne is never committed" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 2 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "deleteOne" - arguments: - filter: { _id: 1 } - outcome: - error: true - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/legacy/findOneAndDelete-errorLabels.json b/test/spec/retryable-writes/legacy/findOneAndDelete-errorLabels.json deleted file mode 100644 index 60e6e0a7bc..0000000000 --- a/test/spec/retryable-writes/legacy/findOneAndDelete-errorLabels.json +++ /dev/null @@ -1,118 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.3.1", - "topology": [ - "replicaset", - "sharded", - "load-balanced" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "FindOneAndDelete succeeds with RetryableWriteError from server", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "findAndModify" - ], - "errorCode": 112, - "errorLabels": [ - "RetryableWriteError" - ] - } - }, - "operation": { - "name": "findOneAndDelete", - "arguments": { - "filter": { - "x": { - "$gte": 11 - } - }, - "sort": { - "x": 1 - } - } - }, - "outcome": { - "result": { - "_id": 1, - "x": 11 - }, - "collection": { - "data": [ - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "FindOneAndDelete fails if server does not return RetryableWriteError", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "findAndModify" - ], - "errorCode": 11600, - "errorLabels": [] - } - }, - "operation": { - "name": "findOneAndDelete", - "arguments": { - "filter": { - "x": { - "$gte": 11 - } - }, - "sort": { - "x": 1 - } - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsOmit": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/findOneAndDelete-errorLabels.yml b/test/spec/retryable-writes/legacy/findOneAndDelete-errorLabels.yml deleted file mode 100644 index 5192c5adfe..0000000000 --- a/test/spec/retryable-writes/legacy/findOneAndDelete-errorLabels.yml +++ /dev/null @@ -1,49 +0,0 @@ -runOn: - - minServerVersion: "4.3.1" - topology: ["replicaset", "sharded", "load-balanced"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - description: "FindOneAndDelete succeeds with RetryableWriteError from server" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["findAndModify"] - errorCode: 112 # WriteConflict, not a retryable error code - errorLabels: ["RetryableWriteError"] # Override server behavior: send RetryableWriteError label with non-retryable error code - operation: - name: "findOneAndDelete" - arguments: - filter: { x: { $gte: 11 } } - sort: { x: 1 } - outcome: # Driver retries operation and it succeeds - result: { _id: 1, x: 11 } - collection: - data: - - { _id: 2, x: 22 } - - - description: "FindOneAndDelete fails if server does not return RetryableWriteError" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["findAndModify"] - errorCode: 11600 # InterruptedAtShutdown, normally a retryable error code - errorLabels: [] # Override server behavior: do not send RetryableWriteError label with retryable code - operation: - name: "findOneAndDelete" - arguments: - filter: { x: { $gte: 11 } } - sort: { x: 1 } - outcome: - error: true # Driver does not retry operation because there was no RetryableWriteError label on response - result: - errorLabelsOmit: ["RetryableWriteError"] - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/legacy/findOneAndDelete-serverErrors.json b/test/spec/retryable-writes/legacy/findOneAndDelete-serverErrors.json deleted file mode 100644 index c18b63f456..0000000000 --- a/test/spec/retryable-writes/legacy/findOneAndDelete-serverErrors.json +++ /dev/null @@ -1,170 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "FindOneAndDelete succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "findAndModify" - ], - "errorCode": 189, - "errorLabels": [ - "RetryableWriteError" - ] - } - }, - "operation": { - "name": "findOneAndDelete", - "arguments": { - "filter": { - "x": { - "$gte": 11 - } - }, - "sort": { - "x": 1 - } - } - }, - "outcome": { - "result": { - "_id": 1, - "x": 11 - }, - "collection": { - "data": [ - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "FindOneAndDelete succeeds after WriteConcernError ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "findAndModify" - ], - "errorLabels": [ - "RetryableWriteError" - ], - "writeConcernError": { - "code": 91, - "errmsg": "Replication is being shut down" - } - } - }, - "operation": { - "name": "findOneAndDelete", - "arguments": { - "filter": { - "x": { - "$gte": 11 - } - }, - "sort": { - "x": 1 - } - } - }, - "outcome": { - "result": { - "_id": 1, - "x": 11 - }, - "collection": { - "data": [ - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "FindOneAndDelete fails with a RetryableWriteError label after two connection failures", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "findAndModify" - ], - "closeConnection": true - } - }, - "operation": { - "name": "findOneAndDelete", - "arguments": { - "filter": { - "x": { - "$gte": 11 - } - }, - "sort": { - "x": 1 - } - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsContain": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/findOneAndDelete-serverErrors.yml b/test/spec/retryable-writes/legacy/findOneAndDelete-serverErrors.yml deleted file mode 100644 index 688ee3342e..0000000000 --- a/test/spec/retryable-writes/legacy/findOneAndDelete-serverErrors.yml +++ /dev/null @@ -1,74 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "FindOneAndDelete succeeds after PrimarySteppedDown" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["findAndModify"] - errorCode: 189 - errorLabels: ["RetryableWriteError"] - operation: - name: "findOneAndDelete" - arguments: - filter: { x: { $gte: 11 }} - sort: { x: 1 } - outcome: - result: { _id: 1, x: 11 } - collection: - data: - - { _id: 2, x: 22 } - - - description: "FindOneAndDelete succeeds after WriteConcernError ShutdownInProgress" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["findAndModify"] - errorLabels: ["RetryableWriteError"] - writeConcernError: - code: 91 - errmsg: Replication is being shut down - operation: - name: "findOneAndDelete" - arguments: - filter: { x: { $gte: 11 }} - sort: { x: 1 } - outcome: - result: { _id: 1, x: 11 } - collection: - data: - - { _id: 2, x: 22 } - - - description: "FindOneAndDelete fails with a RetryableWriteError label after two connection failures" - failPoint: - configureFailPoint: failCommand - mode: { times: 2 } - data: - failCommands: ["findAndModify"] - closeConnection: true - operation: - name: "findOneAndDelete" - arguments: - filter: { x: { $gte: 11 } } - sort: { x: 1 } - outcome: - error: true - result: - errorLabelsContain: ["RetryableWriteError"] - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/legacy/findOneAndDelete.json b/test/spec/retryable-writes/legacy/findOneAndDelete.json deleted file mode 100644 index 0cbe18108b..0000000000 --- a/test/spec/retryable-writes/legacy/findOneAndDelete.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "3.6", - "topology": [ - "replicaset" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "FindOneAndDelete is committed on first attempt", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - } - }, - "operation": { - "name": "findOneAndDelete", - "arguments": { - "filter": { - "x": { - "$gte": 11 - } - }, - "sort": { - "x": 1 - } - } - }, - "outcome": { - "result": { - "_id": 1, - "x": 11 - }, - "collection": { - "data": [ - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "FindOneAndDelete is not committed on first attempt", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "findOneAndDelete", - "arguments": { - "filter": { - "x": { - "$gte": 11 - } - }, - "sort": { - "x": 1 - } - } - }, - "outcome": { - "result": { - "_id": 1, - "x": 11 - }, - "collection": { - "data": [ - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "FindOneAndDelete is never committed", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 2 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "findOneAndDelete", - "arguments": { - "filter": { - "x": { - "$gte": 11 - } - }, - "sort": { - "x": 1 - } - } - }, - "outcome": { - "error": true, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/findOneAndDelete.yml b/test/spec/retryable-writes/legacy/findOneAndDelete.yml deleted file mode 100644 index 1456ad7162..0000000000 --- a/test/spec/retryable-writes/legacy/findOneAndDelete.yml +++ /dev/null @@ -1,58 +0,0 @@ -runOn: - - - minServerVersion: "3.6" - topology: ["replicaset"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "FindOneAndDelete is committed on first attempt" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - operation: - name: "findOneAndDelete" - arguments: - filter: { x: { $gte: 11 }} - sort: { x: 1 } - outcome: - result: { _id: 1, x: 11 } - collection: - data: - - { _id: 2, x: 22 } - - - description: "FindOneAndDelete is not committed on first attempt" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "findOneAndDelete" - arguments: - filter: { x: { $gte: 11 }} - sort: { x: 1 } - outcome: - result: { _id: 1, x: 11 } - collection: - data: - - { _id: 2, x: 22 } - - - description: "FindOneAndDelete is never committed" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 2 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "findOneAndDelete" - arguments: - filter: { x: { $gte: 11 }} - sort: { x: 1 } - outcome: - error: true - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/legacy/findOneAndReplace-errorLabels.json b/test/spec/retryable-writes/legacy/findOneAndReplace-errorLabels.json deleted file mode 100644 index afa2f47af4..0000000000 --- a/test/spec/retryable-writes/legacy/findOneAndReplace-errorLabels.json +++ /dev/null @@ -1,122 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.3.1", - "topology": [ - "replicaset", - "sharded", - "load-balanced" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "FindOneAndReplace succeeds with RetryableWriteError from server", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "findAndModify" - ], - "errorCode": 112, - "errorLabels": [ - "RetryableWriteError" - ] - } - }, - "operation": { - "name": "findOneAndReplace", - "arguments": { - "filter": { - "_id": 1 - }, - "replacement": { - "_id": 1, - "x": 111 - }, - "returnDocument": "Before" - } - }, - "outcome": { - "result": { - "_id": 1, - "x": 11 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 111 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "FindOneAndReplace fails if server does not return RetryableWriteError", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "findAndModify" - ], - "errorCode": 11600, - "errorLabels": [] - } - }, - "operation": { - "name": "findOneAndReplace", - "arguments": { - "filter": { - "_id": 1 - }, - "replacement": { - "_id": 1, - "x": 111 - }, - "returnDocument": "Before" - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsOmit": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/findOneAndReplace-errorLabels.yml b/test/spec/retryable-writes/legacy/findOneAndReplace-errorLabels.yml deleted file mode 100644 index 184366163f..0000000000 --- a/test/spec/retryable-writes/legacy/findOneAndReplace-errorLabels.yml +++ /dev/null @@ -1,52 +0,0 @@ -runOn: - - minServerVersion: "4.3.1" - topology: ["replicaset", "sharded", "load-balanced"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - description: "FindOneAndReplace succeeds with RetryableWriteError from server" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["findAndModify"] - errorCode: 112 # WriteConflict, not a retryable error code - errorLabels: ["RetryableWriteError"] # Override server behavior: send RetryableWriteError label with non-retryable error code - operation: - name: "findOneAndReplace" - arguments: - filter: { _id: 1 } - replacement: { _id: 1, x: 111 } - returnDocument: "Before" - outcome: # Driver retries operation and it succeeds - result: { _id: 1, x: 11 } - collection: - data: - - { _id: 1, x: 111 } - - { _id: 2, x: 22 } - - - description: "FindOneAndReplace fails if server does not return RetryableWriteError" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["findAndModify"] - errorCode: 11600 # InterruptedAtShutdown, normally a retryable error code - errorLabels: [] # Override server behavior: do not send RetryableWriteError label with retryable code - operation: - name: "findOneAndReplace" - arguments: - filter: { _id: 1 } - replacement: { _id: 1, x: 111 } - returnDocument: "Before" - outcome: - error: true # Driver does not retry operation because there was no RetryableWriteError label on response - result: - errorLabelsOmit: ["RetryableWriteError"] - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/legacy/findOneAndReplace-serverErrors.json b/test/spec/retryable-writes/legacy/findOneAndReplace-serverErrors.json deleted file mode 100644 index 944a3af848..0000000000 --- a/test/spec/retryable-writes/legacy/findOneAndReplace-serverErrors.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "FindOneAndReplace succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "findAndModify" - ], - "errorCode": 189, - "errorLabels": [ - "RetryableWriteError" - ] - } - }, - "operation": { - "name": "findOneAndReplace", - "arguments": { - "filter": { - "_id": 1 - }, - "replacement": { - "_id": 1, - "x": 111 - }, - "returnDocument": "Before" - } - }, - "outcome": { - "result": { - "_id": 1, - "x": 11 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 111 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "FindOneAndReplace succeeds after WriteConcernError ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "findAndModify" - ], - "errorLabels": [ - "RetryableWriteError" - ], - "writeConcernError": { - "code": 91, - "errmsg": "Replication is being shut down" - } - } - }, - "operation": { - "name": "findOneAndReplace", - "arguments": { - "filter": { - "_id": 1 - }, - "replacement": { - "_id": 1, - "x": 111 - }, - "returnDocument": "Before" - } - }, - "outcome": { - "result": { - "_id": 1, - "x": 11 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 111 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "FindOneAndReplace fails with a RetryableWriteError label after two connection failures", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "findAndModify" - ], - "closeConnection": true - } - }, - "operation": { - "name": "findOneAndReplace", - "arguments": { - "filter": { - "_id": 1 - }, - "replacement": { - "_id": 1, - "x": 111 - }, - "returnDocument": "Before" - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsContain": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/findOneAndReplace-serverErrors.yml b/test/spec/retryable-writes/legacy/findOneAndReplace-serverErrors.yml deleted file mode 100644 index 6f0f31874a..0000000000 --- a/test/spec/retryable-writes/legacy/findOneAndReplace-serverErrors.yml +++ /dev/null @@ -1,80 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "FindOneAndReplace succeeds after PrimarySteppedDown" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["findAndModify"] - errorCode: 189 - errorLabels: ["RetryableWriteError"] - operation: - name: "findOneAndReplace" - arguments: - filter: { _id: 1 } - replacement: { _id: 1, x: 111 } - returnDocument: "Before" - outcome: - result: { _id: 1, x: 11 } - collection: - data: - - { _id: 1, x: 111 } - - { _id: 2, x: 22 } - - - description: "FindOneAndReplace succeeds after WriteConcernError ShutdownInProgress" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["findAndModify"] - errorLabels: ["RetryableWriteError"] - writeConcernError: - code: 91 - errmsg: Replication is being shut down - operation: - name: "findOneAndReplace" - arguments: - filter: { _id: 1 } - replacement: { _id: 1, x: 111 } - returnDocument: "Before" - outcome: - result: { _id: 1, x: 11 } - collection: - data: - - { _id: 1, x: 111 } - - { _id: 2, x: 22 } - - - - description: "FindOneAndReplace fails with a RetryableWriteError label after two connection failures" - failPoint: - configureFailPoint: failCommand - mode: { times: 2 } - data: - failCommands: ["findAndModify"] - closeConnection: true - operation: - name: "findOneAndReplace" - arguments: - filter: { _id: 1 } - replacement: { _id: 1, x: 111 } - returnDocument: "Before" - outcome: - error: true - result: - errorLabelsContain: ["RetryableWriteError"] - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/legacy/findOneAndReplace.json b/test/spec/retryable-writes/legacy/findOneAndReplace.json deleted file mode 100644 index e1f9ab7f8c..0000000000 --- a/test/spec/retryable-writes/legacy/findOneAndReplace.json +++ /dev/null @@ -1,145 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "3.6", - "topology": [ - "replicaset" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "FindOneAndReplace is committed on first attempt", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - } - }, - "operation": { - "name": "findOneAndReplace", - "arguments": { - "filter": { - "_id": 1 - }, - "replacement": { - "_id": 1, - "x": 111 - }, - "returnDocument": "Before" - } - }, - "outcome": { - "result": { - "_id": 1, - "x": 11 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 111 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "FindOneAndReplace is not committed on first attempt", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "findOneAndReplace", - "arguments": { - "filter": { - "_id": 1 - }, - "replacement": { - "_id": 1, - "x": 111 - }, - "returnDocument": "Before" - } - }, - "outcome": { - "result": { - "_id": 1, - "x": 11 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 111 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "FindOneAndReplace is never committed", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 2 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "findOneAndReplace", - "arguments": { - "filter": { - "_id": 1 - }, - "replacement": { - "_id": 1, - "x": 111 - }, - "returnDocument": "Before" - } - }, - "outcome": { - "error": true, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/findOneAndReplace.yml b/test/spec/retryable-writes/legacy/findOneAndReplace.yml deleted file mode 100644 index 36d81d461e..0000000000 --- a/test/spec/retryable-writes/legacy/findOneAndReplace.yml +++ /dev/null @@ -1,63 +0,0 @@ -runOn: - - - minServerVersion: "3.6" - topology: ["replicaset"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "FindOneAndReplace is committed on first attempt" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - operation: - name: "findOneAndReplace" - arguments: - filter: { _id: 1 } - replacement: { _id: 1, x: 111 } - returnDocument: "Before" - outcome: - result: { _id: 1, x: 11 } - collection: - data: - - { _id: 1, x: 111 } - - { _id: 2, x: 22 } - - - description: "FindOneAndReplace is not committed on first attempt" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "findOneAndReplace" - arguments: - filter: { _id: 1 } - replacement: { _id: 1, x: 111 } - returnDocument: "Before" - outcome: - result: { _id: 1, x: 11 } - collection: - data: - - { _id: 1, x: 111 } - - { _id: 2, x: 22 } - - - description: "FindOneAndReplace is never committed" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 2 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "findOneAndReplace" - arguments: - filter: { _id: 1 } - replacement: { _id: 1, x: 111 } - returnDocument: "Before" - outcome: - error: true - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/legacy/findOneAndUpdate-errorLabels.json b/test/spec/retryable-writes/legacy/findOneAndUpdate-errorLabels.json deleted file mode 100644 index 19b3a9e771..0000000000 --- a/test/spec/retryable-writes/legacy/findOneAndUpdate-errorLabels.json +++ /dev/null @@ -1,124 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.3.1", - "topology": [ - "replicaset", - "sharded", - "load-balanced" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "FindOneAndUpdate succeeds with RetryableWriteError from server", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "findAndModify" - ], - "errorCode": 112, - "errorLabels": [ - "RetryableWriteError" - ] - } - }, - "operation": { - "name": "findOneAndUpdate", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "returnDocument": "Before" - } - }, - "outcome": { - "result": { - "_id": 1, - "x": 11 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 12 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "FindOneAndUpdate fails if server does not return RetryableWriteError", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "findAndModify" - ], - "errorCode": 11600, - "errorLabels": [] - } - }, - "operation": { - "name": "findOneAndUpdate", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "returnDocument": "Before" - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsOmit": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/findOneAndUpdate-errorLabels.yml b/test/spec/retryable-writes/legacy/findOneAndUpdate-errorLabels.yml deleted file mode 100644 index 03751d568b..0000000000 --- a/test/spec/retryable-writes/legacy/findOneAndUpdate-errorLabels.yml +++ /dev/null @@ -1,52 +0,0 @@ -runOn: - - minServerVersion: "4.3.1" - topology: ["replicaset", "sharded", "load-balanced"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - description: "FindOneAndUpdate succeeds with RetryableWriteError from server" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["findAndModify"] - errorCode: 112 # WriteConflict, not a retryable error code - errorLabels: ["RetryableWriteError"] # Override server behavior: send RetryableWriteError label with non-retryable error code - operation: - name: "findOneAndUpdate" - arguments: - filter: { _id: 1 } - update: { $inc: { x: 1 } } - returnDocument: "Before" - outcome: # Driver retries operation and it succeeds - result: { _id: 1, x: 11 } - collection: - data: - - { _id: 1, x: 12 } - - { _id: 2, x: 22 } - - - description: "FindOneAndUpdate fails if server does not return RetryableWriteError" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["findAndModify"] - errorCode: 11600 # InterruptedAtShutdown, normally a retryable error code - errorLabels: [] # Override server behavior: do not send RetryableWriteError label with retryable code - operation: - name: "findOneAndUpdate" - arguments: - filter: { _id: 1 } - update: { $inc: { x: 1 } } - returnDocument: "Before" - outcome: - error: true # Driver does not retry operation because there was no RetryableWriteError label on response - result: - errorLabelsOmit: ["RetryableWriteError"] - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/legacy/findOneAndUpdate-serverErrors.json b/test/spec/retryable-writes/legacy/findOneAndUpdate-serverErrors.json deleted file mode 100644 index e83a610615..0000000000 --- a/test/spec/retryable-writes/legacy/findOneAndUpdate-serverErrors.json +++ /dev/null @@ -1,181 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "FindOneAndUpdate succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "findAndModify" - ], - "errorCode": 189, - "errorLabels": [ - "RetryableWriteError" - ] - } - }, - "operation": { - "name": "findOneAndUpdate", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "returnDocument": "Before" - } - }, - "outcome": { - "result": { - "_id": 1, - "x": 11 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 12 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "FindOneAndUpdate succeeds after WriteConcernError ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "findAndModify" - ], - "errorLabels": [ - "RetryableWriteError" - ], - "writeConcernError": { - "code": 91, - "errmsg": "Replication is being shut down" - } - } - }, - "operation": { - "name": "findOneAndUpdate", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "returnDocument": "Before" - } - }, - "outcome": { - "result": { - "_id": 1, - "x": 11 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 12 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "FindOneAndUpdate fails with a RetryableWriteError label after two connection failures", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "findAndModify" - ], - "closeConnection": true - } - }, - "operation": { - "name": "findOneAndUpdate", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "returnDocument": "Before" - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsContain": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/findOneAndUpdate-serverErrors.yml b/test/spec/retryable-writes/legacy/findOneAndUpdate-serverErrors.yml deleted file mode 100644 index c1e0b6a7ca..0000000000 --- a/test/spec/retryable-writes/legacy/findOneAndUpdate-serverErrors.yml +++ /dev/null @@ -1,79 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "FindOneAndUpdate succeeds after PrimarySteppedDown" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["findAndModify"] - errorCode: 189 - errorLabels: ["RetryableWriteError"] - operation: - name: "findOneAndUpdate" - arguments: - filter: { _id: 1 } - update: { $inc: { x : 1 }} - returnDocument: "Before" - outcome: - result: { _id: 1, x: 11 } - collection: - data: - - { _id: 1, x: 12 } - - { _id: 2, x: 22 } - - - description: "FindOneAndUpdate succeeds after WriteConcernError ShutdownInProgress" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["findAndModify"] - errorLabels: ["RetryableWriteError"] - writeConcernError: - code: 91 - errmsg: Replication is being shut down - operation: - name: "findOneAndUpdate" - arguments: - filter: { _id: 1 } - update: { $inc: { x : 1 }} - returnDocument: "Before" - outcome: - result: { _id: 1, x: 11 } - collection: - data: - - { _id: 1, x: 12 } - - { _id: 2, x: 22 } - - - description: "FindOneAndUpdate fails with a RetryableWriteError label after two connection failures" - failPoint: - configureFailPoint: failCommand - mode: { times: 2 } - data: - failCommands: ["findAndModify"] - closeConnection: true - operation: - name: "findOneAndUpdate" - arguments: - filter: { _id: 1 } - update: { $inc: { x: 1 } } - returnDocument: "Before" - outcome: - error: true - result: - errorLabelsContain: ["RetryableWriteError"] - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/legacy/findOneAndUpdate.json b/test/spec/retryable-writes/legacy/findOneAndUpdate.json deleted file mode 100644 index 9ae2d87d82..0000000000 --- a/test/spec/retryable-writes/legacy/findOneAndUpdate.json +++ /dev/null @@ -1,147 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "3.6", - "topology": [ - "replicaset" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "FindOneAndUpdate is committed on first attempt", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - } - }, - "operation": { - "name": "findOneAndUpdate", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "returnDocument": "Before" - } - }, - "outcome": { - "result": { - "_id": 1, - "x": 11 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 12 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "FindOneAndUpdate is not committed on first attempt", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "findOneAndUpdate", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "returnDocument": "Before" - } - }, - "outcome": { - "result": { - "_id": 1, - "x": 11 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 12 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "FindOneAndUpdate is never committed", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 2 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "findOneAndUpdate", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - "outcome": { - "error": true, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/findOneAndUpdate.yml b/test/spec/retryable-writes/legacy/findOneAndUpdate.yml deleted file mode 100644 index 9235526be7..0000000000 --- a/test/spec/retryable-writes/legacy/findOneAndUpdate.yml +++ /dev/null @@ -1,62 +0,0 @@ -runOn: - - - minServerVersion: "3.6" - topology: ["replicaset"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "FindOneAndUpdate is committed on first attempt" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - operation: - name: "findOneAndUpdate" - arguments: - filter: { _id: 1 } - update: { $inc: { x : 1 }} - returnDocument: "Before" - outcome: - result: { _id: 1, x: 11 } - collection: - data: - - { _id: 1, x: 12 } - - { _id: 2, x: 22 } - - - description: "FindOneAndUpdate is not committed on first attempt" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "findOneAndUpdate" - arguments: - filter: { _id: 1 } - update: { $inc: { x : 1 }} - returnDocument: "Before" - outcome: - result: { _id: 1, x: 11 } - collection: - data: - - { _id: 1, x: 12 } - - { _id: 2, x: 22 } - - - description: "FindOneAndUpdate is never committed" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 2 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "findOneAndUpdate" - arguments: - filter: { _id: 1 } - update: { $inc: { x : 1 }} - outcome: - error: true - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/legacy/insertMany-errorLabels.json b/test/spec/retryable-writes/legacy/insertMany-errorLabels.json deleted file mode 100644 index 65fd377fa6..0000000000 --- a/test/spec/retryable-writes/legacy/insertMany-errorLabels.json +++ /dev/null @@ -1,130 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.3.1", - "topology": [ - "replicaset", - "sharded", - "load-balanced" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - } - ], - "tests": [ - { - "description": "InsertMany succeeds with RetryableWriteError from server", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorCode": 112, - "errorLabels": [ - "RetryableWriteError" - ] - } - }, - "operation": { - "name": "insertMany", - "arguments": { - "documents": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "insertedIds": { - "0": 2, - "1": 3 - } - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertMany fails if server does not return RetryableWriteError", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorCode": 11600, - "errorLabels": [] - } - }, - "operation": { - "name": "insertMany", - "arguments": { - "documents": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsOmit": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/insertMany-errorLabels.yml b/test/spec/retryable-writes/legacy/insertMany-errorLabels.yml deleted file mode 100644 index 9f5e163623..0000000000 --- a/test/spec/retryable-writes/legacy/insertMany-errorLabels.yml +++ /dev/null @@ -1,54 +0,0 @@ -runOn: - - minServerVersion: "4.3.1" - topology: ["replicaset", "sharded", "load-balanced"] - -data: - - { _id: 1, x: 11 } - -tests: - - description: "InsertMany succeeds with RetryableWriteError from server" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorCode: 112 # WriteConflict, not a retryable error code - errorLabels: ["RetryableWriteError"] # Override server behavior: send RetryableWriteError label with non-retryable error code - operation: - name: "insertMany" - arguments: - documents: - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - options: { ordered: true } - outcome: # Driver retries operation and it succeeds - result: - insertedIds: { 0: 2, 1: 3 } - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertMany fails if server does not return RetryableWriteError" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorCode: 11600 # InterruptedAtShutdown, normally a retryable error code - errorLabels: [] # Override server behavior: do not send RetryableWriteError label with retryable code - operation: - name: "insertMany" - arguments: - documents: - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - options: { ordered: true } - outcome: - error: true # Driver does not retry operation because there was no RetryableWriteError label on response - result: - errorLabelsOmit: ["RetryableWriteError"] - collection: - data: - - { _id: 1, x: 11 } diff --git a/test/spec/retryable-writes/legacy/insertMany-serverErrors.json b/test/spec/retryable-writes/legacy/insertMany-serverErrors.json deleted file mode 100644 index fe8dbf4a62..0000000000 --- a/test/spec/retryable-writes/legacy/insertMany-serverErrors.json +++ /dev/null @@ -1,197 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - } - ], - "tests": [ - { - "description": "InsertMany succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorCode": 189, - "errorLabels": [ - "RetryableWriteError" - ] - } - }, - "operation": { - "name": "insertMany", - "arguments": { - "documents": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "insertedIds": { - "0": 2, - "1": 3 - } - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertMany succeeds after WriteConcernError ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorLabels": [ - "RetryableWriteError" - ], - "writeConcernError": { - "code": 91, - "errmsg": "Replication is being shut down" - } - } - }, - "operation": { - "name": "insertMany", - "arguments": { - "documents": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "insertedIds": { - "0": 2, - "1": 3 - } - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertMany fails with a RetryableWriteError label after two connection failures", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "insert" - ], - "closeConnection": true - } - }, - "operation": { - "name": "insertMany", - "arguments": { - "documents": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsContain": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/insertMany-serverErrors.yml b/test/spec/retryable-writes/legacy/insertMany-serverErrors.yml deleted file mode 100644 index 0dc7518c6b..0000000000 --- a/test/spec/retryable-writes/legacy/insertMany-serverErrors.yml +++ /dev/null @@ -1,84 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -data: - - { _id: 1, x: 11 } - -tests: - - - description: "InsertMany succeeds after PrimarySteppedDown" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorCode: 189 - errorLabels: ["RetryableWriteError"] - operation: - name: "insertMany" - arguments: - documents: - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - options: { ordered: true } - outcome: - result: - insertedIds: { 0: 2, 1: 3 } - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertMany succeeds after WriteConcernError ShutdownInProgress" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorLabels: ["RetryableWriteError"] - writeConcernError: - code: 91 - errmsg: Replication is being shut down - operation: - name: "insertMany" - arguments: - documents: - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - options: { ordered: true } - outcome: - result: - insertedIds: { 0: 2, 1: 3 } - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertMany fails with a RetryableWriteError label after two connection failures" - failPoint: - configureFailPoint: failCommand - mode: { times: 2 } - data: - failCommands: ["insert"] - closeConnection: true - operation: - name: "insertMany" - arguments: - documents: - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - options: { ordered: true } - outcome: - error: true - result: - errorLabelsContain: ["RetryableWriteError"] - collection: - data: - - { _id: 1, x: 11 } diff --git a/test/spec/retryable-writes/legacy/insertMany.json b/test/spec/retryable-writes/legacy/insertMany.json deleted file mode 100644 index 0ad326e2dc..0000000000 --- a/test/spec/retryable-writes/legacy/insertMany.json +++ /dev/null @@ -1,163 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "3.6", - "topology": [ - "replicaset" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - } - ], - "tests": [ - { - "description": "InsertMany succeeds after one network error", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - } - }, - "operation": { - "name": "insertMany", - "arguments": { - "documents": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "result": { - "insertedIds": { - "0": 2, - "1": 3 - } - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertMany with unordered execution", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - } - }, - "operation": { - "name": "insertMany", - "arguments": { - "documents": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ], - "options": { - "ordered": false - } - } - }, - "outcome": { - "result": { - "insertedIds": { - "0": 2, - "1": 3 - } - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertMany fails after multiple network errors", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": "alwaysOn", - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "insertMany", - "arguments": { - "documents": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - }, - { - "_id": 4, - "x": 44 - } - ], - "options": { - "ordered": true - } - } - }, - "outcome": { - "error": true, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/insertMany.yml b/test/spec/retryable-writes/legacy/insertMany.yml deleted file mode 100644 index eed450e0a3..0000000000 --- a/test/spec/retryable-writes/legacy/insertMany.yml +++ /dev/null @@ -1,74 +0,0 @@ -runOn: - - - minServerVersion: "3.6" - topology: ["replicaset"] - -data: - - { _id: 1, x: 11 } - -tests: - - - description: "InsertMany succeeds after one network error" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - operation: - name: "insertMany" - arguments: - documents: - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - options: { ordered: true } - outcome: - result: - insertedIds: { 0: 2, 1: 3 } - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertMany with unordered execution" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - operation: - name: "insertMany" - arguments: - documents: - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - options: { ordered: false } - outcome: - result: - insertedIds: { 0: 2, 1: 3 } - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertMany fails after multiple network errors" - failPoint: - # Normally, a mongod will insert the documents as a batch with a - # single commit. If this fails, mongod may try to insert each - # document one at a time depending on the failure. Therefore our - # single insert command may trigger the failpoint twice on each - # driver attempt. This test permanently enables the fail point to - # ensure the retry attempt always fails. - configureFailPoint: onPrimaryTransactionalWrite - mode: "alwaysOn" - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "insertMany" - arguments: - documents: - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - { _id: 4, x: 44 } - options: { ordered: true } - outcome: - error: true - collection: - data: - - { _id: 1, x: 11 } diff --git a/test/spec/retryable-writes/legacy/insertOne-errorLabels.json b/test/spec/retryable-writes/legacy/insertOne-errorLabels.json deleted file mode 100644 index d90ac5dfbd..0000000000 --- a/test/spec/retryable-writes/legacy/insertOne-errorLabels.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.3.1", - "topology": [ - "replicaset", - "sharded", - "load-balanced" - ] - } - ], - "data": [], - "tests": [ - { - "description": "InsertOne succeeds with RetryableWriteError from server", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorCode": 112, - "errorLabels": [ - "RetryableWriteError" - ] - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 1, - "x": 11 - } - } - }, - "outcome": { - "result": { - "insertedId": 1 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - } - ] - } - } - }, - { - "description": "InsertOne fails if server does not return RetryableWriteError", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorCode": 11600, - "errorLabels": [] - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 1, - "x": 11 - } - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsOmit": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/insertOne-errorLabels.yml b/test/spec/retryable-writes/legacy/insertOne-errorLabels.yml deleted file mode 100644 index 87100aa5cf..0000000000 --- a/test/spec/retryable-writes/legacy/insertOne-errorLabels.yml +++ /dev/null @@ -1,44 +0,0 @@ -runOn: - - minServerVersion: "4.3.1" - topology: ["replicaset", "sharded", "load-balanced"] - -data: [] - -tests: - - description: "InsertOne succeeds with RetryableWriteError from server" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorCode: 112 # WriteConflict, not a retryable error code - errorLabels: ["RetryableWriteError"] # Override server behavior: send RetryableWriteError label with non-retryable error code - operation: - name: "insertOne" - arguments: - document: { _id: 1, x: 11 } - outcome: # Driver retries operation and it succeeds - result: - insertedId: 1 - collection: - data: - - { _id: 1, x: 11 } - - - description: "InsertOne fails if server does not return RetryableWriteError" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorCode: 11600 # InterruptedAtShutdown, normally a retryable error code - errorLabels: [] # Override server behavior: do not send RetryableWriteError label with retryable code - operation: - name: "insertOne" - arguments: - document: { _id: 1, x: 11 } - outcome: - error: true # Driver does not retry operation because there was no RetryableWriteError label on response - result: - errorLabelsOmit: ["RetryableWriteError"] - collection: - data: [] diff --git a/test/spec/retryable-writes/legacy/insertOne-serverErrors.json b/test/spec/retryable-writes/legacy/insertOne-serverErrors.json deleted file mode 100644 index 5179a6ab75..0000000000 --- a/test/spec/retryable-writes/legacy/insertOne-serverErrors.json +++ /dev/null @@ -1,1162 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "InsertOne succeeds after connection failure", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "closeConnection": true - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "result": { - "insertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne fails after connection failure when retryWrites option is false", - "clientOptions": { - "retryWrites": false - }, - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "closeConnection": true - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsOmit": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "InsertOne succeeds after NotWritablePrimary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorCode": 10107, - "errorLabels": [ - "RetryableWriteError" - ], - "closeConnection": false - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "result": { - "insertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne succeeds after NotPrimaryOrSecondary", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorCode": 13436, - "errorLabels": [ - "RetryableWriteError" - ], - "closeConnection": false - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "result": { - "insertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne succeeds after NotPrimaryNoSecondaryOk", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorCode": 13435, - "errorLabels": [ - "RetryableWriteError" - ], - "closeConnection": false - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "result": { - "insertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne succeeds after InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorCode": 11602, - "errorLabels": [ - "RetryableWriteError" - ], - "closeConnection": false - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "result": { - "insertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne succeeds after InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorCode": 11600, - "errorLabels": [ - "RetryableWriteError" - ], - "closeConnection": false - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "result": { - "insertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorCode": 189, - "errorLabels": [ - "RetryableWriteError" - ], - "closeConnection": false - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "result": { - "insertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne succeeds after ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorCode": 91, - "errorLabels": [ - "RetryableWriteError" - ], - "closeConnection": false - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "result": { - "insertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne succeeds after HostNotFound", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorCode": 7, - "errorLabels": [ - "RetryableWriteError" - ], - "closeConnection": false - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "result": { - "insertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne succeeds after HostUnreachable", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorCode": 6, - "errorLabels": [ - "RetryableWriteError" - ], - "closeConnection": false - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "result": { - "insertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne succeeds after SocketException", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorCode": 9001, - "errorLabels": [ - "RetryableWriteError" - ], - "closeConnection": false - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "result": { - "insertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne succeeds after NetworkTimeout", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorCode": 89, - "errorLabels": [ - "RetryableWriteError" - ], - "closeConnection": false - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "result": { - "insertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne succeeds after ExceededTimeLimit", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorCode": 262, - "errorLabels": [ - "RetryableWriteError" - ], - "closeConnection": false - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "result": { - "insertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne fails after Interrupted", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorCode": 11601, - "closeConnection": false - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsOmit": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "InsertOne succeeds after WriteConcernError InterruptedAtShutdown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorLabels": [ - "RetryableWriteError" - ], - "writeConcernError": { - "code": 11600, - "errmsg": "Replication is being shut down" - } - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "result": { - "insertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne succeeds after WriteConcernError InterruptedDueToReplStateChange", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorLabels": [ - "RetryableWriteError" - ], - "writeConcernError": { - "code": 11602, - "errmsg": "Replication is being shut down" - } - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "result": { - "insertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne succeeds after WriteConcernError PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorLabels": [ - "RetryableWriteError" - ], - "writeConcernError": { - "code": 189, - "errmsg": "Replication is being shut down" - } - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "result": { - "insertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne succeeds after WriteConcernError ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorLabels": [ - "RetryableWriteError" - ], - "writeConcernError": { - "code": 91, - "errmsg": "Replication is being shut down" - } - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "result": { - "insertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne fails after multiple retryable writeConcernErrors", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "insert" - ], - "errorLabels": [ - "RetryableWriteError" - ], - "writeConcernError": { - "code": 91, - "errmsg": "Replication is being shut down" - } - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsContain": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne fails after WriteConcernError Interrupted", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "writeConcernError": { - "code": 11601, - "errmsg": "operation was interrupted" - } - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsOmit": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne fails after WriteConcernError WriteConcernFailed", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "insert" - ], - "writeConcernError": { - "code": 64, - "codeName": "WriteConcernFailed", - "errmsg": "waiting for replication timed out", - "errInfo": { - "wtimeout": true - } - } - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsOmit": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne fails with a RetryableWriteError label after two connection failures", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "insert" - ], - "closeConnection": true - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsContain": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/insertOne-serverErrors.yml b/test/spec/retryable-writes/legacy/insertOne-serverErrors.yml deleted file mode 100644 index bfbd187742..0000000000 --- a/test/spec/retryable-writes/legacy/insertOne-serverErrors.yml +++ /dev/null @@ -1,527 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "InsertOne succeeds after connection failure" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - closeConnection: true - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - result: - insertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertOne fails after connection failure when retryWrites option is false" - clientOptions: - retryWrites: false - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - closeConnection: true - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - error: true - result: - # If retryWrites is false, the driver should not add the - # RetryableWriteError label to the error. - errorLabelsOmit: ["RetryableWriteError"] - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - - description: "InsertOne succeeds after NotWritablePrimary" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorCode: 10107 - errorLabels: ["RetryableWriteError"] - closeConnection: false - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - result: - insertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertOne succeeds after NotPrimaryOrSecondary" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorCode: 13436 - errorLabels: ["RetryableWriteError"] - closeConnection: false - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - result: - insertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertOne succeeds after NotPrimaryNoSecondaryOk" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorCode: 13435 - errorLabels: ["RetryableWriteError"] - closeConnection: false - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - result: - insertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertOne succeeds after InterruptedDueToReplStateChange" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorCode: 11602 - errorLabels: ["RetryableWriteError"] - closeConnection: false - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - result: - insertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertOne succeeds after InterruptedAtShutdown" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorCode: 11600 - errorLabels: ["RetryableWriteError"] - closeConnection: false - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - result: - insertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertOne succeeds after PrimarySteppedDown" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorCode: 189 - errorLabels: ["RetryableWriteError"] - closeConnection: false - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - result: - insertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertOne succeeds after ShutdownInProgress" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorCode: 91 - errorLabels: ["RetryableWriteError"] - closeConnection: false - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - result: - insertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertOne succeeds after HostNotFound" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorCode: 7 - errorLabels: ["RetryableWriteError"] - closeConnection: false - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - result: - insertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertOne succeeds after HostUnreachable" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorCode: 6 - errorLabels: ["RetryableWriteError"] - closeConnection: false - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - result: - insertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertOne succeeds after SocketException" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorCode: 9001 - errorLabels: ["RetryableWriteError"] - closeConnection: false - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - result: - insertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertOne succeeds after NetworkTimeout" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorCode: 89 - errorLabels: ["RetryableWriteError"] - closeConnection: false - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - result: - insertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertOne succeeds after ExceededTimeLimit" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorCode: 262 - errorLabels: ["RetryableWriteError"] - closeConnection: false - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - result: - insertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertOne fails after Interrupted" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorCode: 11601 - closeConnection: false - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - error: true - result: - errorLabelsOmit: ["RetryableWriteError"] - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - - description: "InsertOne succeeds after WriteConcernError InterruptedAtShutdown" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorLabels: ["RetryableWriteError"] - writeConcernError: - code: 11600 - errmsg: Replication is being shut down - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - result: - insertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertOne succeeds after WriteConcernError InterruptedDueToReplStateChange" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorLabels: ["RetryableWriteError"] - writeConcernError: - code: 11602 - errmsg: Replication is being shut down - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - result: - insertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertOne succeeds after WriteConcernError PrimarySteppedDown" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorLabels: ["RetryableWriteError"] - writeConcernError: - code: 189 - errmsg: Replication is being shut down - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - result: - insertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertOne succeeds after WriteConcernError ShutdownInProgress" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - errorLabels: ["RetryableWriteError"] - writeConcernError: - code: 91 - errmsg: Replication is being shut down - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - result: - insertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertOne fails after multiple retryable writeConcernErrors" - failPoint: - configureFailPoint: failCommand - mode: { times: 2 } - data: - failCommands: ["insert"] - errorLabels: ["RetryableWriteError"] - writeConcernError: - code: 91 - errmsg: Replication is being shut down - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - error: true - result: - errorLabelsContain: ["RetryableWriteError"] - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } # The write was still applied. - - - description: "InsertOne fails after WriteConcernError Interrupted" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - writeConcernError: - code: 11601 - errmsg: operation was interrupted - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - error: true - result: - errorLabelsOmit: ["RetryableWriteError"] - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } # The write was still applied. - - - description: "InsertOne fails after WriteConcernError WriteConcernFailed" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["insert"] - writeConcernError: - code: 64 - codeName: WriteConcernFailed - errmsg: waiting for replication timed out - errInfo: {wtimeout: True} - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - error: true - result: - errorLabelsOmit: ["RetryableWriteError"] - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } # The write was still applied. - - - - description: "InsertOne fails with a RetryableWriteError label after two connection failures" - failPoint: - configureFailPoint: failCommand - mode: { times: 2 } - data: - failCommands: ["insert"] - closeConnection: true - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - error: true - result: - errorLabelsContain: ["RetryableWriteError"] - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/legacy/insertOne.json b/test/spec/retryable-writes/legacy/insertOne.json deleted file mode 100644 index 04dee6dd68..0000000000 --- a/test/spec/retryable-writes/legacy/insertOne.json +++ /dev/null @@ -1,139 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "3.6", - "topology": [ - "replicaset" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "InsertOne is committed on first attempt", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "result": { - "insertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne is not committed on first attempt", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "result": { - "insertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } - } - }, - { - "description": "InsertOne is never committed", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 2 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "insertOne", - "arguments": { - "document": { - "_id": 3, - "x": 33 - } - } - }, - "outcome": { - "error": true, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/insertOne.yml b/test/spec/retryable-writes/legacy/insertOne.yml deleted file mode 100644 index ebfdf23e66..0000000000 --- a/test/spec/retryable-writes/legacy/insertOne.yml +++ /dev/null @@ -1,61 +0,0 @@ -runOn: - - - minServerVersion: "3.6" - topology: ["replicaset"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "InsertOne is committed on first attempt" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - result: - insertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertOne is not committed on first attempt" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - result: - insertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 33 } - - - description: "InsertOne is never committed" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 2 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "insertOne" - arguments: - document: { _id: 3, x: 33 } - outcome: - error: true - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/legacy/replaceOne-errorLabels.json b/test/spec/retryable-writes/legacy/replaceOne-errorLabels.json deleted file mode 100644 index 6029b875dc..0000000000 --- a/test/spec/retryable-writes/legacy/replaceOne-errorLabels.json +++ /dev/null @@ -1,121 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.3.1", - "topology": [ - "replicaset", - "sharded", - "load-balanced" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "ReplaceOne succeeds with RetryableWriteError from server", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "update" - ], - "errorCode": 112, - "errorLabels": [ - "RetryableWriteError" - ] - } - }, - "operation": { - "name": "replaceOne", - "arguments": { - "filter": { - "_id": 1 - }, - "replacement": { - "_id": 1, - "x": 111 - } - } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 111 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "ReplaceOne fails if server does not return RetryableWriteError", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "update" - ], - "errorCode": 11600, - "errorLabels": [] - } - }, - "operation": { - "name": "replaceOne", - "arguments": { - "filter": { - "_id": 1 - }, - "replacement": { - "_id": 1, - "x": 111 - } - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsOmit": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/replaceOne-errorLabels.yml b/test/spec/retryable-writes/legacy/replaceOne-errorLabels.yml deleted file mode 100644 index 4193909293..0000000000 --- a/test/spec/retryable-writes/legacy/replaceOne-errorLabels.yml +++ /dev/null @@ -1,53 +0,0 @@ -runOn: - - minServerVersion: "4.3.1" - topology: ["replicaset", "sharded", "load-balanced"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - description: "ReplaceOne succeeds with RetryableWriteError from server" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["update"] - errorCode: 112 # WriteConflict, not a retryable error code - errorLabels: ["RetryableWriteError"] # Override server behavior: send RetryableWriteError label with non-retryable error code - operation: - name: "replaceOne" - arguments: - filter: { _id: 1 } - replacement: { _id: 1, x: 111 } - outcome: # Driver retries operation and it succeeds - result: - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - collection: - data: - - { _id: 1, x: 111 } - - { _id: 2, x: 22 } - - - description: "ReplaceOne fails if server does not return RetryableWriteError" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["update"] - errorCode: 11600 # InterruptedAtShutdown, normally a retryable error code - errorLabels: [] # Override server behavior: do not send RetryableWriteError label with retryable code - operation: - name: "replaceOne" - arguments: - filter: { _id: 1 } - replacement: { _id: 1, x: 111 } - outcome: - error: true # Driver does not retry operation because there was no RetryableWriteError label on response - result: - errorLabelsOmit: ["RetryableWriteError"] - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/legacy/replaceOne-serverErrors.json b/test/spec/retryable-writes/legacy/replaceOne-serverErrors.json deleted file mode 100644 index 6b35722e12..0000000000 --- a/test/spec/retryable-writes/legacy/replaceOne-serverErrors.json +++ /dev/null @@ -1,177 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "ReplaceOne succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "update" - ], - "errorCode": 189, - "errorLabels": [ - "RetryableWriteError" - ] - } - }, - "operation": { - "name": "replaceOne", - "arguments": { - "filter": { - "_id": 1 - }, - "replacement": { - "_id": 1, - "x": 111 - } - } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 111 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "ReplaceOne succeeds after WriteConcernError ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "update" - ], - "errorLabels": [ - "RetryableWriteError" - ], - "writeConcernError": { - "code": 91, - "errmsg": "Replication is being shut down" - } - } - }, - "operation": { - "name": "replaceOne", - "arguments": { - "filter": { - "_id": 1 - }, - "replacement": { - "_id": 1, - "x": 111 - } - } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 111 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "ReplaceOne fails with a RetryableWriteError label after two connection failures", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "update" - ], - "closeConnection": true - } - }, - "operation": { - "name": "replaceOne", - "arguments": { - "filter": { - "_id": 1 - }, - "replacement": { - "_id": 1, - "x": 111 - } - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsContain": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/replaceOne-serverErrors.yml b/test/spec/retryable-writes/legacy/replaceOne-serverErrors.yml deleted file mode 100644 index 3dd79db750..0000000000 --- a/test/spec/retryable-writes/legacy/replaceOne-serverErrors.yml +++ /dev/null @@ -1,82 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "ReplaceOne succeeds after PrimarySteppedDown" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["update"] - errorCode: 189 - errorLabels: ["RetryableWriteError"] - operation: - name: "replaceOne" - arguments: - filter: { _id: 1 } - replacement: { _id: 1, x: 111 } - outcome: - result: - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - collection: - data: - - { _id: 1, x: 111 } - - { _id: 2, x: 22 } - - - description: "ReplaceOne succeeds after WriteConcernError ShutdownInProgress" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["update"] - errorLabels: ["RetryableWriteError"] - writeConcernError: - code: 91 - errmsg: Replication is being shut down - operation: - name: "replaceOne" - arguments: - filter: { _id: 1 } - replacement: { _id: 1, x: 111 } - outcome: - result: - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - collection: - data: - - { _id: 1, x: 111 } - - { _id: 2, x: 22 } - - - description: "ReplaceOne fails with a RetryableWriteError label after two connection failures" - failPoint: - configureFailPoint: failCommand - mode: { times: 2 } - data: - failCommands: ["update"] - closeConnection: true - operation: - name: "replaceOne" - arguments: - filter: { _id: 1 } - replacement: { _id: 1, x: 111 } - outcome: - error: true - result: - errorLabelsContain: ["RetryableWriteError"] - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/legacy/replaceOne.json b/test/spec/retryable-writes/legacy/replaceOne.json deleted file mode 100644 index e5b8cf8eab..0000000000 --- a/test/spec/retryable-writes/legacy/replaceOne.json +++ /dev/null @@ -1,144 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "3.6", - "topology": [ - "replicaset" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "ReplaceOne is committed on first attempt", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - } - }, - "operation": { - "name": "replaceOne", - "arguments": { - "filter": { - "_id": 1 - }, - "replacement": { - "_id": 1, - "x": 111 - } - } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 111 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "ReplaceOne is not committed on first attempt", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "replaceOne", - "arguments": { - "filter": { - "_id": 1 - }, - "replacement": { - "_id": 1, - "x": 111 - } - } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 111 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "ReplaceOne is never committed", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 2 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "replaceOne", - "arguments": { - "filter": { - "_id": 1 - }, - "replacement": { - "_id": 1, - "x": 111 - } - } - }, - "outcome": { - "error": true, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/replaceOne.yml b/test/spec/retryable-writes/legacy/replaceOne.yml deleted file mode 100644 index 0000904a40..0000000000 --- a/test/spec/retryable-writes/legacy/replaceOne.yml +++ /dev/null @@ -1,66 +0,0 @@ -runOn: - - - minServerVersion: "3.6" - topology: ["replicaset"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "ReplaceOne is committed on first attempt" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - operation: - name: "replaceOne" - arguments: - filter: { _id: 1 } - replacement: { _id: 1, x: 111 } - outcome: - result: - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - collection: - data: - - { _id: 1, x: 111 } - - { _id: 2, x: 22 } - - - description: "ReplaceOne is not committed on first attempt" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "replaceOne" - arguments: - filter: { _id: 1 } - replacement: { _id: 1, x: 111 } - outcome: - result: - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - collection: - data: - - { _id: 1, x: 111 } - - { _id: 2, x: 22 } - - - description: "ReplaceOne is never committed" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 2 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "replaceOne" - arguments: - filter: { _id: 1 } - replacement: { _id: 1, x: 111 } - outcome: - error: true - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/legacy/updateMany.json b/test/spec/retryable-writes/legacy/updateMany.json deleted file mode 100644 index 46fef73e74..0000000000 --- a/test/spec/retryable-writes/legacy/updateMany.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "3.6", - "topology": [ - "replicaset", - "sharded", - "load-balanced" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "UpdateMany ignores retryWrites", - "useMultipleMongoses": true, - "operation": { - "name": "updateMany", - "arguments": { - "filter": {}, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - "outcome": { - "result": { - "matchedCount": 2, - "modifiedCount": 2, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 12 - }, - { - "_id": 2, - "x": 23 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/updateMany.yml b/test/spec/retryable-writes/legacy/updateMany.yml deleted file mode 100644 index f3ab39faa3..0000000000 --- a/test/spec/retryable-writes/legacy/updateMany.yml +++ /dev/null @@ -1,27 +0,0 @@ -runOn: - - - minServerVersion: "3.6" - topology: ["replicaset", "sharded", "load-balanced"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "UpdateMany ignores retryWrites" - useMultipleMongoses: true - operation: - name: "updateMany" - arguments: - filter: { } - update: { $inc: { x : 1 }} - outcome: - result: - matchedCount: 2 - modifiedCount: 2 - upsertedCount: 0 - collection: - data: - - { _id: 1, x: 12 } - - { _id: 2, x: 23 } diff --git a/test/spec/retryable-writes/legacy/updateOne-errorLabels.json b/test/spec/retryable-writes/legacy/updateOne-errorLabels.json deleted file mode 100644 index 5bd00cde90..0000000000 --- a/test/spec/retryable-writes/legacy/updateOne-errorLabels.json +++ /dev/null @@ -1,123 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.3.1", - "topology": [ - "replicaset", - "sharded", - "load-balanced" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "UpdateOne succeeds with RetryableWriteError from server", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "update" - ], - "errorCode": 112, - "errorLabels": [ - "RetryableWriteError" - ] - } - }, - "operation": { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 12 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "UpdateOne fails if server does not return RetryableWriteError", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "update" - ], - "errorCode": 11600, - "errorLabels": [] - } - }, - "operation": { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsOmit": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/updateOne-errorLabels.yml b/test/spec/retryable-writes/legacy/updateOne-errorLabels.yml deleted file mode 100644 index 6bfef3b129..0000000000 --- a/test/spec/retryable-writes/legacy/updateOne-errorLabels.yml +++ /dev/null @@ -1,53 +0,0 @@ -runOn: - - minServerVersion: "4.3.1" - topology: ["replicaset", "sharded", "load-balanced"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - description: "UpdateOne succeeds with RetryableWriteError from server" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["update"] - errorCode: 112 # WriteConflict, not a retryable error code - errorLabels: ["RetryableWriteError"] # Override server behavior: send RetryableWriteError label with non-retryable error code - operation: - name: "updateOne" - arguments: - filter: { _id: 1 } - update: { $inc: { x: 1 } } - outcome: # Driver retries operation and it succeeds - result: - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - collection: - data: - - { _id: 1, x: 12 } - - { _id: 2, x: 22 } - - - description: "UpdateOne fails if server does not return RetryableWriteError" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["update"] - errorCode: 11600 # InterruptedAtShutdown, normally a retryable error code - errorLabels: [] # Override server behavior: do not send RetryableWriteError label with retryable code - operation: - name: "updateOne" - arguments: - filter: { _id: 1 } - update: { $inc: { x: 1 } } - outcome: - error: true # Driver does not retry operation because there was no RetryableWriteError label on response - result: - errorLabelsOmit: ["RetryableWriteError"] - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/legacy/updateOne-serverErrors.json b/test/spec/retryable-writes/legacy/updateOne-serverErrors.json deleted file mode 100644 index cf274f57e0..0000000000 --- a/test/spec/retryable-writes/legacy/updateOne-serverErrors.json +++ /dev/null @@ -1,180 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "4.0", - "topology": [ - "replicaset" - ] - }, - { - "minServerVersion": "4.1.7", - "topology": [ - "sharded", - "load-balanced" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "UpdateOne succeeds after PrimarySteppedDown", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "update" - ], - "errorCode": 189, - "errorLabels": [ - "RetryableWriteError" - ] - } - }, - "operation": { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 12 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "UpdateOne succeeds after WriteConcernError ShutdownInProgress", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 1 - }, - "data": { - "failCommands": [ - "update" - ], - "errorLabels": [ - "RetryableWriteError" - ], - "writeConcernError": { - "code": 91, - "errmsg": "Replication is being shut down" - } - } - }, - "operation": { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 12 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "UpdateOne fails with a RetryableWriteError label after two connection failures", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "update" - ], - "closeConnection": true - } - }, - "operation": { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - "outcome": { - "error": true, - "result": { - "errorLabelsContain": [ - "RetryableWriteError" - ] - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/updateOne-serverErrors.yml b/test/spec/retryable-writes/legacy/updateOne-serverErrors.yml deleted file mode 100644 index fffe851cae..0000000000 --- a/test/spec/retryable-writes/legacy/updateOne-serverErrors.yml +++ /dev/null @@ -1,82 +0,0 @@ -runOn: - - - minServerVersion: "4.0" - topology: ["replicaset"] - - - minServerVersion: "4.1.7" - topology: ["sharded", "load-balanced"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "UpdateOne succeeds after PrimarySteppedDown" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["update"] - errorCode: 189 - errorLabels: ["RetryableWriteError"] - operation: - name: "updateOne" - arguments: - filter: { _id: 1 } - update: { $inc: { x : 1 }} - outcome: - result: - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - collection: - data: - - { _id: 1, x: 12 } - - { _id: 2, x: 22 } - - - description: "UpdateOne succeeds after WriteConcernError ShutdownInProgress" - failPoint: - configureFailPoint: failCommand - mode: { times: 1 } - data: - failCommands: ["update"] - errorLabels: ["RetryableWriteError"] - writeConcernError: - code: 91 - errmsg: Replication is being shut down - operation: - name: "updateOne" - arguments: - filter: { _id: 1 } - update: { $inc: { x : 1 }} - outcome: - result: - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - collection: - data: - - { _id: 1, x: 12 } - - { _id: 2, x: 22 } - - - description: "UpdateOne fails with a RetryableWriteError label after two connection failures" - failPoint: - configureFailPoint: failCommand - mode: { times: 2 } - data: - failCommands: ["update"] - closeConnection: true - operation: - name: "updateOne" - arguments: - filter: { _id: 1 } - update: { $inc: { x: 1 } } - outcome: - error: true - result: - errorLabelsContain: ["RetryableWriteError"] - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/legacy/updateOne.json b/test/spec/retryable-writes/legacy/updateOne.json deleted file mode 100644 index 0f806dc3d8..0000000000 --- a/test/spec/retryable-writes/legacy/updateOne.json +++ /dev/null @@ -1,288 +0,0 @@ -{ - "runOn": [ - { - "minServerVersion": "3.6", - "topology": [ - "replicaset" - ] - } - ], - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ], - "tests": [ - { - "description": "UpdateOne is committed on first attempt", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - } - }, - "operation": { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 12 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "UpdateOne is not committed on first attempt", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - "outcome": { - "result": { - "matchedCount": 1, - "modifiedCount": 1, - "upsertedCount": 0 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 12 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "UpdateOne is never committed", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 2 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 1 - }, - "update": { - "$inc": { - "x": 1 - } - } - } - }, - "outcome": { - "error": true, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - }, - { - "description": "UpdateOne with upsert is committed on first attempt", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - } - }, - "operation": { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 3, - "x": 33 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "upsert": true - } - }, - "outcome": { - "result": { - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 1, - "upsertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 34 - } - ] - } - } - }, - { - "description": "UpdateOne with upsert is not committed on first attempt", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 1 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 3, - "x": 33 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "upsert": true - } - }, - "outcome": { - "result": { - "matchedCount": 0, - "modifiedCount": 0, - "upsertedCount": 1, - "upsertedId": 3 - }, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 34 - } - ] - } - } - }, - { - "description": "UpdateOne with upsert is never committed", - "failPoint": { - "configureFailPoint": "onPrimaryTransactionalWrite", - "mode": { - "times": 2 - }, - "data": { - "failBeforeCommitExceptionCode": 1 - } - }, - "operation": { - "name": "updateOne", - "arguments": { - "filter": { - "_id": 3, - "x": 33 - }, - "update": { - "$inc": { - "x": 1 - } - }, - "upsert": true - } - }, - "outcome": { - "error": true, - "collection": { - "data": [ - { - "_id": 1, - "x": 11 - }, - { - "_id": 2, - "x": 22 - } - ] - } - } - } - ] -} diff --git a/test/spec/retryable-writes/legacy/updateOne.yml b/test/spec/retryable-writes/legacy/updateOne.yml deleted file mode 100644 index 56b7d822b4..0000000000 --- a/test/spec/retryable-writes/legacy/updateOne.yml +++ /dev/null @@ -1,129 +0,0 @@ -runOn: - - - minServerVersion: "3.6" - topology: ["replicaset"] - -data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - -tests: - - - description: "UpdateOne is committed on first attempt" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - operation: - name: "updateOne" - arguments: - filter: { _id: 1 } - update: { $inc: { x : 1 }} - outcome: - result: - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - collection: - data: - - { _id: 1, x: 12 } - - { _id: 2, x: 22 } - - - description: "UpdateOne is not committed on first attempt" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "updateOne" - arguments: - filter: { _id: 1 } - update: { $inc: { x : 1 }} - outcome: - result: - matchedCount: 1 - modifiedCount: 1 - upsertedCount: 0 - collection: - data: - - { _id: 1, x: 12 } - - { _id: 2, x: 22 } - - - description: "UpdateOne is never committed" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 2 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "updateOne" - arguments: - filter: { _id: 1 } - update: { $inc: { x : 1 }} - outcome: - error: true - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - - description: "UpdateOne with upsert is committed on first attempt" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - operation: - name: "updateOne" - arguments: - filter: { _id: 3, x: 33 } - update: { $inc: { x : 1 }} - upsert: true - outcome: - result: - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 1 - upsertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 34 } - - - description: "UpdateOne with upsert is not committed on first attempt" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 1 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "updateOne" - arguments: - filter: { _id: 3, x: 33 } - update: { $inc: { x : 1 }} - upsert: true - outcome: - result: - matchedCount: 0 - modifiedCount: 0 - upsertedCount: 1 - upsertedId: 3 - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } - - { _id: 3, x: 34 } - - - description: "UpdateOne with upsert is never committed" - failPoint: - configureFailPoint: onPrimaryTransactionalWrite - mode: { times: 2 } - data: { failBeforeCommitExceptionCode: 1 } - operation: - name: "updateOne" - arguments: - filter: { _id: 3, x: 33 } - update: { $inc: { x : 1 }} - upsert: true - outcome: - error: true - collection: - data: - - { _id: 1, x: 11 } - - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/bulkWrite-errorLabels.json b/test/spec/retryable-writes/unified/bulkWrite-errorLabels.json new file mode 100644 index 0000000000..13ba9bae75 --- /dev/null +++ b/test/spec/retryable-writes/unified/bulkWrite-errorLabels.json @@ -0,0 +1,416 @@ +{ + "description": "bulkWrite-errorLabels", + "schemaVersion": "1.3", + "runOnRequirements": [ + { + "minServerVersion": "4.3.1", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "BulkWrite succeeds with RetryableWriteError from server", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "update" + ], + "errorCode": 112, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "deleteOne": { + "filter": { + "_id": 1 + } + } + }, + { + "insertOne": { + "document": { + "_id": 3, + "x": 33 + } + } + }, + { + "updateOne": { + "filter": { + "_id": 2 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + } + ], + "ordered": true + }, + "expectResult": { + "deletedCount": 1, + "insertedCount": 1, + "insertedIds": { + "$$unsetOrMatches": { + "1": 3 + } + }, + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0, + "upsertedIds": {} + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 2, + "x": 23 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "BulkWrite fails if server does not return RetryableWriteError", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "update" + ], + "errorCode": 11600, + "errorLabels": [] + } + } + } + }, + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "deleteOne": { + "filter": { + "_id": 1 + } + } + }, + { + "insertOne": { + "document": { + "_id": 3, + "x": 33 + } + } + }, + { + "updateOne": { + "filter": { + "_id": 2 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + } + ], + "ordered": true + }, + "expectError": { + "isError": true, + "errorLabelsOmit": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "BulkWrite succeeds after PrimarySteppedDown", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "update" + ], + "errorCode": 189, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "deleteOne": { + "filter": { + "_id": 1 + } + } + }, + { + "insertOne": { + "document": { + "_id": 3, + "x": 33 + } + } + }, + { + "updateOne": { + "filter": { + "_id": 2 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + } + ], + "ordered": true + }, + "expectResult": { + "deletedCount": 1, + "insertedCount": 1, + "insertedIds": { + "$$unsetOrMatches": { + "1": 3 + } + }, + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0, + "upsertedIds": {} + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 2, + "x": 23 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "BulkWrite succeeds after WriteConcernError ShutdownInProgress", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorLabels": [ + "RetryableWriteError" + ], + "writeConcernError": { + "code": 91, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "deleteOne": { + "filter": { + "_id": 1 + } + } + }, + { + "insertOne": { + "document": { + "_id": 3, + "x": 33 + } + } + }, + { + "updateOne": { + "filter": { + "_id": 2 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + } + ], + "ordered": true + }, + "expectResult": { + "deletedCount": 1, + "insertedCount": 1, + "insertedIds": { + "$$unsetOrMatches": { + "1": 3 + } + }, + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0, + "upsertedIds": {} + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 2, + "x": 23 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/bulkWrite-errorLabels.yml b/test/spec/retryable-writes/unified/bulkWrite-errorLabels.yml new file mode 100644 index 0000000000..9adec6de71 --- /dev/null +++ b/test/spec/retryable-writes/unified/bulkWrite-errorLabels.yml @@ -0,0 +1,222 @@ +description: bulkWrite-errorLabels + +schemaVersion: '1.3' + +runOnRequirements: + - + minServerVersion: 4.3.1 # failCommand errorLabels option + topologies: [ replicaset, sharded, load-balanced ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'BulkWrite succeeds with RetryableWriteError from server' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ update ] + errorCode: 112 # WriteConflict, not a retryable error code + # Override server behavior: send RetryableWriteError label with non-retryable error code + errorLabels: + - RetryableWriteError + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + deleteOne: + filter: { _id: 1 } + - + insertOne: + document: { _id: 3, x: 33 } + - + updateOne: + filter: { _id: 2 } + update: { $inc: { x: 1 } } + ordered: true + # Driver retries operation and it succeeds + expectResult: + deletedCount: 1 + insertedCount: 1 + insertedIds: { $$unsetOrMatches: { '1': 3 } } + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 23 } + - { _id: 3, x: 33 } + - + description: 'BulkWrite fails if server does not return RetryableWriteError' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ update ] + errorCode: 11600 # InterruptedAtShutdown, normally a retryable error code + errorLabels: [] # Override server behavior: do not send RetryableWriteError label with retryable code + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + deleteOne: + filter: { _id: 1 } + - + insertOne: + document: { _id: 3, x: 33 } + - + updateOne: + filter: { _id: 2 } + update: { $inc: { x: 1 } } + ordered: true + # Driver does not retry operation because there was no RetryableWriteError label on response + expectError: + isError: true + errorLabelsOmit: + - RetryableWriteError + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'BulkWrite succeeds after PrimarySteppedDown' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ update ] + errorCode: 189 + errorLabels: + - RetryableWriteError + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + deleteOne: + filter: { _id: 1 } + - + insertOne: + document: { _id: 3, x: 33 } + - + updateOne: + filter: { _id: 2 } + update: { $inc: { x: 1 } } + ordered: true + expectResult: + deletedCount: 1 + insertedCount: 1 + insertedIds: { $$unsetOrMatches: { '1': 3 } } + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 23 } + - { _id: 3, x: 33 } + - + description: 'BulkWrite succeeds after WriteConcernError ShutdownInProgress' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorLabels: + - RetryableWriteError + writeConcernError: + code: 91 + errmsg: 'Replication is being shut down' + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + deleteOne: + filter: { _id: 1 } + - + insertOne: + document: { _id: 3, x: 33 } + - + updateOne: + filter: { _id: 2 } + update: { $inc: { x: 1 } } + ordered: true + expectResult: + deletedCount: 1 + insertedCount: 1 + insertedIds: { $$unsetOrMatches: { '1': 3 } } + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 23 } + - { _id: 3, x: 33 } diff --git a/test/spec/retryable-writes/unified/bulkWrite-serverErrors.json b/test/spec/retryable-writes/unified/bulkWrite-serverErrors.json index 737a1555e8..0a063ab4d9 100644 --- a/test/spec/retryable-writes/unified/bulkWrite-serverErrors.json +++ b/test/spec/retryable-writes/unified/bulkWrite-serverErrors.json @@ -1,6 +1,6 @@ { "description": "retryable-writes bulkWrite serverErrors", - "schemaVersion": "1.0", + "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.0", @@ -11,7 +11,8 @@ { "minServerVersion": "4.1.7", "topologies": [ - "sharded" + "sharded", + "load-balanced" ] } ], @@ -197,6 +198,88 @@ ] } ] + }, + { + "description": "BulkWrite fails with a RetryableWriteError label after two connection failures", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "update" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "deleteOne": { + "filter": { + "_id": 1 + } + } + }, + { + "insertOne": { + "document": { + "_id": 3, + "x": 33 + } + } + }, + { + "updateOne": { + "filter": { + "_id": 2 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + } + ], + "ordered": true + }, + "expectError": { + "isError": true, + "errorLabelsContain": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] } ] } diff --git a/test/spec/retryable-writes/unified/bulkWrite-serverErrors.yml b/test/spec/retryable-writes/unified/bulkWrite-serverErrors.yml index 332dd5aae8..a88a206123 100644 --- a/test/spec/retryable-writes/unified/bulkWrite-serverErrors.yml +++ b/test/spec/retryable-writes/unified/bulkWrite-serverErrors.yml @@ -1,12 +1,12 @@ description: "retryable-writes bulkWrite serverErrors" -schemaVersion: "1.0" +schemaVersion: "1.3" runOnRequirements: - minServerVersion: "4.0" topologies: [ replicaset ] - minServerVersion: "4.1.7" - topologies: [ sharded ] + topologies: [ sharded, load-balanced ] createEntities: - client: @@ -93,3 +93,44 @@ tests: documents: - { _id: 1, x: 11 } - { _id: 3, x: 33 } # The write was still applied + - + description: 'BulkWrite fails with a RetryableWriteError label after two connection failures' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ update ] + closeConnection: true + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + deleteOne: + filter: { _id: 1 } + - + insertOne: + document: { _id: 3, x: 33 } + - + updateOne: + filter: { _id: 2 } + update: { $inc: { x: 1 } } + ordered: true + expectError: + isError: true + errorLabelsContain: + - RetryableWriteError + outcome: + - + collectionName: *collectionName + databaseName: *databaseName + documents: + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } diff --git a/test/spec/retryable-writes/unified/bulkWrite.json b/test/spec/retryable-writes/unified/bulkWrite.json new file mode 100644 index 0000000000..691321746b --- /dev/null +++ b/test/spec/retryable-writes/unified/bulkWrite.json @@ -0,0 +1,931 @@ +{ + "description": "bulkWrite", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "3.6", + "topologies": [ + "replicaset" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ], + "tests": [ + { + "description": "First command is retried", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + } + } + } + }, + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "insertOne": { + "document": { + "_id": 2, + "x": 22 + } + } + }, + { + "updateOne": { + "filter": { + "_id": 2 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "deleteOne": { + "filter": { + "_id": 1 + } + } + } + ], + "ordered": true + }, + "expectResult": { + "deletedCount": 1, + "insertedCount": 1, + "insertedIds": { + "$$unsetOrMatches": { + "0": 2 + } + }, + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0, + "upsertedIds": {} + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 2, + "x": 23 + } + ] + } + ] + }, + { + "description": "All commands are retried", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 7 + } + } + } + }, + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "insertOne": { + "document": { + "_id": 2, + "x": 22 + } + } + }, + { + "updateOne": { + "filter": { + "_id": 2 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "insertOne": { + "document": { + "_id": 3, + "x": 33 + } + } + }, + { + "updateOne": { + "filter": { + "_id": 4, + "x": 44 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "upsert": true + } + }, + { + "insertOne": { + "document": { + "_id": 5, + "x": 55 + } + } + }, + { + "replaceOne": { + "filter": { + "_id": 3 + }, + "replacement": { + "_id": 3, + "x": 333 + } + } + }, + { + "deleteOne": { + "filter": { + "_id": 1 + } + } + } + ], + "ordered": true + }, + "expectResult": { + "deletedCount": 1, + "insertedCount": 3, + "insertedIds": { + "$$unsetOrMatches": { + "0": 2, + "2": 3, + "4": 5 + } + }, + "matchedCount": 2, + "modifiedCount": 2, + "upsertedCount": 1, + "upsertedIds": { + "3": 4 + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 2, + "x": 23 + }, + { + "_id": 3, + "x": 333 + }, + { + "_id": 4, + "x": 45 + }, + { + "_id": 5, + "x": 55 + } + ] + } + ] + }, + { + "description": "Both commands are retried after their first statement fails", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 2 + } + } + } + }, + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "insertOne": { + "document": { + "_id": 2, + "x": 22 + } + } + }, + { + "updateOne": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "updateOne": { + "filter": { + "_id": 2 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + } + ], + "ordered": true + }, + "expectResult": { + "deletedCount": 0, + "insertedCount": 1, + "insertedIds": { + "$$unsetOrMatches": { + "0": 2 + } + }, + "matchedCount": 2, + "modifiedCount": 2, + "upsertedCount": 0, + "upsertedIds": {} + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 23 + } + ] + } + ] + }, + { + "description": "Second command is retried after its second statement fails", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "skip": 2 + } + } + } + }, + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "insertOne": { + "document": { + "_id": 2, + "x": 22 + } + } + }, + { + "updateOne": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "updateOne": { + "filter": { + "_id": 2 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + } + ], + "ordered": true + }, + "expectResult": { + "deletedCount": 0, + "insertedCount": 1, + "insertedIds": { + "$$unsetOrMatches": { + "0": 2 + } + }, + "matchedCount": 2, + "modifiedCount": 2, + "upsertedCount": 0, + "upsertedIds": {} + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 23 + } + ] + } + ] + }, + { + "description": "BulkWrite with unordered execution", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + } + } + } + }, + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "insertOne": { + "document": { + "_id": 2, + "x": 22 + } + } + }, + { + "insertOne": { + "document": { + "_id": 3, + "x": 33 + } + } + } + ], + "ordered": false + }, + "expectResult": { + "deletedCount": 0, + "insertedCount": 2, + "insertedIds": { + "$$unsetOrMatches": { + "0": 2, + "1": 3 + } + }, + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 0, + "upsertedIds": {} + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "First insertOne is never committed", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 2 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "insertOne": { + "document": { + "_id": 2, + "x": 22 + } + } + }, + { + "updateOne": { + "filter": { + "_id": 2 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "deleteOne": { + "filter": { + "_id": 1 + } + } + } + ], + "ordered": true + }, + "expectError": { + "isError": true, + "expectResult": { + "deletedCount": 0, + "insertedCount": 0, + "insertedIds": { + "$$unsetOrMatches": {} + }, + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 0, + "upsertedIds": {} + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "Second updateOne is never committed", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "skip": 1 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "insertOne": { + "document": { + "_id": 2, + "x": 22 + } + } + }, + { + "updateOne": { + "filter": { + "_id": 2 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "deleteOne": { + "filter": { + "_id": 1 + } + } + } + ], + "ordered": true + }, + "expectError": { + "isError": true, + "expectResult": { + "deletedCount": 0, + "insertedCount": 1, + "insertedIds": { + "$$unsetOrMatches": { + "0": 2 + } + }, + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 0, + "upsertedIds": {} + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "Third updateOne is never committed", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "skip": 2 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "updateOne": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "insertOne": { + "document": { + "_id": 2, + "x": 22 + } + } + }, + { + "updateOne": { + "filter": { + "_id": 2 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + } + ], + "ordered": true + }, + "expectError": { + "isError": true, + "expectResult": { + "deletedCount": 0, + "insertedCount": 1, + "insertedIds": { + "$$unsetOrMatches": { + "1": 2 + } + }, + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0, + "upsertedIds": {} + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "Single-document write following deleteMany is retried", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "deleteMany": { + "filter": { + "x": 11 + } + } + }, + { + "insertOne": { + "document": { + "_id": 2, + "x": 22 + } + } + } + ], + "ordered": true + }, + "expectResult": { + "deletedCount": 1, + "insertedCount": 1, + "insertedIds": { + "$$unsetOrMatches": { + "1": 2 + } + }, + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 0, + "upsertedIds": {} + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "Single-document write following updateMany is retried", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "updateMany": { + "filter": { + "x": 11 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "insertOne": { + "document": { + "_id": 2, + "x": 22 + } + } + } + ], + "ordered": true + }, + "expectResult": { + "deletedCount": 0, + "insertedCount": 1, + "insertedIds": { + "$$unsetOrMatches": { + "1": 2 + } + }, + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0, + "upsertedIds": {} + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/bulkWrite.yml b/test/spec/retryable-writes/unified/bulkWrite.yml new file mode 100644 index 0000000000..d064c9dbc5 --- /dev/null +++ b/test/spec/retryable-writes/unified/bulkWrite.yml @@ -0,0 +1,495 @@ +description: bulkWrite + +schemaVersion: '1.0' + +runOnRequirements: + - + minServerVersion: '3.6' + topologies: [ replicaset ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + +tests: + - + description: 'First command is retried' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + insertOne: + document: { _id: 2, x: 22 } + - + updateOne: + filter: { _id: 2 } + update: { $inc: { x: 1 } } + - + deleteOne: + filter: { _id: 1 } + ordered: true + expectResult: + deletedCount: 1 + insertedCount: 1 + insertedIds: { $$unsetOrMatches: { '0': 2 } } + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 23 } + - + # Write operations in this ordered batch are intentionally sequenced so that + # each write command consists of a single statement, which will fail on the + # first attempt and succeed on the second, retry attempt. + description: 'All commands are retried' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 7 } + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + insertOne: + document: { _id: 2, x: 22 } + - + updateOne: + filter: { _id: 2 } + update: { $inc: { x: 1 } } + - + insertOne: + document: { _id: 3, x: 33 } + - + updateOne: + filter: { _id: 4, x: 44 } + update: { $inc: { x: 1 } } + upsert: true + - + insertOne: + document: { _id: 5, x: 55 } + - + replaceOne: + filter: { _id: 3 } + replacement: { _id: 3, x: 333 } + - + deleteOne: + filter: { _id: 1 } + ordered: true + expectResult: + deletedCount: 1 + insertedCount: 3 + insertedIds: + $$unsetOrMatches: + '0': 2 + '2': 3 + '4': 5 + matchedCount: 2 + modifiedCount: 2 + upsertedCount: 1 + upsertedIds: { '3': 4 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 23 } + - { _id: 3, x: 333 } + - { _id: 4, x: 45 } + - { _id: 5, x: 55 } + - + description: 'Both commands are retried after their first statement fails' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 2 } + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + insertOne: + document: { _id: 2, x: 22 } + - + updateOne: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + - + updateOne: + filter: { _id: 2 } + update: { $inc: { x: 1 } } + ordered: true + expectResult: + deletedCount: 0 + insertedCount: 1 + insertedIds: { $$unsetOrMatches: { '0': 2 } } + matchedCount: 2 + modifiedCount: 2 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 23 } + - + description: 'Second command is retried after its second statement fails' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { skip: 2 } + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + insertOne: + document: { _id: 2, x: 22 } + - + updateOne: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + - + updateOne: + filter: { _id: 2 } + update: { $inc: { x: 1 } } + ordered: true + expectResult: + deletedCount: 0 + insertedCount: 1 + insertedIds: { $$unsetOrMatches: { '0': 2 } } + matchedCount: 2 + modifiedCount: 2 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 23 } + - + description: 'BulkWrite with unordered execution' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + insertOne: + document: { _id: 2, x: 22 } + - + insertOne: + document: { _id: 3, x: 33 } + ordered: false + expectResult: + deletedCount: 0 + insertedCount: 2 + insertedIds: + $$unsetOrMatches: + '0': 2 + '1': 3 + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'First insertOne is never committed' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 2 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + insertOne: + document: { _id: 2, x: 22 } + - + updateOne: + filter: { _id: 2 } + update: { $inc: { x: 1 } } + - + deleteOne: + filter: { _id: 1 } + ordered: true + expectError: + isError: true + expectResult: + deletedCount: 0 + insertedCount: 0 + insertedIds: + $$unsetOrMatches: { } + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'Second updateOne is never committed' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { skip: 1 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + insertOne: + document: { _id: 2, x: 22 } + - + updateOne: + filter: { _id: 2 } + update: { $inc: { x: 1 } } + - + deleteOne: + filter: { _id: 1 } + ordered: true + expectError: + isError: true + expectResult: + deletedCount: 0 + insertedCount: 1 + insertedIds: { $$unsetOrMatches: { '0': 2 } } + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - + description: 'Third updateOne is never committed' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { skip: 2 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + updateOne: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + - + insertOne: + document: { _id: 2, x: 22 } + - + updateOne: + filter: { _id: 2 } + update: { $inc: { x: 1 } } + ordered: true + expectError: + isError: true + expectResult: + deletedCount: 0 + insertedCount: 1 + insertedIds: { $$unsetOrMatches: { '1': 2 } } + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 22 } + - + # The onPrimaryTransactionalWrite fail point only triggers for write + # operations that include a transaction ID. Therefore, it will not affect + # the initial deleteMany and will trigger once (and only once) for the first + # insertOne attempt. + description: 'Single-document write following deleteMany is retried' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + deleteMany: + filter: { x: 11 } + - + insertOne: + document: { _id: 2, x: 22 } + ordered: true + expectResult: + deletedCount: 1 + insertedCount: 1 + insertedIds: { $$unsetOrMatches: { '1': 2 } } + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 22 } + - + # The onPrimaryTransactionalWrite fail point only triggers for write + # operations that include a transaction ID. Therefore, it will not affect + # the initial updateMany and will trigger once (and only once) for the first + # insertOne attempt. + description: 'Single-document write following updateMany is retried' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: bulkWrite + arguments: + requests: + - + updateMany: + filter: { x: 11 } + update: { $inc: { x: 1 } } + - + insertOne: + document: { _id: 2, x: 22 } + ordered: true + expectResult: + deletedCount: 0 + insertedCount: 1 + insertedIds: { $$unsetOrMatches: { '1': 2 } } + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + upsertedIds: { } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/client-bulkWrite-clientErrors.json b/test/spec/retryable-writes/unified/client-bulkWrite-clientErrors.json new file mode 100644 index 0000000000..e2c0fb9c0a --- /dev/null +++ b/test/spec/retryable-writes/unified/client-bulkWrite-clientErrors.json @@ -0,0 +1,350 @@ +{ + "description": "client bulkWrite retryable writes with client errors", + "schemaVersion": "1.21", + "runOnRequirements": [ + { + "minServerVersion": "8.0", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ], + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "_yamlAnchors": { + "namespace": "retryable-writes-tests.coll0" + }, + "tests": [ + { + "description": "client bulkWrite with one network error succeeds after retry", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "closeConnection": true + } + } + } + }, + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "retryable-writes-tests.coll0", + "document": { + "_id": 4, + "x": 44 + } + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 4 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 4, + "x": 44 + } + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ], + "lsid": { + "$$exists": true + }, + "txnNumber": { + "$$exists": true + } + } + } + }, + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 4, + "x": 44 + } + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ], + "lsid": { + "$$exists": true + }, + "txnNumber": { + "$$exists": true + } + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ] + }, + { + "description": "client bulkWrite with two network errors fails after retry", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "closeConnection": true + } + } + } + }, + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "retryable-writes-tests.coll0", + "document": { + "_id": 4, + "x": 44 + } + } + } + ], + "verboseResults": true + }, + "expectError": { + "isClientError": true, + "errorLabelsContain": [ + "RetryableWriteError" + ] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 4, + "x": 44 + } + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ], + "lsid": { + "$$exists": true + }, + "txnNumber": { + "$$exists": true + } + } + } + }, + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 4, + "x": 44 + } + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ], + "lsid": { + "$$exists": true + }, + "txnNumber": { + "$$exists": true + } + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/client-bulkWrite-clientErrors.yml b/test/spec/retryable-writes/unified/client-bulkWrite-clientErrors.yml new file mode 100644 index 0000000000..85696e89db --- /dev/null +++ b/test/spec/retryable-writes/unified/client-bulkWrite-clientErrors.yml @@ -0,0 +1,172 @@ +description: "client bulkWrite retryable writes with client errors" +schemaVersion: "1.21" +runOnRequirements: + - minServerVersion: "8.0" + topologies: + - replicaset + - sharded + - load-balanced + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + useMultipleMongoses: false + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name retryable-writes-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +_yamlAnchors: + namespace: &namespace "retryable-writes-tests.coll0" + +tests: + - description: "client bulkWrite with one network error succeeds after retry" + operations: + - object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: [ bulkWrite ] + closeConnection: true + - object: *client0 + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *namespace + document: { _id: 4, x: 44 } + verboseResults: true + expectResult: + insertedCount: 1 + upsertedCount: 0 + matchedCount: 0 + modifiedCount: 0 + deletedCount: 0 + insertResults: + 0: + insertedId: 4 + updateResults: {} + deleteResults: {} + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + ops: + - insert: 0 + document: { _id: 4, x: 44 } + nsInfo: + - ns: *namespace + # An implicit session is included with the transaction number: + lsid: { "$$exists": true } + txnNumber: { "$$exists": true } + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + ops: + - insert: 0 + document: { _id: 4, x: 44 } + nsInfo: + - ns: *namespace + # An implicit session is included with the transaction number: + lsid: { "$$exists": true } + txnNumber: { "$$exists": true } + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - { _id: 4, x: 44 } + - description: "client bulkWrite with two network errors fails after retry" + operations: + - object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 2 + data: + failCommands: [ bulkWrite ] + closeConnection: true + - object: *client0 + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *namespace + document: { _id: 4, x: 44 } + verboseResults: true + expectError: + isClientError: true + errorLabelsContain: ["RetryableWriteError"] # Error label added by driver. + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + ops: + - insert: 0 + document: { _id: 4, x: 44 } + nsInfo: + - ns: *namespace + # An implicit session is included with the transaction number: + lsid: { "$$exists": true } + txnNumber: { "$$exists": true } + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + ops: + - insert: 0 + document: { _id: 4, x: 44 } + nsInfo: + - ns: *namespace + # An implicit session is included with the transaction number: + lsid: { "$$exists": true } + txnNumber: { "$$exists": true } + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } diff --git a/test/spec/retryable-writes/unified/client-bulkWrite-serverErrors.json b/test/spec/retryable-writes/unified/client-bulkWrite-serverErrors.json new file mode 100644 index 0000000000..4a0b210eb5 --- /dev/null +++ b/test/spec/retryable-writes/unified/client-bulkWrite-serverErrors.json @@ -0,0 +1,872 @@ +{ + "description": "client bulkWrite retryable writes", + "schemaVersion": "1.21", + "runOnRequirements": [ + { + "minServerVersion": "8.0", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ], + "useMultipleMongoses": false + } + }, + { + "client": { + "id": "clientRetryWritesFalse", + "uriOptions": { + "retryWrites": false + }, + "observeEvents": [ + "commandStartedEvent" + ], + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "_yamlAnchors": { + "namespace": "retryable-writes-tests.coll0" + }, + "tests": [ + { + "description": "client bulkWrite with no multi: true operations succeeds after retryable top-level error", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "errorCode": 189, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "retryable-writes-tests.coll0", + "document": { + "_id": 4, + "x": 44 + } + } + }, + { + "updateOne": { + "namespace": "retryable-writes-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "replaceOne": { + "namespace": "retryable-writes-tests.coll0", + "filter": { + "_id": 2 + }, + "replacement": { + "x": 222 + } + } + }, + { + "deleteOne": { + "namespace": "retryable-writes-tests.coll0", + "filter": { + "_id": 3 + } + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 2, + "modifiedCount": 2, + "deletedCount": 1, + "insertResults": { + "0": { + "insertedId": 4 + } + }, + "updateResults": { + "1": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + }, + "2": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + } + }, + "deleteResults": { + "3": { + "deletedCount": 1 + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 4, + "x": 44 + } + }, + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": false + }, + { + "update": 0, + "filter": { + "_id": 2 + }, + "updateMods": { + "x": 222 + }, + "multi": false + }, + { + "delete": 0, + "filter": { + "_id": 3 + }, + "multi": false + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ], + "lsid": { + "$$exists": true + }, + "txnNumber": { + "$$exists": true + } + } + } + }, + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 4, + "x": 44 + } + }, + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": false + }, + { + "update": 0, + "filter": { + "_id": 2 + }, + "updateMods": { + "x": 222 + }, + "multi": false + }, + { + "delete": 0, + "filter": { + "_id": 3 + }, + "multi": false + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ], + "lsid": { + "$$exists": true + }, + "txnNumber": { + "$$exists": true + } + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 222 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ] + }, + { + "description": "client bulkWrite with multi: true operations fails after retryable top-level error", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "errorCode": 189, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "updateMany": { + "namespace": "retryable-writes-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "deleteMany": { + "namespace": "retryable-writes-tests.coll0", + "filter": { + "_id": 3 + } + } + } + ] + }, + "expectError": { + "errorCode": 189, + "errorLabelsContain": [ + "RetryableWriteError" + ] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": true, + "ordered": true, + "ops": [ + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": true + }, + { + "delete": 0, + "filter": { + "_id": 3 + }, + "multi": true + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ] + } + } + } + ] + } + ] + }, + { + "description": "client bulkWrite with no multi: true operations succeeds after retryable writeConcernError", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "errorLabels": [ + "RetryableWriteError" + ], + "writeConcernError": { + "code": 91, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "retryable-writes-tests.coll0", + "document": { + "_id": 4, + "x": 44 + } + } + }, + { + "updateOne": { + "namespace": "retryable-writes-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "replaceOne": { + "namespace": "retryable-writes-tests.coll0", + "filter": { + "_id": 2 + }, + "replacement": { + "x": 222 + } + } + }, + { + "deleteOne": { + "namespace": "retryable-writes-tests.coll0", + "filter": { + "_id": 3 + } + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 2, + "modifiedCount": 2, + "deletedCount": 1, + "insertResults": { + "0": { + "insertedId": 4 + } + }, + "updateResults": { + "1": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + }, + "2": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + } + }, + "deleteResults": { + "3": { + "deletedCount": 1 + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 4, + "x": 44 + } + }, + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": false + }, + { + "update": 0, + "filter": { + "_id": 2 + }, + "updateMods": { + "x": 222 + }, + "multi": false + }, + { + "delete": 0, + "filter": { + "_id": 3 + }, + "multi": false + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ], + "lsid": { + "$$exists": true + }, + "txnNumber": { + "$$exists": true + } + } + } + }, + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 4, + "x": 44 + } + }, + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": false + }, + { + "update": 0, + "filter": { + "_id": 2 + }, + "updateMods": { + "x": 222 + }, + "multi": false + }, + { + "delete": 0, + "filter": { + "_id": 3 + }, + "multi": false + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ], + "lsid": { + "$$exists": true + }, + "txnNumber": { + "$$exists": true + } + } + } + } + ] + } + ] + }, + { + "description": "client bulkWrite with multi: true operations fails after retryable writeConcernError", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "errorLabels": [ + "RetryableWriteError" + ], + "writeConcernError": { + "code": 91, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "updateMany": { + "namespace": "retryable-writes-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "deleteMany": { + "namespace": "retryable-writes-tests.coll0", + "filter": { + "_id": 3 + } + } + } + ] + }, + "expectError": { + "writeConcernErrors": [ + { + "code": 91, + "message": "Replication is being shut down" + } + ] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": true, + "ordered": true, + "ops": [ + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": true + }, + { + "delete": 0, + "filter": { + "_id": 3 + }, + "multi": true + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ] + } + } + } + ] + } + ] + }, + { + "description": "client bulkWrite with retryWrites: false does not retry", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "clientRetryWritesFalse", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "errorCode": 189, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "clientRetryWritesFalse", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "retryable-writes-tests.coll0", + "document": { + "_id": 4, + "x": 44 + } + } + } + ] + }, + "expectError": { + "errorCode": 189, + "errorLabelsContain": [ + "RetryableWriteError" + ] + } + } + ], + "expectEvents": [ + { + "client": "clientRetryWritesFalse", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": true, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 4, + "x": 44 + } + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ] + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/client-bulkWrite-serverErrors.yml b/test/spec/retryable-writes/unified/client-bulkWrite-serverErrors.yml new file mode 100644 index 0000000000..23d2c622ee --- /dev/null +++ b/test/spec/retryable-writes/unified/client-bulkWrite-serverErrors.yml @@ -0,0 +1,412 @@ +description: "client bulkWrite retryable writes" +schemaVersion: "1.21" +runOnRequirements: + - minServerVersion: "8.0" + topologies: + - replicaset + - sharded + - load-balanced + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + useMultipleMongoses: false + - client: + id: &clientRetryWritesFalse clientRetryWritesFalse + uriOptions: + retryWrites: false + observeEvents: [ commandStartedEvent ] + useMultipleMongoses: false + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name retryable-writes-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +_yamlAnchors: + namespace: &namespace "retryable-writes-tests.coll0" + +tests: + - description: "client bulkWrite with no multi: true operations succeeds after retryable top-level error" + operations: + - object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: [ bulkWrite ] + errorCode: 189 # PrimarySteppedDown + errorLabels: [ RetryableWriteError ] + - object: *client0 + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *namespace + document: { _id: 4, x: 44 } + - updateOne: + namespace: *namespace + filter: { _id: 1 } + update: + $inc: { x: 1 } + - replaceOne: + namespace: *namespace + filter: { _id: 2 } + replacement: { x: 222 } + - deleteOne: + namespace: *namespace + filter: { _id: 3 } + verboseResults: true + expectResult: + insertedCount: 1 + upsertedCount: 0 + matchedCount: 2 + modifiedCount: 2 + deletedCount: 1 + insertResults: + 0: + insertedId: 4 + updateResults: + 1: + matchedCount: 1 + modifiedCount: 1 + upsertedId: { $$exists: false } + 2: + matchedCount: 1 + modifiedCount: 1 + upsertedId: { $$exists: false } + deleteResults: + 3: + deletedCount: 1 + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + ops: + - insert: 0 + document: { _id: 4, x: 44 } + - update: 0 + filter: { _id: 1 } + updateMods: + $inc: { x: 1 } + multi: false + - update: 0 + filter: { _id: 2 } + updateMods: { x: 222 } + multi: false + - delete: 0 + filter: { _id: 3 } + multi: false + nsInfo: + - ns: *namespace + lsid: { $$exists: true } + txnNumber: { $$exists: true } + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + ops: + - insert: 0 + document: { _id: 4, x: 44 } + - update: 0 + filter: { _id: 1 } + updateMods: + $inc: { x: 1 } + multi: false + - update: 0 + filter: { _id: 2 } + updateMods: { x: 222 } + multi: false + - delete: 0 + filter: { _id: 3 } + multi: false + nsInfo: + - ns: *namespace + lsid: { $$exists: true } + txnNumber: { $$exists: true } + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 222 } + - { _id: 4, x: 44 } + - description: "client bulkWrite with multi: true operations fails after retryable top-level error" + operations: + - object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: [ bulkWrite ] + errorCode: 189 # PrimarySteppedDown + errorLabels: [ RetryableWriteError ] + - object: *client0 + name: clientBulkWrite + arguments: + models: + - updateMany: + namespace: *namespace + filter: { _id: 1 } + update: + $inc: { x: 1 } + - deleteMany: + namespace: *namespace + filter: { _id: 3 } + expectError: + errorCode: 189 + errorLabelsContain: [ RetryableWriteError ] + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: true + ordered: true + ops: + - update: 0 + filter: { _id: 1 } + updateMods: + $inc: { x: 1 } + multi: true + - delete: 0 + filter: { _id: 3 } + multi: true + nsInfo: + - ns: *namespace + - description: "client bulkWrite with no multi: true operations succeeds after retryable writeConcernError" + operations: + - object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: [ bulkWrite ] + errorLabels: [ RetryableWriteError ] + writeConcernError: + code: 91 + errmsg: "Replication is being shut down" + - object: *client0 + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *namespace + document: { _id: 4, x: 44 } + - updateOne: + namespace: *namespace + filter: { _id: 1 } + update: + $inc: { x: 1 } + - replaceOne: + namespace: *namespace + filter: { _id: 2 } + replacement: { x: 222 } + - deleteOne: + namespace: *namespace + filter: { _id: 3 } + verboseResults: true + expectResult: + insertedCount: 1 + upsertedCount: 0 + matchedCount: 2 + modifiedCount: 2 + deletedCount: 1 + insertResults: + 0: + insertedId: 4 + updateResults: + 1: + matchedCount: 1 + modifiedCount: 1 + upsertedId: { $$exists: false } + 2: + matchedCount: 1 + modifiedCount: 1 + upsertedId: { $$exists: false } + deleteResults: + 3: + deletedCount: 1 + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + ops: + - insert: 0 + document: { _id: 4, x: 44 } + - update: 0 + filter: { _id: 1 } + updateMods: + $inc: { x: 1 } + multi: false + - update: 0 + filter: { _id: 2 } + updateMods: { x: 222 } + multi: false + - delete: 0 + filter: { _id: 3 } + multi: false + nsInfo: + - ns: *namespace + lsid: { $$exists: true } + txnNumber: { $$exists: true } + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: false + ordered: true + ops: + - insert: 0 + document: { _id: 4, x: 44 } + - update: 0 + filter: { _id: 1 } + updateMods: + $inc: { x: 1 } + multi: false + - update: 0 + filter: { _id: 2 } + updateMods: { x: 222 } + multi: false + - delete: 0 + filter: { _id: 3 } + multi: false + nsInfo: + - ns: *namespace + lsid: { $$exists: true } + txnNumber: { $$exists: true } + - description: "client bulkWrite with multi: true operations fails after retryable writeConcernError" + operations: + - object: testRunner + name: failPoint + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: [ bulkWrite ] + errorLabels: [ RetryableWriteError ] + writeConcernError: + code: 91 + errmsg: "Replication is being shut down" + - object: *client0 + name: clientBulkWrite + arguments: + models: + - updateMany: + namespace: *namespace + filter: { _id: 1 } + update: + $inc: { x: 1 } + - deleteMany: + namespace: *namespace + filter: { _id: 3 } + expectError: + writeConcernErrors: + - code: 91 + message: "Replication is being shut down" + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: true + ordered: true + ops: + - update: 0 + filter: { _id: 1 } + updateMods: + $inc: { x: 1 } + multi: true + - delete: 0 + filter: { _id: 3 } + multi: true + nsInfo: + - ns: *namespace + - description: "client bulkWrite with retryWrites: false does not retry" + operations: + - object: testRunner + name: failPoint + arguments: + client: *clientRetryWritesFalse + failPoint: + configureFailPoint: failCommand + mode: + times: 1 + data: + failCommands: [ bulkWrite ] + errorCode: 189 # PrimarySteppedDown + errorLabels: [ RetryableWriteError ] + - object: *clientRetryWritesFalse + name: clientBulkWrite + arguments: + models: + - insertOne: + namespace: *namespace + document: { _id: 4, x: 44 } + expectError: + errorCode: 189 + errorLabelsContain: [ RetryableWriteError ] + expectEvents: + - client: *clientRetryWritesFalse + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + errorsOnly: true + ordered: true + ops: + - insert: 0 + document: { _id: 4, x: 44 } + nsInfo: + - ns: *namespace diff --git a/test/spec/retryable-writes/unified/deleteMany.json b/test/spec/retryable-writes/unified/deleteMany.json new file mode 100644 index 0000000000..087576cc0f --- /dev/null +++ b/test/spec/retryable-writes/unified/deleteMany.json @@ -0,0 +1,76 @@ +{ + "description": "deleteMany", + "schemaVersion": "1.3", + "runOnRequirements": [ + { + "minServerVersion": "3.6", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": true + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "DeleteMany ignores retryWrites", + "operations": [ + { + "object": "collection0", + "name": "deleteMany", + "arguments": { + "filter": {} + }, + "expectResult": { + "deletedCount": 2 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/deleteMany.yml b/test/spec/retryable-writes/unified/deleteMany.yml new file mode 100644 index 0000000000..31a6e07864 --- /dev/null +++ b/test/spec/retryable-writes/unified/deleteMany.yml @@ -0,0 +1,49 @@ +description: deleteMany + +schemaVersion: '1.3' + +runOnRequirements: + - + minServerVersion: '3.6' + topologies: [ replicaset, sharded, load-balanced ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: true + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'DeleteMany ignores retryWrites' + operations: + - + object: *collection0 + name: deleteMany + arguments: + filter: { } + expectResult: + deletedCount: 2 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: [] diff --git a/test/spec/retryable-writes/unified/deleteOne-errorLabels.json b/test/spec/retryable-writes/unified/deleteOne-errorLabels.json new file mode 100644 index 0000000000..88920862ec --- /dev/null +++ b/test/spec/retryable-writes/unified/deleteOne-errorLabels.json @@ -0,0 +1,266 @@ +{ + "description": "deleteOne-errorLabels", + "schemaVersion": "1.3", + "runOnRequirements": [ + { + "minServerVersion": "4.3.1", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "DeleteOne succeeds with RetryableWriteError from server", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "delete" + ], + "errorCode": 112, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "collection0", + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectResult": { + "deletedCount": 1 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "DeleteOne fails if server does not return RetryableWriteError", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "delete" + ], + "errorCode": 11600, + "errorLabels": [] + } + } + } + }, + { + "object": "collection0", + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectError": { + "isError": true, + "errorLabelsOmit": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "DeleteOne succeeds after PrimarySteppedDown", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "delete" + ], + "errorCode": 189, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "collection0", + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectResult": { + "deletedCount": 1 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "DeleteOne succeeds after WriteConcernError ShutdownInProgress", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "delete" + ], + "errorLabels": [ + "RetryableWriteError" + ], + "writeConcernError": { + "code": 91, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "object": "collection0", + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectResult": { + "deletedCount": 1 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/deleteOne-errorLabels.yml b/test/spec/retryable-writes/unified/deleteOne-errorLabels.yml new file mode 100644 index 0000000000..08e700a9bb --- /dev/null +++ b/test/spec/retryable-writes/unified/deleteOne-errorLabels.yml @@ -0,0 +1,157 @@ +description: deleteOne-errorLabels + +schemaVersion: '1.3' + +runOnRequirements: + - + minServerVersion: 4.3.1 # failCommand errorLabels option + topologies: [ replicaset, sharded, load-balanced ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'DeleteOne succeeds with RetryableWriteError from server' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ delete ] + errorCode: 112 # WriteConflict, not a retryable error code + # Override server behavior: send RetryableWriteError label with non-retryable error code + errorLabels: + - RetryableWriteError + - + object: *collection0 + name: deleteOne + arguments: + filter: { _id: 1 } + # Driver retries operation and it succeeds + expectResult: + deletedCount: 1 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 22 } + - + description: 'DeleteOne fails if server does not return RetryableWriteError' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ delete ] + errorCode: 11600 # InterruptedAtShutdown, normally a retryable error code + errorLabels: [] # Override server behavior: do not send RetryableWriteError label with retryable code + - + object: *collection0 + name: deleteOne + arguments: + filter: { _id: 1 } + # Driver does not retry operation because there was no RetryableWriteError label on response + expectError: + isError: true + errorLabelsOmit: + - RetryableWriteError + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - + description: 'DeleteOne succeeds after PrimarySteppedDown' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ delete ] + errorCode: 189 + errorLabels: + - RetryableWriteError + - + object: *collection0 + name: deleteOne + arguments: + filter: { _id: 1 } + expectResult: + deletedCount: 1 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 22 } + - + description: 'DeleteOne succeeds after WriteConcernError ShutdownInProgress' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ delete ] + errorLabels: + - RetryableWriteError + writeConcernError: + code: 91 + errmsg: 'Replication is being shut down' + - + object: *collection0 + name: deleteOne + arguments: + filter: { _id: 1 } + expectResult: + deletedCount: 1 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/deleteOne-serverErrors.json b/test/spec/retryable-writes/unified/deleteOne-serverErrors.json new file mode 100644 index 0000000000..0808b7921d --- /dev/null +++ b/test/spec/retryable-writes/unified/deleteOne-serverErrors.json @@ -0,0 +1,114 @@ +{ + "description": "deleteOne-serverErrors", + "schemaVersion": "1.3", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "DeleteOne fails with RetryableWriteError label after two connection failures", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "delete" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectError": { + "isError": true, + "errorLabelsContain": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/deleteOne-serverErrors.yml b/test/spec/retryable-writes/unified/deleteOne-serverErrors.yml new file mode 100644 index 0000000000..2b63c43e37 --- /dev/null +++ b/test/spec/retryable-writes/unified/deleteOne-serverErrors.yml @@ -0,0 +1,67 @@ +description: deleteOne-serverErrors + +schemaVersion: '1.3' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: [ replicaset ] + - + minServerVersion: 4.1.7 + topologies: [ sharded, load-balanced ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'DeleteOne fails with RetryableWriteError label after two connection failures' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ delete ] + closeConnection: true + - + object: *collection0 + name: deleteOne + arguments: + filter: { _id: 1 } + expectError: + isError: true + errorLabelsContain: + - RetryableWriteError + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/deleteOne.json b/test/spec/retryable-writes/unified/deleteOne.json new file mode 100644 index 0000000000..c3aaf88655 --- /dev/null +++ b/test/spec/retryable-writes/unified/deleteOne.json @@ -0,0 +1,188 @@ +{ + "description": "deleteOne", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "3.6", + "topologies": [ + "replicaset" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "DeleteOne is committed on first attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + } + } + } + }, + { + "object": "collection0", + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectResult": { + "deletedCount": 1 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "DeleteOne is not committed on first attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectResult": { + "deletedCount": 1 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "DeleteOne is never committed", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 2 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + } + }, + "expectError": { + "isError": true + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/deleteOne.yml b/test/spec/retryable-writes/unified/deleteOne.yml new file mode 100644 index 0000000000..ee31a33248 --- /dev/null +++ b/test/spec/retryable-writes/unified/deleteOne.yml @@ -0,0 +1,111 @@ +description: deleteOne + +schemaVersion: '1.0' + +runOnRequirements: + - + minServerVersion: '3.6' + topologies: [ replicaset ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'DeleteOne is committed on first attempt' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + - + object: *collection0 + name: deleteOne + arguments: + filter: { _id: 1 } + expectResult: + deletedCount: 1 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 22 } + - + description: 'DeleteOne is not committed on first attempt' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: deleteOne + arguments: + filter: { _id: 1 } + expectResult: + deletedCount: 1 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 22 } + - + description: 'DeleteOne is never committed' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 2 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: deleteOne + arguments: + filter: { _id: 1 } + expectError: + isError: true + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/findOneAndDelete-errorLabels.json b/test/spec/retryable-writes/unified/findOneAndDelete-errorLabels.json new file mode 100644 index 0000000000..8639873fca --- /dev/null +++ b/test/spec/retryable-writes/unified/findOneAndDelete-errorLabels.json @@ -0,0 +1,289 @@ +{ + "description": "findOneAndDelete-errorLabels", + "schemaVersion": "1.3", + "runOnRequirements": [ + { + "minServerVersion": "4.3.1", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "FindOneAndDelete succeeds with RetryableWriteError from server", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "findAndModify" + ], + "errorCode": 112, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndDelete", + "arguments": { + "filter": { + "x": { + "$gte": 11 + } + }, + "sort": { + "x": 1 + } + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "FindOneAndDelete fails if server does not return RetryableWriteError", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "findAndModify" + ], + "errorCode": 11600, + "errorLabels": [] + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndDelete", + "arguments": { + "filter": { + "x": { + "$gte": 11 + } + }, + "sort": { + "x": 1 + } + }, + "expectError": { + "isError": true, + "errorLabelsOmit": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "FindOneAndDelete succeeds after PrimarySteppedDown", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "findAndModify" + ], + "errorCode": 189, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndDelete", + "arguments": { + "filter": { + "x": { + "$gte": 11 + } + }, + "sort": { + "x": 1 + } + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "FindOneAndDelete succeeds after WriteConcernError ShutdownInProgress", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "findAndModify" + ], + "errorLabels": [ + "RetryableWriteError" + ], + "writeConcernError": { + "code": 91, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndDelete", + "arguments": { + "filter": { + "x": { + "$gte": 11 + } + }, + "sort": { + "x": 1 + } + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/findOneAndDelete-errorLabels.yml b/test/spec/retryable-writes/unified/findOneAndDelete-errorLabels.yml new file mode 100644 index 0000000000..cd712f2eb3 --- /dev/null +++ b/test/spec/retryable-writes/unified/findOneAndDelete-errorLabels.yml @@ -0,0 +1,158 @@ +description: findOneAndDelete-errorLabels + +schemaVersion: '1.3' + +runOnRequirements: + - + minServerVersion: 4.3.1 # failCommand errorLabels option + topologies: [ replicaset, sharded, load-balanced ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'FindOneAndDelete succeeds with RetryableWriteError from server' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ findAndModify ] + errorCode: 112 # WriteConflict, not a retryable error code + # Override server behavior: send RetryableWriteError label with non-retryable error code + errorLabels: + - RetryableWriteError + - + object: *collection0 + name: findOneAndDelete + arguments: + filter: { x: { $gte: 11 } } + sort: { x: 1 } + # Driver retries operation and it succeeds + expectResult: { _id: 1, x: 11 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 22 } + - + description: 'FindOneAndDelete fails if server does not return RetryableWriteError' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ findAndModify ] + errorCode: 11600 # InterruptedAtShutdown, normally a retryable error code + errorLabels: [] # Override server behavior: do not send RetryableWriteError label with retryable code + - + object: *collection0 + name: findOneAndDelete + arguments: + filter: { x: { $gte: 11 } } + sort: { x: 1 } + # Driver does not retry operation because there was no RetryableWriteError label on response + expectError: + isError: true + errorLabelsOmit: + - RetryableWriteError + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - + description: 'FindOneAndDelete succeeds after PrimarySteppedDown' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ findAndModify ] + errorCode: 189 + errorLabels: + - RetryableWriteError + - + object: *collection0 + name: findOneAndDelete + arguments: + filter: { x: { $gte: 11 } } + sort: { x: 1 } + expectResult: { _id: 1, x: 11 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 22 } + - + description: 'FindOneAndDelete succeeds after WriteConcernError ShutdownInProgress' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ findAndModify ] + errorLabels: + - RetryableWriteError + writeConcernError: + code: 91 + errmsg: 'Replication is being shut down' + - + object: *collection0 + name: findOneAndDelete + arguments: + filter: { x: { $gte: 11 } } + sort: { x: 1 } + expectResult: { _id: 1, x: 11 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/findOneAndDelete-serverErrors.json b/test/spec/retryable-writes/unified/findOneAndDelete-serverErrors.json new file mode 100644 index 0000000000..f6d8e9d69c --- /dev/null +++ b/test/spec/retryable-writes/unified/findOneAndDelete-serverErrors.json @@ -0,0 +1,119 @@ +{ + "description": "findOneAndDelete-serverErrors", + "schemaVersion": "1.3", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "FindOneAndDelete fails with a RetryableWriteError label after two connection failures", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "findAndModify" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndDelete", + "arguments": { + "filter": { + "x": { + "$gte": 11 + } + }, + "sort": { + "x": 1 + } + }, + "expectError": { + "isError": true, + "errorLabelsContain": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/findOneAndDelete-serverErrors.yml b/test/spec/retryable-writes/unified/findOneAndDelete-serverErrors.yml new file mode 100644 index 0000000000..a9da496c08 --- /dev/null +++ b/test/spec/retryable-writes/unified/findOneAndDelete-serverErrors.yml @@ -0,0 +1,68 @@ +description: findOneAndDelete-serverErrors + +schemaVersion: '1.3' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: [ replicaset ] + - + minServerVersion: 4.1.7 + topologies: [ sharded, load-balanced ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'FindOneAndDelete fails with a RetryableWriteError label after two connection failures' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ findAndModify ] + closeConnection: true + - + object: *collection0 + name: findOneAndDelete + arguments: + filter: { x: { $gte: 11 } } + sort: { x: 1 } + expectError: + isError: true + errorLabelsContain: + - RetryableWriteError + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/findOneAndDelete.json b/test/spec/retryable-writes/unified/findOneAndDelete.json new file mode 100644 index 0000000000..89dbb9d655 --- /dev/null +++ b/test/spec/retryable-writes/unified/findOneAndDelete.json @@ -0,0 +1,205 @@ +{ + "description": "findOneAndDelete", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "3.6", + "topologies": [ + "replicaset" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "FindOneAndDelete is committed on first attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndDelete", + "arguments": { + "filter": { + "x": { + "$gte": 11 + } + }, + "sort": { + "x": 1 + } + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "FindOneAndDelete is not committed on first attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndDelete", + "arguments": { + "filter": { + "x": { + "$gte": 11 + } + }, + "sort": { + "x": 1 + } + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "FindOneAndDelete is never committed", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 2 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndDelete", + "arguments": { + "filter": { + "x": { + "$gte": 11 + } + }, + "sort": { + "x": 1 + } + }, + "expectError": { + "isError": true + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/findOneAndDelete.yml b/test/spec/retryable-writes/unified/findOneAndDelete.yml new file mode 100644 index 0000000000..464611a0f5 --- /dev/null +++ b/test/spec/retryable-writes/unified/findOneAndDelete.yml @@ -0,0 +1,112 @@ +description: findOneAndDelete + +schemaVersion: '1.0' + +runOnRequirements: + - + minServerVersion: '3.6' + topologies: [ replicaset ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'FindOneAndDelete is committed on first attempt' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + - + object: *collection0 + name: findOneAndDelete + arguments: + filter: { x: { $gte: 11 } } + sort: { x: 1 } + expectResult: { _id: 1, x: 11 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 22 } + - + description: 'FindOneAndDelete is not committed on first attempt' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: findOneAndDelete + arguments: + filter: { x: { $gte: 11 } } + sort: { x: 1 } + expectResult: { _id: 1, x: 11 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 2, x: 22 } + - + description: 'FindOneAndDelete is never committed' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 2 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: findOneAndDelete + arguments: + filter: { x: { $gte: 11 } } + sort: { x: 1 } + expectError: + isError: true + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/findOneAndReplace-errorLabels.json b/test/spec/retryable-writes/unified/findOneAndReplace-errorLabels.json new file mode 100644 index 0000000000..78db52e75d --- /dev/null +++ b/test/spec/retryable-writes/unified/findOneAndReplace-errorLabels.json @@ -0,0 +1,301 @@ +{ + "description": "findOneAndReplace-errorLabels", + "schemaVersion": "1.3", + "runOnRequirements": [ + { + "minServerVersion": "4.3.1", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "FindOneAndReplace succeeds with RetryableWriteError from server", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "findAndModify" + ], + "errorCode": 112, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "_id": 1, + "x": 111 + }, + "returnDocument": "Before" + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 111 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "FindOneAndReplace fails if server does not return RetryableWriteError", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "findAndModify" + ], + "errorCode": 11600, + "errorLabels": [] + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "_id": 1, + "x": 111 + }, + "returnDocument": "Before" + }, + "expectError": { + "isError": true, + "errorLabelsOmit": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "FindOneAndReplace succeeds after PrimarySteppedDown", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "findAndModify" + ], + "errorCode": 189, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "_id": 1, + "x": 111 + }, + "returnDocument": "Before" + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 111 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "FindOneAndReplace succeeds after WriteConcernError ShutdownInProgress", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "findAndModify" + ], + "errorLabels": [ + "RetryableWriteError" + ], + "writeConcernError": { + "code": 91, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "_id": 1, + "x": 111 + }, + "returnDocument": "Before" + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 111 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/findOneAndReplace-errorLabels.yml b/test/spec/retryable-writes/unified/findOneAndReplace-errorLabels.yml new file mode 100644 index 0000000000..254b61980d --- /dev/null +++ b/test/spec/retryable-writes/unified/findOneAndReplace-errorLabels.yml @@ -0,0 +1,165 @@ +description: findOneAndReplace-errorLabels + +schemaVersion: '1.3' + +runOnRequirements: + - + minServerVersion: 4.3.1 # failCommand errorLabels option + topologies: [ replicaset, sharded, load-balanced ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'FindOneAndReplace succeeds with RetryableWriteError from server' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ findAndModify ] + errorCode: 112 # WriteConflict, not a retryable error code + # Override server behavior: send RetryableWriteError label with non-retryable error code + errorLabels: + - RetryableWriteError + - + object: *collection0 + name: findOneAndReplace + arguments: + filter: { _id: 1 } + replacement: { _id: 1, x: 111 } + returnDocument: Before + # Driver retries operation and it succeeds + expectResult: { _id: 1, x: 11 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 111 } + - { _id: 2, x: 22 } + - + description: 'FindOneAndReplace fails if server does not return RetryableWriteError' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ findAndModify ] + errorCode: 11600 # InterruptedAtShutdown, normally a retryable error code + errorLabels: [] # Override server behavior: do not send RetryableWriteError label with retryable code + - + object: *collection0 + name: findOneAndReplace + arguments: + filter: { _id: 1 } + replacement: { _id: 1, x: 111 } + returnDocument: Before + # Driver does not retry operation because there was no RetryableWriteError label on response + expectError: + isError: true + errorLabelsOmit: + - RetryableWriteError + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - + description: 'FindOneAndReplace succeeds after PrimarySteppedDown' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ findAndModify ] + errorCode: 189 + errorLabels: + - RetryableWriteError + - + object: *collection0 + name: findOneAndReplace + arguments: + filter: { _id: 1 } + replacement: { _id: 1, x: 111 } + returnDocument: Before + expectResult: { _id: 1, x: 11 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 111 } + - { _id: 2, x: 22 } + - + description: 'FindOneAndReplace succeeds after WriteConcernError ShutdownInProgress' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ findAndModify ] + errorLabels: + - RetryableWriteError + writeConcernError: + code: 91 + errmsg: 'Replication is being shut down' + - + object: *collection0 + name: findOneAndReplace + arguments: + filter: { _id: 1 } + replacement: { _id: 1, x: 111 } + returnDocument: Before + expectResult: { _id: 1, x: 11 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 111 } + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/findOneAndReplace-serverErrors.json b/test/spec/retryable-writes/unified/findOneAndReplace-serverErrors.json new file mode 100644 index 0000000000..1c355c3ebf --- /dev/null +++ b/test/spec/retryable-writes/unified/findOneAndReplace-serverErrors.json @@ -0,0 +1,119 @@ +{ + "description": "findOneAndReplace-serverErrors", + "schemaVersion": "1.3", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "FindOneAndReplace fails with a RetryableWriteError label after two connection failures", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "findAndModify" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "_id": 1, + "x": 111 + }, + "returnDocument": "Before" + }, + "expectError": { + "isError": true, + "errorLabelsContain": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/findOneAndReplace-serverErrors.yml b/test/spec/retryable-writes/unified/findOneAndReplace-serverErrors.yml new file mode 100644 index 0000000000..090356badd --- /dev/null +++ b/test/spec/retryable-writes/unified/findOneAndReplace-serverErrors.yml @@ -0,0 +1,69 @@ +description: findOneAndReplace-serverErrors + +schemaVersion: '1.3' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: [ replicaset ] + - + minServerVersion: 4.1.7 + topologies: [ sharded, load-balanced ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'FindOneAndReplace fails with a RetryableWriteError label after two connection failures' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ findAndModify ] + closeConnection: true + - + object: *collection0 + name: findOneAndReplace + arguments: + filter: { _id: 1 } + replacement: { _id: 1, x: 111 } + returnDocument: Before + expectError: + isError: true + errorLabelsContain: + - RetryableWriteError + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/findOneAndReplace.json b/test/spec/retryable-writes/unified/findOneAndReplace.json new file mode 100644 index 0000000000..6d1cc17974 --- /dev/null +++ b/test/spec/retryable-writes/unified/findOneAndReplace.json @@ -0,0 +1,213 @@ +{ + "description": "findOneAndReplace", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "3.6", + "topologies": [ + "replicaset" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "FindOneAndReplace is committed on first attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "_id": 1, + "x": 111 + }, + "returnDocument": "Before" + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 111 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "FindOneAndReplace is not committed on first attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "_id": 1, + "x": 111 + }, + "returnDocument": "Before" + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 111 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "FindOneAndReplace is never committed", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 2 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "_id": 1, + "x": 111 + }, + "returnDocument": "Before" + }, + "expectError": { + "isError": true + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/findOneAndReplace.yml b/test/spec/retryable-writes/unified/findOneAndReplace.yml new file mode 100644 index 0000000000..7a564143bd --- /dev/null +++ b/test/spec/retryable-writes/unified/findOneAndReplace.yml @@ -0,0 +1,117 @@ +description: findOneAndReplace + +schemaVersion: '1.0' + +runOnRequirements: + - + minServerVersion: '3.6' + topologies: [ replicaset ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'FindOneAndReplace is committed on first attempt' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + - + object: *collection0 + name: findOneAndReplace + arguments: + filter: { _id: 1 } + replacement: { _id: 1, x: 111 } + returnDocument: Before + expectResult: { _id: 1, x: 11 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 111 } + - { _id: 2, x: 22 } + - + description: 'FindOneAndReplace is not committed on first attempt' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: findOneAndReplace + arguments: + filter: { _id: 1 } + replacement: { _id: 1, x: 111 } + returnDocument: Before + expectResult: { _id: 1, x: 11 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 111 } + - { _id: 2, x: 22 } + - + description: 'FindOneAndReplace is never committed' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 2 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: findOneAndReplace + arguments: + filter: { _id: 1 } + replacement: { _id: 1, x: 111 } + returnDocument: Before + expectError: + isError: true + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/findOneAndUpdate-errorLabels.json b/test/spec/retryable-writes/unified/findOneAndUpdate-errorLabels.json new file mode 100644 index 0000000000..38b3f7ba44 --- /dev/null +++ b/test/spec/retryable-writes/unified/findOneAndUpdate-errorLabels.json @@ -0,0 +1,305 @@ +{ + "description": "findOneAndUpdate-errorLabels", + "schemaVersion": "1.3", + "runOnRequirements": [ + { + "minServerVersion": "4.3.1", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "FindOneAndUpdate succeeds with RetryableWriteError from server", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "findAndModify" + ], + "errorCode": 112, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "returnDocument": "Before" + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "FindOneAndUpdate fails if server does not return RetryableWriteError", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "findAndModify" + ], + "errorCode": 11600, + "errorLabels": [] + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "returnDocument": "Before" + }, + "expectError": { + "isError": true, + "errorLabelsOmit": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "FindOneAndUpdate succeeds after PrimarySteppedDown", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "findAndModify" + ], + "errorCode": 189, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "returnDocument": "Before" + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "FindOneAndUpdate succeeds after WriteConcernError ShutdownInProgress", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "findAndModify" + ], + "errorLabels": [ + "RetryableWriteError" + ], + "writeConcernError": { + "code": 91, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "returnDocument": "Before" + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/findOneAndUpdate-errorLabels.yml b/test/spec/retryable-writes/unified/findOneAndUpdate-errorLabels.yml new file mode 100644 index 0000000000..034edbe77e --- /dev/null +++ b/test/spec/retryable-writes/unified/findOneAndUpdate-errorLabels.yml @@ -0,0 +1,165 @@ +description: findOneAndUpdate-errorLabels + +schemaVersion: '1.3' + +runOnRequirements: + - + minServerVersion: 4.3.1 # failCommand errorLabels option + topologies: [ replicaset, sharded, load-balanced ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'FindOneAndUpdate succeeds with RetryableWriteError from server' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ findAndModify ] + errorCode: 112 # WriteConflict, not a retryable error code + # Override server behavior: send RetryableWriteError label with non-retryable error code + errorLabels: + - RetryableWriteError + - + object: *collection0 + name: findOneAndUpdate + arguments: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + returnDocument: Before + # Driver retries operation and it succeeds + expectResult: { _id: 1, x: 11 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 22 } + - + description: 'FindOneAndUpdate fails if server does not return RetryableWriteError' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ findAndModify ] + errorCode: 11600 # InterruptedAtShutdown, normally a retryable error code + errorLabels: [] # Override server behavior: do not send RetryableWriteError label with retryable code + - + object: *collection0 + name: findOneAndUpdate + arguments: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + returnDocument: Before + # Driver does not retry operation because there was no RetryableWriteError label on response + expectError: + isError: true + errorLabelsOmit: + - RetryableWriteError + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - + description: 'FindOneAndUpdate succeeds after PrimarySteppedDown' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ findAndModify ] + errorCode: 189 + errorLabels: + - RetryableWriteError + - + object: *collection0 + name: findOneAndUpdate + arguments: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + returnDocument: Before + expectResult: { _id: 1, x: 11 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 22 } + - + description: 'FindOneAndUpdate succeeds after WriteConcernError ShutdownInProgress' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ findAndModify ] + errorLabels: + - RetryableWriteError + writeConcernError: + code: 91 + errmsg: 'Replication is being shut down' + - + object: *collection0 + name: findOneAndUpdate + arguments: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + returnDocument: Before + expectResult: { _id: 1, x: 11 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/findOneAndUpdate-serverErrors.json b/test/spec/retryable-writes/unified/findOneAndUpdate-serverErrors.json new file mode 100644 index 0000000000..150012ac72 --- /dev/null +++ b/test/spec/retryable-writes/unified/findOneAndUpdate-serverErrors.json @@ -0,0 +1,120 @@ +{ + "description": "findOneAndUpdate-serverErrors", + "schemaVersion": "1.3", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "FindOneAndUpdate fails with a RetryableWriteError label after two connection failures", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "findAndModify" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "returnDocument": "Before" + }, + "expectError": { + "isError": true, + "errorLabelsContain": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/findOneAndUpdate-serverErrors.yml b/test/spec/retryable-writes/unified/findOneAndUpdate-serverErrors.yml new file mode 100644 index 0000000000..8f9765fc19 --- /dev/null +++ b/test/spec/retryable-writes/unified/findOneAndUpdate-serverErrors.yml @@ -0,0 +1,69 @@ +description: findOneAndUpdate-serverErrors + +schemaVersion: '1.3' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: [ replicaset ] + - + minServerVersion: 4.1.7 + topologies: [ sharded, load-balanced ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'FindOneAndUpdate fails with a RetryableWriteError label after two connection failures' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ findAndModify ] + closeConnection: true + - + object: *collection0 + name: findOneAndUpdate + arguments: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + returnDocument: Before + expectError: + isError: true + errorLabelsContain: + - RetryableWriteError + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/findOneAndUpdate.json b/test/spec/retryable-writes/unified/findOneAndUpdate.json new file mode 100644 index 0000000000..eb88fbe9b3 --- /dev/null +++ b/test/spec/retryable-writes/unified/findOneAndUpdate.json @@ -0,0 +1,215 @@ +{ + "description": "findOneAndUpdate", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "3.6", + "topologies": [ + "replicaset" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "FindOneAndUpdate is committed on first attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "returnDocument": "Before" + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "FindOneAndUpdate is not committed on first attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "returnDocument": "Before" + }, + "expectResult": { + "_id": 1, + "x": 11 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "FindOneAndUpdate is never committed", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 2 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + }, + "expectError": { + "isError": true + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/findOneAndUpdate.yml b/test/spec/retryable-writes/unified/findOneAndUpdate.yml new file mode 100644 index 0000000000..1a67f9b047 --- /dev/null +++ b/test/spec/retryable-writes/unified/findOneAndUpdate.yml @@ -0,0 +1,116 @@ +description: findOneAndUpdate + +schemaVersion: '1.0' + +runOnRequirements: + - + minServerVersion: '3.6' + topologies: [ replicaset ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'FindOneAndUpdate is committed on first attempt' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + - + object: *collection0 + name: findOneAndUpdate + arguments: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + returnDocument: Before + expectResult: { _id: 1, x: 11 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 22 } + - + description: 'FindOneAndUpdate is not committed on first attempt' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: findOneAndUpdate + arguments: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + returnDocument: Before + expectResult: { _id: 1, x: 11 } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 22 } + - + description: 'FindOneAndUpdate is never committed' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 2 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: findOneAndUpdate + arguments: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + expectError: + isError: true + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/handshakeError.json b/test/spec/retryable-writes/unified/handshakeError.json index df37bd7232..3c46463759 100644 --- a/test/spec/retryable-writes/unified/handshakeError.json +++ b/test/spec/retryable-writes/unified/handshakeError.json @@ -53,6 +53,222 @@ } ], "tests": [ + { + "description": "client.clientBulkWrite succeeds after retryable handshake network error", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "ping", + "saslContinue" + ], + "closeConnection": true + } + } + } + }, + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "ping", + "command": { + "ping": 1 + } + }, + "expectError": { + "isError": true + } + }, + { + "name": "clientBulkWrite", + "object": "client", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "retryable-writes-handshake-tests.coll", + "document": { + "_id": 8, + "x": 88 + } + } + } + ] + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "cmap", + "events": [ + { + "connectionCheckOutStartedEvent": {} + }, + { + "connectionCheckOutStartedEvent": {} + }, + { + "connectionCheckOutStartedEvent": {} + }, + { + "connectionCheckOutStartedEvent": {} + } + ] + }, + { + "client": "client", + "events": [ + { + "commandStartedEvent": { + "command": { + "ping": 1 + }, + "databaseName": "retryable-writes-handshake-tests" + } + }, + { + "commandFailedEvent": { + "commandName": "ping" + } + }, + { + "commandStartedEvent": { + "commandName": "bulkWrite" + } + }, + { + "commandSucceededEvent": { + "commandName": "bulkWrite" + } + } + ] + } + ] + }, + { + "description": "client.clientBulkWrite succeeds after retryable handshake server error (ShutdownInProgress)", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "ping", + "saslContinue" + ], + "closeConnection": true + } + } + } + }, + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "ping", + "command": { + "ping": 1 + } + }, + "expectError": { + "isError": true + } + }, + { + "name": "clientBulkWrite", + "object": "client", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "retryable-writes-handshake-tests.coll", + "document": { + "_id": 8, + "x": 88 + } + } + } + ] + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "cmap", + "events": [ + { + "connectionCheckOutStartedEvent": {} + }, + { + "connectionCheckOutStartedEvent": {} + }, + { + "connectionCheckOutStartedEvent": {} + }, + { + "connectionCheckOutStartedEvent": {} + } + ] + }, + { + "client": "client", + "events": [ + { + "commandStartedEvent": { + "command": { + "ping": 1 + }, + "databaseName": "retryable-writes-handshake-tests" + } + }, + { + "commandFailedEvent": { + "commandName": "ping" + } + }, + { + "commandStartedEvent": { + "commandName": "bulkWrite" + } + }, + { + "commandSucceededEvent": { + "commandName": "bulkWrite" + } + } + ] + } + ] + }, { "description": "collection.insertOne succeeds after retryable handshake network error", "operations": [ diff --git a/test/spec/retryable-writes/unified/handshakeError.yml b/test/spec/retryable-writes/unified/handshakeError.yml index 9b2774bc77..131bbf2e5c 100644 --- a/test/spec/retryable-writes/unified/handshakeError.yml +++ b/test/spec/retryable-writes/unified/handshakeError.yml @@ -50,6 +50,96 @@ tests: # - Triggers failpoint (second time). # - Tests whether operation successfully retries the handshake and succeeds. + - description: "client.clientBulkWrite succeeds after retryable handshake network error" + runOnRequirements: + - minServerVersion: "8.0" # `bulkWrite` added to server 8.0 + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: clientBulkWrite + object: *client + arguments: + models: + - insertOne: + namespace: retryable-writes-handshake-tests.coll + document: { _id: 8, x: 88 } + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: bulkWrite + - commandSucceededEvent: + commandName: bulkWrite + + - description: "client.clientBulkWrite succeeds after retryable handshake server error (ShutdownInProgress)" + runOnRequirements: + - minServerVersion: "8.0" # `bulkWrite` added to server 8.0 + operations: + - name: failPoint + object: testRunner + arguments: + client: *client + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ping, saslContinue] + closeConnection: true + - name: runCommand + object: *database + arguments: { commandName: ping, command: { ping: 1 } } + expectError: { isError: true } + - name: clientBulkWrite + object: *client + arguments: + models: + - insertOne: + namespace: retryable-writes-handshake-tests.coll + document: { _id: 8, x: 88 } + expectEvents: + - client: *client + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - { connectionCheckOutStartedEvent: {} } + - client: *client + events: + - commandStartedEvent: + command: { ping: 1 } + databaseName: *databaseName + - commandFailedEvent: + commandName: ping + - commandStartedEvent: + commandName: bulkWrite + - commandSucceededEvent: + commandName: bulkWrite + - description: "collection.insertOne succeeds after retryable handshake network error" operations: - name: failPoint diff --git a/test/spec/retryable-writes/unified/insertMany-errorLabels.json b/test/spec/retryable-writes/unified/insertMany-errorLabels.json new file mode 100644 index 0000000000..5254ba7cb2 --- /dev/null +++ b/test/spec/retryable-writes/unified/insertMany-errorLabels.json @@ -0,0 +1,335 @@ +{ + "description": "insertMany-errorLabels", + "schemaVersion": "1.3", + "runOnRequirements": [ + { + "minServerVersion": "4.3.1", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ], + "tests": [ + { + "description": "InsertMany succeeds with RetryableWriteError from server", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 112, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "collection0", + "name": "insertMany", + "arguments": { + "documents": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "ordered": true + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedIds": { + "$$unsetOrMatches": { + "0": 2, + "1": 3 + } + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "InsertMany fails if server does not return RetryableWriteError", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 11600, + "errorLabels": [] + } + } + } + }, + { + "object": "collection0", + "name": "insertMany", + "arguments": { + "documents": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "ordered": true + }, + "expectError": { + "isError": true, + "errorLabelsOmit": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "InsertMany succeeds after PrimarySteppedDown", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 189, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "collection0", + "name": "insertMany", + "arguments": { + "documents": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "ordered": true + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedIds": { + "$$unsetOrMatches": { + "0": 2, + "1": 3 + } + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "InsertMany succeeds after WriteConcernError ShutdownInProgress", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorLabels": [ + "RetryableWriteError" + ], + "writeConcernError": { + "code": 91, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "object": "collection0", + "name": "insertMany", + "arguments": { + "documents": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "ordered": true + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedIds": { + "$$unsetOrMatches": { + "0": 2, + "1": 3 + } + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/insertMany-errorLabels.yml b/test/spec/retryable-writes/unified/insertMany-errorLabels.yml new file mode 100644 index 0000000000..631b3a5762 --- /dev/null +++ b/test/spec/retryable-writes/unified/insertMany-errorLabels.yml @@ -0,0 +1,185 @@ +description: insertMany-errorLabels + +schemaVersion: '1.3' + +runOnRequirements: + - + minServerVersion: 4.3.1 # failCommand errorLabels option + topologies: [ replicaset, sharded, load-balanced ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + +tests: + - + description: 'InsertMany succeeds with RetryableWriteError from server' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorCode: 112 # WriteConflict, not a retryable error code + # Override server behavior: send RetryableWriteError label with non-retryable error code + errorLabels: + - RetryableWriteError + - + object: *collection0 + name: insertMany + arguments: + documents: + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + ordered: true + # Driver retries operation and it succeeds + expectResult: + $$unsetOrMatches: + insertedIds: + $$unsetOrMatches: + '0': 2 + '1': 3 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'InsertMany fails if server does not return RetryableWriteError' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorCode: 11600 # InterruptedAtShutdown, normally a retryable error code + errorLabels: [] # Override server behavior: do not send RetryableWriteError label with retryable code + - + object: *collection0 + name: insertMany + arguments: + documents: + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + ordered: true + # Driver does not retry operation because there was no RetryableWriteError label on response + expectError: + isError: true + errorLabelsOmit: + - RetryableWriteError + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'InsertMany succeeds after PrimarySteppedDown' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorCode: 189 + errorLabels: + - RetryableWriteError + - + object: *collection0 + name: insertMany + arguments: + documents: + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + ordered: true + expectResult: + $$unsetOrMatches: + insertedIds: + $$unsetOrMatches: + '0': 2 + '1': 3 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'InsertMany succeeds after WriteConcernError ShutdownInProgress' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorLabels: + - RetryableWriteError + writeConcernError: + code: 91 + errmsg: 'Replication is being shut down' + - + object: *collection0 + name: insertMany + arguments: + documents: + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + ordered: true + expectResult: + $$unsetOrMatches: + insertedIds: + $$unsetOrMatches: + '0': 2 + '1': 3 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } diff --git a/test/spec/retryable-writes/unified/insertMany-serverErrors.json b/test/spec/retryable-writes/unified/insertMany-serverErrors.json new file mode 100644 index 0000000000..f5f513603c --- /dev/null +++ b/test/spec/retryable-writes/unified/insertMany-serverErrors.json @@ -0,0 +1,114 @@ +{ + "description": "insertMany-serverErrors", + "schemaVersion": "1.3", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ], + "tests": [ + { + "description": "InsertMany fails with a RetryableWriteError label after two connection failures", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "insert" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "insertMany", + "arguments": { + "documents": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "ordered": true + }, + "expectError": { + "isError": true, + "errorLabelsContain": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/insertMany-serverErrors.yml b/test/spec/retryable-writes/unified/insertMany-serverErrors.yml new file mode 100644 index 0000000000..f229428bd7 --- /dev/null +++ b/test/spec/retryable-writes/unified/insertMany-serverErrors.yml @@ -0,0 +1,68 @@ +description: insertMany-serverErrors + +schemaVersion: '1.3' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: [ replicaset ] + - + minServerVersion: 4.1.7 + topologies: [ sharded, load-balanced ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + +tests: + - + description: 'InsertMany fails with a RetryableWriteError label after two connection failures' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ insert ] + closeConnection: true + - + object: *collection0 + name: insertMany + arguments: + documents: + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + ordered: true + expectError: + isError: true + errorLabelsContain: + - RetryableWriteError + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } diff --git a/test/spec/retryable-writes/unified/insertMany.json b/test/spec/retryable-writes/unified/insertMany.json new file mode 100644 index 0000000000..47181d0a9e --- /dev/null +++ b/test/spec/retryable-writes/unified/insertMany.json @@ -0,0 +1,233 @@ +{ + "description": "insertMany", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "3.6", + "topologies": [ + "replicaset" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ], + "tests": [ + { + "description": "InsertMany succeeds after one network error", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + } + } + } + }, + { + "object": "collection0", + "name": "insertMany", + "arguments": { + "documents": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "ordered": true + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedIds": { + "$$unsetOrMatches": { + "0": 2, + "1": 3 + } + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "InsertMany with unordered execution", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + } + } + } + }, + { + "object": "collection0", + "name": "insertMany", + "arguments": { + "documents": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "ordered": false + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedIds": { + "$$unsetOrMatches": { + "0": 2, + "1": 3 + } + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "InsertMany fails after multiple network errors", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": "alwaysOn", + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "insertMany", + "arguments": { + "documents": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ], + "ordered": true + }, + "expectError": { + "isError": true + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/insertMany.yml b/test/spec/retryable-writes/unified/insertMany.yml new file mode 100644 index 0000000000..0656b0c7ca --- /dev/null +++ b/test/spec/retryable-writes/unified/insertMany.yml @@ -0,0 +1,135 @@ +description: insertMany + +schemaVersion: '1.0' + +runOnRequirements: + - + minServerVersion: '3.6' + topologies: [ replicaset ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + +tests: + - + description: 'InsertMany succeeds after one network error' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + - + object: *collection0 + name: insertMany + arguments: + documents: + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + ordered: true + expectResult: + $$unsetOrMatches: + insertedIds: + $$unsetOrMatches: + '0': 2 + '1': 3 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'InsertMany with unordered execution' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + - + object: *collection0 + name: insertMany + arguments: + documents: + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + ordered: false + expectResult: + $$unsetOrMatches: + insertedIds: + $$unsetOrMatches: + '0': 2 + '1': 3 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'InsertMany fails after multiple network errors' + operations: + - + # Normally, a mongod will insert the documents as a batch with a single + # commit. If this fails, mongod may try to insert each document one at a + # time depending on the failure. Therefore our single insert command may + # trigger the failpoint twice on each driver attempt. This test + # permanently enables the fail point to ensure the retry attempt always + # fails. + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: alwaysOn + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: insertMany + arguments: + documents: + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - { _id: 4, x: 44 } + ordered: true + expectError: + isError: true + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } diff --git a/test/spec/retryable-writes/unified/insertOne-errorLabels.json b/test/spec/retryable-writes/unified/insertOne-errorLabels.json new file mode 100644 index 0000000000..39f31a8aa6 --- /dev/null +++ b/test/spec/retryable-writes/unified/insertOne-errorLabels.json @@ -0,0 +1,1127 @@ +{ + "description": "insertOne-errorLabels", + "schemaVersion": "1.3", + "runOnRequirements": [ + { + "minServerVersion": "4.3.1", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [] + } + ], + "tests": [ + { + "description": "InsertOne succeeds with RetryableWriteError from server", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 112, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "x": 11 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "InsertOne fails if server does not return RetryableWriteError", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 11600, + "errorLabels": [] + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "x": 11 + } + }, + "expectError": { + "isError": true, + "errorLabelsOmit": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [] + } + ] + }, + { + "description": "InsertOne succeeds after NotWritablePrimary", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 10107, + "errorLabels": [ + "RetryableWriteError" + ], + "closeConnection": false + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "x": 11 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "InsertOne succeeds after NotPrimaryOrSecondary", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 13436, + "errorLabels": [ + "RetryableWriteError" + ], + "closeConnection": false + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "x": 11 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "InsertOne succeeds after NotPrimaryNoSecondaryOk", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 13435, + "errorLabels": [ + "RetryableWriteError" + ], + "closeConnection": false + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "x": 11 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "InsertOne succeeds after InterruptedDueToReplStateChange", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 11602, + "errorLabels": [ + "RetryableWriteError" + ], + "closeConnection": false + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "x": 11 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "InsertOne succeeds after InterruptedAtShutdown", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 11600, + "errorLabels": [ + "RetryableWriteError" + ], + "closeConnection": false + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "x": 11 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "InsertOne succeeds after PrimarySteppedDown", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 189, + "errorLabels": [ + "RetryableWriteError" + ], + "closeConnection": false + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "x": 11 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "InsertOne succeeds after ShutdownInProgress", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 91, + "errorLabels": [ + "RetryableWriteError" + ], + "closeConnection": false + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "x": 11 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "InsertOne succeeds after HostNotFound", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 7, + "errorLabels": [ + "RetryableWriteError" + ], + "closeConnection": false + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "x": 11 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "InsertOne succeeds after HostUnreachable", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 6, + "errorLabels": [ + "RetryableWriteError" + ], + "closeConnection": false + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "x": 11 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "InsertOne succeeds after SocketException", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 9001, + "errorLabels": [ + "RetryableWriteError" + ], + "closeConnection": false + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "x": 11 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "InsertOne succeeds after NetworkTimeout", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 89, + "errorLabels": [ + "RetryableWriteError" + ], + "closeConnection": false + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "x": 11 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "InsertOne succeeds after ExceededTimeLimit", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 262, + "errorLabels": [ + "RetryableWriteError" + ], + "closeConnection": false + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "x": 11 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "InsertOne succeeds after WriteConcernError InterruptedAtShutdown", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorLabels": [ + "RetryableWriteError" + ], + "writeConcernError": { + "code": 11600, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "x": 11 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "InsertOne succeeds after WriteConcernError InterruptedDueToReplStateChange", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorLabels": [ + "RetryableWriteError" + ], + "writeConcernError": { + "code": 11602, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "x": 11 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "InsertOne succeeds after WriteConcernError PrimarySteppedDown", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorLabels": [ + "RetryableWriteError" + ], + "writeConcernError": { + "code": 189, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "x": 11 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "InsertOne succeeds after WriteConcernError ShutdownInProgress", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorLabels": [ + "RetryableWriteError" + ], + "writeConcernError": { + "code": 91, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "x": 11 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 1 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "InsertOne fails after multiple retryable writeConcernErrors", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorLabels": [ + "RetryableWriteError" + ], + "writeConcernError": { + "code": 91, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "x": 11 + } + }, + "expectError": { + "isError": true, + "errorLabelsContain": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/insertOne-errorLabels.yml b/test/spec/retryable-writes/unified/insertOne-errorLabels.yml new file mode 100644 index 0000000000..ce52421772 --- /dev/null +++ b/test/spec/retryable-writes/unified/insertOne-errorLabels.yml @@ -0,0 +1,610 @@ +description: insertOne-errorLabels + +schemaVersion: '1.3' + +runOnRequirements: + - + minServerVersion: 4.3.1 # failCommand errorLabels option + topologies: [ replicaset, sharded, load-balanced ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: [] + +tests: + - + description: 'InsertOne succeeds with RetryableWriteError from server' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorCode: 112 # WriteConflict, not a retryable error code + # Override server behavior: send RetryableWriteError label with non-retryable error code + errorLabels: + - RetryableWriteError + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 1, x: 11 } + # Driver retries operation and it succeeds + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 1 } } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'InsertOne fails if server does not return RetryableWriteError' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorCode: 11600 # InterruptedAtShutdown, normally a retryable error code + errorLabels: [] # Override server behavior: do not send RetryableWriteError label with retryable code + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 1, x: 11 } + # Driver does not retry operation because there was no RetryableWriteError label on response + expectError: + isError: true + errorLabelsOmit: + - RetryableWriteError + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: [] + - + description: 'InsertOne succeeds after NotWritablePrimary' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorCode: 10107 + errorLabels: + - RetryableWriteError + closeConnection: false + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 1, x: 11 } + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 1 } } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'InsertOne succeeds after NotPrimaryOrSecondary' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorCode: 13436 + errorLabels: + - RetryableWriteError + closeConnection: false + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 1, x: 11 } + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 1 } } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'InsertOne succeeds after NotPrimaryNoSecondaryOk' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorCode: 13435 + errorLabels: + - RetryableWriteError + closeConnection: false + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 1, x: 11 } + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 1 } } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'InsertOne succeeds after InterruptedDueToReplStateChange' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorCode: 11602 + errorLabels: + - RetryableWriteError + closeConnection: false + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 1, x: 11 } + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 1 } } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'InsertOne succeeds after InterruptedAtShutdown' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorCode: 11600 + errorLabels: + - RetryableWriteError + closeConnection: false + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 1, x: 11 } + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 1 } } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'InsertOne succeeds after PrimarySteppedDown' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorCode: 189 + errorLabels: + - RetryableWriteError + closeConnection: false + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 1, x: 11 } + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 1 } } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'InsertOne succeeds after ShutdownInProgress' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorCode: 91 + errorLabels: + - RetryableWriteError + closeConnection: false + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 1, x: 11 } + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 1 } } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'InsertOne succeeds after HostNotFound' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorCode: 7 + errorLabels: + - RetryableWriteError + closeConnection: false + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 1, x: 11 } + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 1 } } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'InsertOne succeeds after HostUnreachable' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorCode: 6 + errorLabels: + - RetryableWriteError + closeConnection: false + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 1, x: 11 } + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 1 } } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'InsertOne succeeds after SocketException' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorCode: 9001 + errorLabels: + - RetryableWriteError + closeConnection: false + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 1, x: 11 } + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 1 } } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'InsertOne succeeds after NetworkTimeout' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorCode: 89 + errorLabels: + - RetryableWriteError + closeConnection: false + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 1, x: 11 } + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 1 } } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'InsertOne succeeds after ExceededTimeLimit' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorCode: 262 + errorLabels: + - RetryableWriteError + closeConnection: false + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 1, x: 11 } + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 1 } } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'InsertOne succeeds after WriteConcernError InterruptedAtShutdown' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorLabels: + - RetryableWriteError + writeConcernError: + code: 11600 + errmsg: 'Replication is being shut down' + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 1, x: 11 } + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 1 } } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'InsertOne succeeds after WriteConcernError InterruptedDueToReplStateChange' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorLabels: + - RetryableWriteError + writeConcernError: + code: 11602 + errmsg: 'Replication is being shut down' + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 1, x: 11 } + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 1 } } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'InsertOne succeeds after WriteConcernError PrimarySteppedDown' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorLabels: + - RetryableWriteError + writeConcernError: + code: 189 + errmsg: 'Replication is being shut down' + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 1, x: 11 } + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 1 } } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'InsertOne succeeds after WriteConcernError ShutdownInProgress' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorLabels: + - RetryableWriteError + writeConcernError: + code: 91 + errmsg: 'Replication is being shut down' + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 1, x: 11 } + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 1 } } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - + description: 'InsertOne fails after multiple retryable writeConcernErrors' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ insert ] + errorLabels: + - RetryableWriteError + writeConcernError: + code: 91 + errmsg: 'Replication is being shut down' + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 1, x: 11 } + expectError: + isError: true + errorLabelsContain: + - RetryableWriteError + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } # The write was still applied. diff --git a/test/spec/retryable-writes/unified/insertOne-noWritesPerformedError.yml b/test/spec/retryable-writes/unified/insertOne-noWritesPerformedError.yml index 3295d153dd..6d8e8e7d4b 100644 --- a/test/spec/retryable-writes/unified/insertOne-noWritesPerformedError.yml +++ b/test/spec/retryable-writes/unified/insertOne-noWritesPerformedError.yml @@ -29,11 +29,9 @@ tests: client: *client0 failPoint: configureFailPoint: failCommand - mode: - times: 2 + mode: { times: 2 } data: - failCommands: - - insert + failCommands: [ insert ] errorCode: 64 errorLabels: - NoWritesPerformed @@ -41,8 +39,7 @@ tests: - name: insertOne object: *collection0 arguments: - document: - x: 1 + document: { x: 1 } expectError: errorCode: 64 errorLabelsContain: diff --git a/test/spec/retryable-writes/unified/insertOne-serverErrors.json b/test/spec/retryable-writes/unified/insertOne-serverErrors.json index 0d0d639cd4..f404adcaf4 100644 --- a/test/spec/retryable-writes/unified/insertOne-serverErrors.json +++ b/test/spec/retryable-writes/unified/insertOne-serverErrors.json @@ -1,6 +1,6 @@ { "description": "retryable-writes insertOne serverErrors", - "schemaVersion": "1.0", + "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.0", @@ -11,7 +11,8 @@ { "minServerVersion": "4.1.7", "topologies": [ - "sharded" + "sharded", + "load-balanced" ] } ], @@ -165,6 +166,700 @@ ] } ] + }, + { + "description": "RetryableWriteError label is added based on top-level code in pre-4.4 server response", + "runOnRequirements": [ + { + "minServerVersion": "4.2", + "maxServerVersion": "4.2.99", + "topologies": [ + "replicaset", + "sharded" + ] + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 189 + } + } + } + }, + { + "name": "insertOne", + "object": "collection0", + "arguments": { + "document": { + "_id": 3, + "x": 33 + } + }, + "expectError": { + "errorLabelsContain": [ + "RetryableWriteError" + ] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "coll", + "documents": [ + { + "_id": 3, + "x": 33 + } + ] + }, + "commandName": "insert", + "databaseName": "retryable-writes-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "coll", + "documents": [ + { + "_id": 3, + "x": 33 + } + ] + }, + "commandName": "insert", + "databaseName": "retryable-writes-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "RetryableWriteError label is added based on writeConcernError in pre-4.4 mongod response", + "runOnRequirements": [ + { + "minServerVersion": "4.2", + "maxServerVersion": "4.2.99", + "topologies": [ + "replicaset" + ] + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "insert" + ], + "writeConcernError": { + "code": 91, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "name": "insertOne", + "object": "collection0", + "arguments": { + "document": { + "_id": 3, + "x": 33 + } + }, + "expectError": { + "errorLabelsContain": [ + "RetryableWriteError" + ] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "coll", + "documents": [ + { + "_id": 3, + "x": 33 + } + ] + }, + "commandName": "insert", + "databaseName": "retryable-writes-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "insert": "coll", + "documents": [ + { + "_id": 3, + "x": 33 + } + ] + }, + "commandName": "insert", + "databaseName": "retryable-writes-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "RetryableWriteError label is not added based on writeConcernError in pre-4.4 mongos response", + "runOnRequirements": [ + { + "minServerVersion": "4.2", + "maxServerVersion": "4.2.99", + "topologies": [ + "sharded" + ] + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "writeConcernError": { + "code": 91, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "name": "insertOne", + "object": "collection0", + "arguments": { + "document": { + "_id": 3, + "x": 33 + } + }, + "expectError": { + "errorLabelsOmit": [ + "RetryableWriteError" + ] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "insert": "coll", + "documents": [ + { + "_id": 3, + "x": 33 + } + ] + }, + "commandName": "insert", + "databaseName": "retryable-writes-tests" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "InsertOne succeeds after connection failure", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 3, + "x": 33 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 3 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "InsertOne fails after connection failure when retryWrites option is false", + "operations": [ + { + "object": "testRunner", + "name": "createEntities", + "arguments": { + "entities": [ + { + "client": { + "id": "client1", + "useMultipleMongoses": false, + "uriOptions": { + "retryWrites": false + } + } + }, + { + "database": { + "id": "database1", + "client": "client1", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection1", + "database": "database1", + "collectionName": "coll" + } + } + ] + } + }, + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client1", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection1", + "name": "insertOne", + "arguments": { + "document": { + "_id": 3, + "x": 33 + } + }, + "expectError": { + "isError": true, + "errorLabelsOmit": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "InsertOne fails after Interrupted", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "errorCode": 11601, + "closeConnection": false + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 3, + "x": 33 + } + }, + "expectError": { + "isError": true, + "errorLabelsOmit": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "InsertOne fails after WriteConcernError Interrupted", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "writeConcernError": { + "code": 11601, + "errmsg": "operation was interrupted" + } + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 3, + "x": 33 + } + }, + "expectError": { + "isError": true, + "errorLabelsOmit": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "InsertOne fails after WriteConcernError WriteConcernFailed", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "insert" + ], + "writeConcernError": { + "code": 64, + "codeName": "WriteConcernFailed", + "errmsg": "waiting for replication timed out", + "errInfo": { + "wtimeout": true + } + } + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 3, + "x": 33 + } + }, + "expectError": { + "isError": true, + "errorLabelsOmit": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "InsertOne fails with a RetryableWriteError label after two connection failures", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "insert" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 3, + "x": 33 + } + }, + "expectError": { + "isError": true, + "errorLabelsContain": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] } ] } diff --git a/test/spec/retryable-writes/unified/insertOne-serverErrors.yml b/test/spec/retryable-writes/unified/insertOne-serverErrors.yml index 76f8c4ff85..95fa71ec79 100644 --- a/test/spec/retryable-writes/unified/insertOne-serverErrors.yml +++ b/test/spec/retryable-writes/unified/insertOne-serverErrors.yml @@ -1,12 +1,12 @@ description: "retryable-writes insertOne serverErrors" -schemaVersion: "1.0" +schemaVersion: "1.9" runOnRequirements: - minServerVersion: "4.0" topologies: [ replicaset ] - minServerVersion: "4.1.7" - topologies: [ sharded ] + topologies: [ sharded, load-balanced ] createEntities: - client: @@ -75,3 +75,332 @@ tests: - { _id: 1, x: 11 } - { _id: 2, x: 22 } - { _id: 3, x: 33 } # The write was still applied + + - description: "RetryableWriteError label is added based on top-level code in pre-4.4 server response" + runOnRequirements: + - minServerVersion: "4.2" + maxServerVersion: "4.2.99" + topologies: [ replicaset, sharded ] + operations: + - name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + # Trigger the fail point twice to allow asserting the error label in + # the retry attempt's response. + mode: { times: 2 } + data: + failCommands: [ "insert" ] + errorCode: 189 # PrimarySteppedDown + - name: insertOne + object: *collection0 + arguments: + document: { _id: 3, x: 33 } + expectError: + errorLabelsContain: [ "RetryableWriteError" ] + expectEvents: + - client: *client0 + events: + - commandStartedEvent: &insertCommandStartedEvent + command: + insert: *collectionName + documents: [{ _id: 3, x: 33 }] + commandName: insert + databaseName: *databaseName + - commandStartedEvent: *insertCommandStartedEvent + outcome: + - collectionName: *collectionName + databaseName: *databaseName + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + + - description: "RetryableWriteError label is added based on writeConcernError in pre-4.4 mongod response" + runOnRequirements: + - minServerVersion: "4.2" + maxServerVersion: "4.2.99" + topologies: [ replicaset ] + operations: + - name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + # Trigger the fail point twice to allow asserting the error label in + # the retry attempt's response. + mode: { times: 2 } + data: + failCommands: [ "insert" ] + writeConcernError: + code: 91 # ShutdownInProgress + errmsg: "Replication is being shut down" + - name: insertOne + object: *collection0 + arguments: + document: { _id: 3, x: 33 } + expectError: + errorLabelsContain: [ "RetryableWriteError" ] + expectEvents: + - client: *client0 + events: + - commandStartedEvent: *insertCommandStartedEvent + - commandStartedEvent: *insertCommandStartedEvent + outcome: + - collectionName: *collectionName + databaseName: *databaseName + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + # writeConcernError doesn't prevent the server from applying the write + - { _id: 3, x: 33 } + + - description: "RetryableWriteError label is not added based on writeConcernError in pre-4.4 mongos response" + runOnRequirements: + - minServerVersion: "4.2" + maxServerVersion: "4.2.99" + topologies: [ sharded ] + operations: + - name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + # Trigger the fail point only once since a RetryableWriteError label + # will not be added and the write will not be retried. + mode: { times: 1 } + data: + failCommands: [ "insert" ] + writeConcernError: + code: 91 # ShutdownInProgress + errmsg: "Replication is being shut down" + - name: insertOne + object: *collection0 + arguments: + document: { _id: 3, x: 33 } + expectError: + errorLabelsOmit: [ "RetryableWriteError" ] + expectEvents: + - client: *client0 + events: + - commandStartedEvent: *insertCommandStartedEvent + outcome: + - collectionName: *collectionName + databaseName: *databaseName + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + # writeConcernError doesn't prevent the server from applying the write + - { _id: 3, x: 33 } + - + description: 'InsertOne succeeds after connection failure' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + closeConnection: true + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 3, x: 33 } + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 3 } } + outcome: + - + collectionName: *collectionName + databaseName: *databaseName + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'InsertOne fails after connection failure when retryWrites option is false' + operations: + - + object: testRunner + name: createEntities + arguments: + entities: + - client: + id: &client1 client1 + useMultipleMongoses: false + uriOptions: + retryWrites: false + - database: + id: &database1 database1 + client: *client1 + databaseName: *databaseName + - collection: + id: &collection1 collection1 + database: *database1 + collectionName: *collectionName + - + name: failPoint + object: testRunner + arguments: + client: *client1 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + closeConnection: true + - + object: *collection1 + name: insertOne + arguments: + document: { _id: 3, x: 33 } + expectError: + isError: true + # If retryWrites is false, the driver should not add the + # RetryableWriteError label to the error. + errorLabelsOmit: + - RetryableWriteError + outcome: + - + collectionName: *collectionName + databaseName: *databaseName + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - + description: 'InsertOne fails after Interrupted' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + errorCode: 11601 + closeConnection: false + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 3, x: 33 } + expectError: + isError: true + errorLabelsOmit: + - RetryableWriteError + outcome: + - + collectionName: *collectionName + databaseName: *databaseName + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - + description: 'InsertOne fails after WriteConcernError Interrupted' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + writeConcernError: + code: 11601 + errmsg: 'operation was interrupted' + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 3, x: 33 } + expectError: + isError: true + errorLabelsOmit: + - RetryableWriteError + outcome: + - + collectionName: *collectionName + databaseName: *databaseName + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } # The write was still applied. + - + description: 'InsertOne fails after WriteConcernError WriteConcernFailed' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ insert ] + writeConcernError: + code: 64 + codeName: WriteConcernFailed + errmsg: 'waiting for replication timed out' + errInfo: + wtimeout: true + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 3, x: 33 } + expectError: + isError: true + errorLabelsOmit: + - RetryableWriteError + outcome: + - + collectionName: *collectionName + databaseName: *databaseName + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } # The write was still applied. + - + description: 'InsertOne fails with a RetryableWriteError label after two connection failures' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ insert ] + closeConnection: true + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 3, x: 33 } + expectError: + isError: true + errorLabelsContain: + - RetryableWriteError + outcome: + - + collectionName: *collectionName + databaseName: *databaseName + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/insertOne.json b/test/spec/retryable-writes/unified/insertOne.json new file mode 100644 index 0000000000..61957415ed --- /dev/null +++ b/test/spec/retryable-writes/unified/insertOne.json @@ -0,0 +1,215 @@ +{ + "description": "insertOne", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "3.6", + "topologies": [ + "replicaset" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "InsertOne is committed on first attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 3, + "x": 33 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 3 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "InsertOne is not committed on first attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 3, + "x": 33 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 3 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "InsertOne is never committed", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 2 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "document": { + "_id": 3, + "x": 33 + } + }, + "expectError": { + "isError": true + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/insertOne.yml b/test/spec/retryable-writes/unified/insertOne.yml new file mode 100644 index 0000000000..50d7766b9c --- /dev/null +++ b/test/spec/retryable-writes/unified/insertOne.yml @@ -0,0 +1,115 @@ +description: insertOne + +schemaVersion: '1.0' + +runOnRequirements: + - + minServerVersion: '3.6' + topologies: [ replicaset ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'InsertOne is committed on first attempt' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 3, x: 33 } + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 3 } } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'InsertOne is not committed on first attempt' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 3, x: 33 } + expectResult: + $$unsetOrMatches: { insertedId: { $$unsetOrMatches: 3 } } + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + - + description: 'InsertOne is never committed' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 2 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: insertOne + arguments: + document: { _id: 3, x: 33 } + expectError: + isError: true + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/replaceOne-errorLabels.json b/test/spec/retryable-writes/unified/replaceOne-errorLabels.json new file mode 100644 index 0000000000..22c4561ae7 --- /dev/null +++ b/test/spec/retryable-writes/unified/replaceOne-errorLabels.json @@ -0,0 +1,300 @@ +{ + "description": "replaceOne-errorLabels", + "schemaVersion": "1.3", + "runOnRequirements": [ + { + "minServerVersion": "4.3.1", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "ReplaceOne succeeds with RetryableWriteError from server", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "update" + ], + "errorCode": 112, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "collection0", + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "_id": 1, + "x": 111 + } + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 111 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "ReplaceOne fails if server does not return RetryableWriteError", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "update" + ], + "errorCode": 11600, + "errorLabels": [] + } + } + } + }, + { + "object": "collection0", + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "_id": 1, + "x": 111 + } + }, + "expectError": { + "isError": true, + "errorLabelsOmit": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "ReplaceOne succeeds after PrimarySteppedDown", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "update" + ], + "errorCode": 189, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "collection0", + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "_id": 1, + "x": 111 + } + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 111 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "ReplaceOne succeeds after WriteConcernError ShutdownInProgress", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "update" + ], + "errorLabels": [ + "RetryableWriteError" + ], + "writeConcernError": { + "code": 91, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "object": "collection0", + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "_id": 1, + "x": 111 + } + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 111 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/replaceOne-errorLabels.yml b/test/spec/retryable-writes/unified/replaceOne-errorLabels.yml new file mode 100644 index 0000000000..38f271d563 --- /dev/null +++ b/test/spec/retryable-writes/unified/replaceOne-errorLabels.yml @@ -0,0 +1,170 @@ +description: replaceOne-errorLabels + +schemaVersion: '1.3' + +runOnRequirements: + - + minServerVersion: 4.3.1 # failCommand errorLabels option + topologies: [ replicaset, sharded, load-balanced ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'ReplaceOne succeeds with RetryableWriteError from server' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ update ] + errorCode: 112 # WriteConflict, not a retryable error code + # Override server behavior: send RetryableWriteError label with non-retryable error code + errorLabels: + - RetryableWriteError + - + object: *collection0 + name: replaceOne + arguments: + filter: { _id: 1 } + replacement: { _id: 1, x: 111 } + # Driver retries operation and it succeeds + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 111 } + - { _id: 2, x: 22 } + - + description: 'ReplaceOne fails if server does not return RetryableWriteError' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ update ] + errorCode: 11600 # InterruptedAtShutdown, normally a retryable error code + errorLabels: [] # Override server behavior: do not send RetryableWriteError label with retryable code + - + object: *collection0 + name: replaceOne + arguments: + filter: { _id: 1 } + replacement: { _id: 1, x: 111 } + # Driver does not retry operation because there was no RetryableWriteError label on response + expectError: + isError: true + errorLabelsOmit: + - RetryableWriteError + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - + description: 'ReplaceOne succeeds after PrimarySteppedDown' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ update ] + errorCode: 189 + errorLabels: + - RetryableWriteError + - + object: *collection0 + name: replaceOne + arguments: + filter: { _id: 1 } + replacement: { _id: 1, x: 111 } + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 111 } + - { _id: 2, x: 22 } + - + description: 'ReplaceOne succeeds after WriteConcernError ShutdownInProgress' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ update ] + errorLabels: + - RetryableWriteError + writeConcernError: + code: 91 + errmsg: 'Replication is being shut down' + - + object: *collection0 + name: replaceOne + arguments: + filter: { _id: 1 } + replacement: { _id: 1, x: 111 } + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 111 } + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/replaceOne-serverErrors.json b/test/spec/retryable-writes/unified/replaceOne-serverErrors.json new file mode 100644 index 0000000000..c957db7244 --- /dev/null +++ b/test/spec/retryable-writes/unified/replaceOne-serverErrors.json @@ -0,0 +1,118 @@ +{ + "description": "replaceOne-serverErrors", + "schemaVersion": "1.3", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "ReplaceOne fails with a RetryableWriteError label after two connection failures", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "update" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "_id": 1, + "x": 111 + } + }, + "expectError": { + "isError": true, + "errorLabelsContain": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/replaceOne-serverErrors.yml b/test/spec/retryable-writes/unified/replaceOne-serverErrors.yml new file mode 100644 index 0000000000..b6f2f65bdf --- /dev/null +++ b/test/spec/retryable-writes/unified/replaceOne-serverErrors.yml @@ -0,0 +1,68 @@ +description: replaceOne-serverErrors + +schemaVersion: '1.3' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: [ replicaset ] + - + minServerVersion: 4.1.7 + topologies: [ sharded, load-balanced ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'ReplaceOne fails with a RetryableWriteError label after two connection failures' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ update ] + closeConnection: true + - + object: *collection0 + name: replaceOne + arguments: + filter: { _id: 1 } + replacement: { _id: 1, x: 111 } + expectError: + isError: true + errorLabelsContain: + - RetryableWriteError + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/replaceOne.json b/test/spec/retryable-writes/unified/replaceOne.json new file mode 100644 index 0000000000..e58625bb5e --- /dev/null +++ b/test/spec/retryable-writes/unified/replaceOne.json @@ -0,0 +1,212 @@ +{ + "description": "replaceOne", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "3.6", + "topologies": [ + "replicaset" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "ReplaceOne is committed on first attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + } + } + } + }, + { + "object": "collection0", + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "_id": 1, + "x": 111 + } + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 111 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "ReplaceOne is not committed on first attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "_id": 1, + "x": 111 + } + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 111 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "ReplaceOne is never committed", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 2 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "_id": 1, + "x": 111 + } + }, + "expectError": { + "isError": true + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/replaceOne.yml b/test/spec/retryable-writes/unified/replaceOne.yml new file mode 100644 index 0000000000..0cc92fb28f --- /dev/null +++ b/test/spec/retryable-writes/unified/replaceOne.yml @@ -0,0 +1,120 @@ +description: replaceOne + +schemaVersion: '1.0' + +runOnRequirements: + - + minServerVersion: '3.6' + topologies: [ replicaset ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'ReplaceOne is committed on first attempt' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + - + object: *collection0 + name: replaceOne + arguments: + filter: { _id: 1 } + replacement: { _id: 1, x: 111 } + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 111 } + - { _id: 2, x: 22 } + - + description: 'ReplaceOne is not committed on first attempt' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: replaceOne + arguments: + filter: { _id: 1 } + replacement: { _id: 1, x: 111 } + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 111 } + - { _id: 2, x: 22 } + - + description: 'ReplaceOne is never committed' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 2 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: replaceOne + arguments: + filter: { _id: 1 } + replacement: { _id: 1, x: 111 } + expectError: + isError: true + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/updateMany.json b/test/spec/retryable-writes/unified/updateMany.json new file mode 100644 index 0000000000..260b7ad1c6 --- /dev/null +++ b/test/spec/retryable-writes/unified/updateMany.json @@ -0,0 +1,92 @@ +{ + "description": "updateMany", + "schemaVersion": "1.3", + "runOnRequirements": [ + { + "minServerVersion": "3.6", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": true + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "UpdateMany ignores retryWrites", + "operations": [ + { + "object": "collection0", + "name": "updateMany", + "arguments": { + "filter": {}, + "update": { + "$inc": { + "x": 1 + } + } + }, + "expectResult": { + "matchedCount": 2, + "modifiedCount": 2, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 23 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/updateMany.yml b/test/spec/retryable-writes/unified/updateMany.yml new file mode 100644 index 0000000000..a1843b9d2a --- /dev/null +++ b/test/spec/retryable-writes/unified/updateMany.yml @@ -0,0 +1,54 @@ +description: updateMany + +schemaVersion: '1.3' + +runOnRequirements: + - + minServerVersion: '3.6' + topologies: [ replicaset, sharded, load-balanced ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: true + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'UpdateMany ignores retryWrites' + operations: + - + object: *collection0 + name: updateMany + arguments: + filter: { } + update: { $inc: { x: 1 } } + expectResult: + matchedCount: 2 + modifiedCount: 2 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 23 } diff --git a/test/spec/retryable-writes/unified/updateOne-errorLabels.json b/test/spec/retryable-writes/unified/updateOne-errorLabels.json new file mode 100644 index 0000000000..e44cef45f6 --- /dev/null +++ b/test/spec/retryable-writes/unified/updateOne-errorLabels.json @@ -0,0 +1,304 @@ +{ + "description": "updateOne-errorLabels", + "schemaVersion": "1.3", + "runOnRequirements": [ + { + "minServerVersion": "4.3.1", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "UpdateOne succeeds with RetryableWriteError from server", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "update" + ], + "errorCode": 112, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "UpdateOne fails if server does not return RetryableWriteError", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "update" + ], + "errorCode": 11600, + "errorLabels": [] + } + } + } + }, + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + }, + "expectError": { + "isError": true, + "errorLabelsOmit": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "UpdateOne succeeds after PrimarySteppedDown", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "update" + ], + "errorCode": 189, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "UpdateOne succeeds after WriteConcernError ShutdownInProgress", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "update" + ], + "errorLabels": [ + "RetryableWriteError" + ], + "writeConcernError": { + "code": 91, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/updateOne-errorLabels.yml b/test/spec/retryable-writes/unified/updateOne-errorLabels.yml new file mode 100644 index 0000000000..f530e8dba4 --- /dev/null +++ b/test/spec/retryable-writes/unified/updateOne-errorLabels.yml @@ -0,0 +1,170 @@ +description: updateOne-errorLabels + +schemaVersion: '1.3' + +runOnRequirements: + - + minServerVersion: 4.3.1 # failCommand errorLabels option + topologies: [ replicaset, sharded, load-balanced ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'UpdateOne succeeds with RetryableWriteError from server' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ update ] + errorCode: 112 # WriteConflict, not a retryable error code + # Override server behavior: send RetryableWriteError label with non-retryable error code + errorLabels: + - RetryableWriteError + - + object: *collection0 + name: updateOne + arguments: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + # Driver retries operation and it succeeds + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 22 } + - + description: 'UpdateOne fails if server does not return RetryableWriteError' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ update ] + errorCode: 11600 # InterruptedAtShutdown, normally a retryable error code + errorLabels: [] # Override server behavior: do not send RetryableWriteError label with retryable code + - + object: *collection0 + name: updateOne + arguments: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + # Driver does not retry operation because there was no RetryableWriteError label on response + expectError: + isError: true + errorLabelsOmit: + - RetryableWriteError + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - + description: 'UpdateOne succeeds after PrimarySteppedDown' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ update ] + errorCode: 189 + errorLabels: + - RetryableWriteError + - + object: *collection0 + name: updateOne + arguments: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 22 } + - + description: 'UpdateOne succeeds after WriteConcernError ShutdownInProgress' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [ update ] + errorLabels: + - RetryableWriteError + writeConcernError: + code: 91 + errmsg: 'Replication is being shut down' + - + object: *collection0 + name: updateOne + arguments: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/updateOne-serverErrors.json b/test/spec/retryable-writes/unified/updateOne-serverErrors.json new file mode 100644 index 0000000000..648834ada4 --- /dev/null +++ b/test/spec/retryable-writes/unified/updateOne-serverErrors.json @@ -0,0 +1,119 @@ +{ + "description": "updateOne-serverErrors", + "schemaVersion": "1.3", + "runOnRequirements": [ + { + "minServerVersion": "4.0", + "topologies": [ + "replicaset" + ] + }, + { + "minServerVersion": "4.1.7", + "topologies": [ + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "UpdateOne fails with a RetryableWriteError label after two connection failures", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "update" + ], + "closeConnection": true + } + } + } + }, + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + }, + "expectError": { + "isError": true, + "errorLabelsContain": [ + "RetryableWriteError" + ] + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/updateOne-serverErrors.yml b/test/spec/retryable-writes/unified/updateOne-serverErrors.yml new file mode 100644 index 0000000000..6cd7281db1 --- /dev/null +++ b/test/spec/retryable-writes/unified/updateOne-serverErrors.yml @@ -0,0 +1,71 @@ +# This file was created automatically using mongodb-spec-converter. +# Please review the generated file, then remove this notice. + +description: updateOne-serverErrors + +schemaVersion: '1.3' + +runOnRequirements: + - + minServerVersion: '4.0' + topologies: [ replicaset ] + - + minServerVersion: 4.1.7 + topologies: [ sharded, load-balanced ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'UpdateOne fails with a RetryableWriteError label after two connection failures' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + failCommands: [ update ] + closeConnection: true + - + object: *collection0 + name: updateOne + arguments: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + expectError: + isError: true + errorLabelsContain: + - RetryableWriteError + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } diff --git a/test/spec/retryable-writes/unified/updateOne.json b/test/spec/retryable-writes/unified/updateOne.json new file mode 100644 index 0000000000..7947cef3c0 --- /dev/null +++ b/test/spec/retryable-writes/unified/updateOne.json @@ -0,0 +1,394 @@ +{ + "description": "updateOne", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "3.6", + "topologies": [ + "replicaset" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll" + } + } + ], + "initialData": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "tests": [ + { + "description": "UpdateOne is committed on first attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + } + } + } + }, + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "UpdateOne is not committed on first attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "UpdateOne is never committed", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 2 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + }, + "expectError": { + "isError": true + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "UpdateOne with upsert is committed on first attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + } + } + } + }, + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": 3, + "x": 33 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "upsert": true + }, + "expectResult": { + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 1, + "upsertedId": 3 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 34 + } + ] + } + ] + }, + { + "description": "UpdateOne with upsert is not committed on first attempt", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 1 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": 3, + "x": 33 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "upsert": true + }, + "expectResult": { + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 1, + "upsertedId": 3 + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 34 + } + ] + } + ] + }, + { + "description": "UpdateOne with upsert is never committed", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "onPrimaryTransactionalWrite", + "mode": { + "times": 2 + }, + "data": { + "failBeforeCommitExceptionCode": 1 + } + } + } + }, + { + "object": "collection0", + "name": "updateOne", + "arguments": { + "filter": { + "_id": 3, + "x": 33 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "upsert": true + }, + "expectError": { + "isError": true + } + } + ], + "outcome": [ + { + "collectionName": "coll", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ] + } + ] +} diff --git a/test/spec/retryable-writes/unified/updateOne.yml b/test/spec/retryable-writes/unified/updateOne.yml new file mode 100644 index 0000000000..55c42c1f4f --- /dev/null +++ b/test/spec/retryable-writes/unified/updateOne.yml @@ -0,0 +1,213 @@ +description: updateOne + +schemaVersion: '1.0' + +runOnRequirements: + - + minServerVersion: '3.6' + topologies: [ replicaset ] + +createEntities: + - + client: + id: &client0 client0 + useMultipleMongoses: false + - + database: + id: &database0 database0 + client: *client0 + databaseName: &database_name retryable-writes-tests + - + collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection_name coll + +initialData: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + +tests: + - + description: 'UpdateOne is committed on first attempt' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + - + object: *collection0 + name: updateOne + arguments: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 22 } + - + description: 'UpdateOne is not committed on first attempt' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: updateOne + arguments: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 12 } + - { _id: 2, x: 22 } + - + description: 'UpdateOne is never committed' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 2 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: updateOne + arguments: + filter: { _id: 1 } + update: { $inc: { x: 1 } } + expectError: + isError: true + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - + description: 'UpdateOne with upsert is committed on first attempt' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + - + object: *collection0 + name: updateOne + arguments: + filter: { _id: 3, x: 33 } + update: { $inc: { x: 1 } } + upsert: true + expectResult: + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 1 + upsertedId: 3 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 34 } + - + description: 'UpdateOne with upsert is not committed on first attempt' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 1 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: updateOne + arguments: + filter: { _id: 3, x: 33 } + update: { $inc: { x: 1 } } + upsert: true + expectResult: + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 1 + upsertedId: 3 + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 34 } + - + description: 'UpdateOne with upsert is never committed' + operations: + - + name: failPoint + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: onPrimaryTransactionalWrite + mode: { times: 2 } + data: + failBeforeCommitExceptionCode: 1 + - + object: *collection0 + name: updateOne + arguments: + filter: { _id: 3, x: 33 } + update: { $inc: { x: 1 } } + upsert: true + expectError: + isError: true + outcome: + - + collectionName: *collection_name + databaseName: *database_name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } diff --git a/test/spec/unified-test-format/valid-fail/entity-findCursor-malformed.json b/test/spec/unified-test-format/valid-fail/entity-findCursor-malformed.json new file mode 100644 index 0000000000..0956efa4c8 --- /dev/null +++ b/test/spec/unified-test-format/valid-fail/entity-findCursor-malformed.json @@ -0,0 +1,44 @@ +{ + "description": "entity-findCursor-malformed", + "schemaVersion": "1.3", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "database0Name" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "databaseName": "database0Name", + "collectionName": "coll0", + "documents": [] + } + ], + "tests": [ + { + "description": "createFindCursor fails if filter is not specified", + "operations": [ + { + "name": "createFindCursor", + "object": "collection0", + "saveResultAsEntity": "cursor0" + } + ] + } + ] +} diff --git a/test/spec/unified-test-format/valid-fail/entity-findCursor-malformed.yml b/test/spec/unified-test-format/valid-fail/entity-findCursor-malformed.yml new file mode 100644 index 0000000000..d7cf4856de --- /dev/null +++ b/test/spec/unified-test-format/valid-fail/entity-findCursor-malformed.yml @@ -0,0 +1,31 @@ +# This test is split out into a separate file to accommodate drivers that validate operation structure while decoding +# from JSON/YML. Such drivers fail to decode any files containing invalid operations. Combining this test in a file +# with other entity-findCursor valid-fail tests, which test failures that occur during test execution, would prevent +# such drivers from decoding the file and running any of the tests. +description: entity-findCursor-malformed + +schemaVersion: '1.3' + +createEntities: + - client: + id: &client0 client0 + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name database0Name + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + +initialData: + - databaseName: *database0Name + collectionName: *collection0Name + documents: [] + +tests: + - description: createFindCursor fails if filter is not specified + operations: + - name: createFindCursor + object: *collection0 + saveResultAsEntity: &cursor0 cursor0 diff --git a/test/spec/unified-test-format/valid-fail/entity-findCursor.json b/test/spec/unified-test-format/valid-fail/entity-findCursor.json new file mode 100644 index 0000000000..389e448c06 --- /dev/null +++ b/test/spec/unified-test-format/valid-fail/entity-findCursor.json @@ -0,0 +1,52 @@ +{ + "description": "entity-findCursor", + "schemaVersion": "1.3", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "database0Name" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "databaseName": "database0Name", + "collectionName": "coll0", + "documents": [] + } + ], + "tests": [ + { + "description": "iterateUntilDocumentOrError fails if it references a nonexistent entity", + "operations": [ + { + "name": "iterateUntilDocumentOrError", + "object": "cursor0" + } + ] + }, + { + "description": "close fails if it references a nonexistent entity", + "operations": [ + { + "name": "close", + "object": "cursor0" + } + ] + } + ] +} diff --git a/test/spec/unified-test-format/valid-fail/entity-findCursor.yml b/test/spec/unified-test-format/valid-fail/entity-findCursor.yml new file mode 100644 index 0000000000..d796c132d2 --- /dev/null +++ b/test/spec/unified-test-format/valid-fail/entity-findCursor.yml @@ -0,0 +1,31 @@ +description: entity-findCursor + +schemaVersion: '1.3' + +createEntities: + - client: + id: &client0 client0 + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name database0Name + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + +initialData: + - databaseName: *database0Name + collectionName: *collection0Name + documents: [] + +tests: + - description: iterateUntilDocumentOrError fails if it references a nonexistent entity + operations: + - name: iterateUntilDocumentOrError + object: cursor0 + + - description: close fails if it references a nonexistent entity + operations: + - name: close + object: cursor0 diff --git a/test/spec/unified-test-format/valid-fail/ignoreResultAndError-malformed.json b/test/spec/unified-test-format/valid-fail/ignoreResultAndError-malformed.json new file mode 100644 index 0000000000..b64779c723 --- /dev/null +++ b/test/spec/unified-test-format/valid-fail/ignoreResultAndError-malformed.json @@ -0,0 +1,48 @@ +{ + "description": "ignoreResultAndError-malformed", + "schemaVersion": "1.3", + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": true + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "database0Name" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "database0Name", + "documents": [] + } + ], + "tests": [ + { + "description": "malformed operation fails if ignoreResultAndError is true", + "operations": [ + { + "name": "insertOne", + "object": "collection0", + "arguments": { + "foo": "bar" + }, + "ignoreResultAndError": true + } + ] + } + ] +} diff --git a/test/spec/unified-test-format/valid-fail/ignoreResultAndError-malformed.yml b/test/spec/unified-test-format/valid-fail/ignoreResultAndError-malformed.yml new file mode 100644 index 0000000000..4822bbe625 --- /dev/null +++ b/test/spec/unified-test-format/valid-fail/ignoreResultAndError-malformed.yml @@ -0,0 +1,34 @@ +# This test is split out into a separate file to accommodate drivers that validate operation structure while decoding +# from JSON/YML. Such drivers fail to decode any files containing invalid operations. Combining this test in a file +# with other ignoreResultAndError valid-fail tests, which test failures that occur during test execution, would prevent +# such drivers from decoding the file and running any of the tests. +description: ignoreResultAndError-malformed + +schemaVersion: '1.3' + +createEntities: + - client: + id: &client0 client0 + useMultipleMongoses: true + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name database0Name + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: [] + +tests: + - description: malformed operation fails if ignoreResultAndError is true + operations: + - name: insertOne + object: *collection0 + arguments: + foo: bar + ignoreResultAndError: true diff --git a/test/spec/unified-test-format/valid-fail/ignoreResultAndError.json b/test/spec/unified-test-format/valid-fail/ignoreResultAndError.json index 4457040b4f..01b2421a9f 100644 --- a/test/spec/unified-test-format/valid-fail/ignoreResultAndError.json +++ b/test/spec/unified-test-format/valid-fail/ignoreResultAndError.json @@ -54,19 +54,6 @@ "ignoreResultAndError": false } ] - }, - { - "description": "malformed operation fails if ignoreResultAndError is true", - "operations": [ - { - "name": "insertOne", - "object": "collection0", - "arguments": { - "foo": "bar" - }, - "ignoreResultAndError": true - } - ] } ] } diff --git a/test/spec/unified-test-format/valid-fail/ignoreResultAndError.yml b/test/spec/unified-test-format/valid-fail/ignoreResultAndError.yml index 52498627a5..802c601f92 100644 --- a/test/spec/unified-test-format/valid-fail/ignoreResultAndError.yml +++ b/test/spec/unified-test-format/valid-fail/ignoreResultAndError.yml @@ -33,11 +33,3 @@ tests: # Insert the same document to force a DuplicateKey error. document: *insertDocument ignoreResultAndError: false - - - description: malformed operation fails if ignoreResultAndError is true - operations: - - name: insertOne - object: *collection0 - arguments: - foo: bar - ignoreResultAndError: true diff --git a/test/spec/unified-test-format/valid-fail/operation-unsupported.json b/test/spec/unified-test-format/valid-fail/operation-unsupported.json new file mode 100644 index 0000000000..d8ef5ab1c8 --- /dev/null +++ b/test/spec/unified-test-format/valid-fail/operation-unsupported.json @@ -0,0 +1,22 @@ +{ + "description": "operation-unsupported", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + } + ], + "tests": [ + { + "description": "Unsupported operation", + "operations": [ + { + "name": "unsupportedOperation", + "object": "client0" + } + ] + } + ] +} diff --git a/test/spec/unified-test-format/valid-fail/operation-unsupported.yml b/test/spec/unified-test-format/valid-fail/operation-unsupported.yml new file mode 100644 index 0000000000..ba311637c0 --- /dev/null +++ b/test/spec/unified-test-format/valid-fail/operation-unsupported.yml @@ -0,0 +1,13 @@ +description: "operation-unsupported" + +schemaVersion: "1.0" + +createEntities: + - client: + id: &client0 client0 + +tests: + - description: "Unsupported operation" + operations: + - name: unsupportedOperation + object: *client0 diff --git a/test/tools/unified-spec-runner/entities.ts b/test/tools/unified-spec-runner/entities.ts index 3289a2932d..07a3c36330 100644 --- a/test/tools/unified-spec-runner/entities.ts +++ b/test/tools/unified-spec-runner/entities.ts @@ -1,5 +1,4 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { expect } from 'chai'; +import { AssertionError, expect } from 'chai'; import { EventEmitter } from 'events'; import { @@ -304,7 +303,7 @@ export class UnifiedMongoClient extends MongoClient { case 'all': return [...this.commandEvents, ...this.cmapEvents, ...this.sdamEvents]; default: - throw new Error(`Unknown eventType: ${eventType}`); + throw new AssertionError(`Unknown eventType: ${eventType}`); } } @@ -362,7 +361,15 @@ export class FailPointMap extends Map { let address: string; if (addressOrClient instanceof MongoClient) { client = addressOrClient; - address = client.topology!.s.seedlist.join(','); + address = client.topology?.s.seedlist.join(','); + if (client.topology?.s.credentials) { + if ( + client.topology.s.credentials.mechanism === 'DEFAULT' || + client.topology.s.credentials.mechanism.startsWith('SCRAM') + ) { + address = `${client.topology.s.credentials.username}:${client.topology.s.credentials.password}@${address}`; + } + } } else { // create a new client address = addressOrClient.toString(); @@ -483,7 +490,7 @@ export class EntitiesMap extends Map { mapOf(type: EntityTypeId): EntitiesMap { const ctor = ENTITY_CTORS.get(type); if (!ctor) { - throw new Error(`Unknown type ${type}`); + throw new AssertionError(`Unknown type ${type}`); } return new EntitiesMap(Array.from(this.entries()).filter(([, e]) => e instanceof ctor)); } @@ -515,8 +522,8 @@ export class EntitiesMap extends Map { getEntity(type: EntityTypeId, key: string, assertExists = true): Entity | undefined { const entity = this.get(key); if (!entity) { - if (assertExists) throw new Error(`Entity '${key}' does not exist`); - return; + if (assertExists) throw new AssertionError(`Entity '${key}' does not exist`); + return undefined; } if (NO_INSTANCE_CHECK.includes(type)) { // Skip constructor checks for interfaces. @@ -524,10 +531,10 @@ export class EntitiesMap extends Map { } const ctor = ENTITY_CTORS.get(type); if (!ctor) { - throw new Error(`Unknown type ${type}`); + throw new AssertionError(`Unknown type ${type}`); } if (!(entity instanceof ctor)) { - throw new Error(`${key} is not an instance of ${type}`); + throw new AssertionError(`${key} is not an instance of ${type}`); } return entity; } @@ -579,11 +586,17 @@ export class EntitiesMap extends Map { uri = makeConnectionString(config.url({ useMultipleMongoses }), entity.client.uriOptions); } const client = new UnifiedMongoClient(uri, entity.client); - new EntityEventRegistry(client, entity.client, map).register(); try { + new EntityEventRegistry(client, entity.client, map).register(); await client.connect(); } catch (error) { console.error(ejson`failed to connect entity ${entity}`); + // In the case where multiple clients are defined in the test and any one of them failed + // to connect, but others did succeed, we need to ensure all open clients are closed. + const clients = map.mapOf('client'); + for (const clientEntry of clients.values()) { + await clientEntry.close(); + } throw error; } map.set(entity.client.id, client); @@ -659,13 +672,13 @@ export class EntitiesMap extends Map { } else if ('thread' in entity) { map.set(entity.thread.id, new UnifiedThread(entity.thread.id)); } else if ('stream' in entity) { - throw new Error(`Unsupported Entity ${JSON.stringify(entity)}`); + throw new AssertionError(`Unsupported Entity ${JSON.stringify(entity)}`); } else if ('clientEncryption' in entity) { - const clientEncryption = createClientEncryption(map, entity.clientEncryption); + const clientEncryption = await createClientEncryption(map, entity.clientEncryption); map.set(entity.clientEncryption.id, clientEncryption); } else { - throw new Error(`Unsupported Entity ${JSON.stringify(entity)}`); + throw new AssertionError(`Unsupported Entity ${JSON.stringify(entity)}`); } } return map; diff --git a/test/tools/unified-spec-runner/entity_event_registry.ts b/test/tools/unified-spec-runner/entity_event_registry.ts index 25c9c862a9..d62e106988 100644 --- a/test/tools/unified-spec-runner/entity_event_registry.ts +++ b/test/tools/unified-spec-runner/entity_event_registry.ts @@ -1,3 +1,5 @@ +import { AssertionError } from 'chai'; + import { COMMAND_FAILED, COMMAND_STARTED, @@ -60,11 +62,15 @@ export class EntityEventRegistry { register(): void { if (this.clientEntity.storeEventsAsEntities) { for (const { id, events } of this.clientEntity.storeEventsAsEntities) { + if (this.entitiesMap.has(id) || this.clientEntity.id === id) { + throw new AssertionError(`Duplicate id ${id} found while storing events as entities`); + } this.entitiesMap.set(id, []); for (const eventName of events) { // Need to map the event names to the Node event names. this.client.on(MAPPINGS[eventName], () => { - this.entitiesMap.getEntity('events', id).push({ + const events = this.entitiesMap.getEntity('events', id); + events.push({ name: eventName, observedAt: Date.now() }); diff --git a/test/tools/unified-spec-runner/match.ts b/test/tools/unified-spec-runner/match.ts index 45048b2bec..3a4d4e5e3d 100644 --- a/test/tools/unified-spec-runner/match.ts +++ b/test/tools/unified-spec-runner/match.ts @@ -22,6 +22,7 @@ import { ConnectionReadyEvent, type Document, Long, + MongoBulkWriteError, MongoError, MongoServerError, ObjectId, @@ -738,7 +739,12 @@ export function expectErrorCheck( if (expected.isClientError === false) { expect(error).to.be.instanceOf(MongoServerError); } else if (expected.isClientError === true) { - expect(error).not.to.be.instanceOf(MongoServerError); + if (error instanceof MongoBulkWriteError) { + // TODO(NODE-6281): do not throw MongoServerErrors from bulk write if the error is a client-side error + expect(error.errorResponse).not.to.be.instanceOf(MongoServerError); + } else { + expect(error).not.to.be.instanceOf(MongoServerError); + } } if (expected.errorContains != null) { diff --git a/test/tools/unified-spec-runner/operations.ts b/test/tools/unified-spec-runner/operations.ts index 9d71dddf55..045016c08e 100644 --- a/test/tools/unified-spec-runner/operations.ts +++ b/test/tools/unified-spec-runner/operations.ts @@ -1,6 +1,8 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { once, Writable } from 'node:stream'; + +import { Readable } from 'node:stream'; +import { pipeline } from 'node:stream/promises'; import { AssertionError, expect } from 'chai'; @@ -42,9 +44,11 @@ type RunOperationFn = ( ) => Promise; export const operations = new Map(); +export class MalformedOperationError extends AssertionError {} + operations.set('createEntities', async ({ entities, operation, testConfig }) => { if (!operation.arguments?.entities) { - throw new Error('encountered createEntities operation without entities argument'); + throw new AssertionError('encountered createEntities operation without entities argument'); } await EntitiesMap.createEntities(testConfig, null, operation.arguments.entities!, entities); }); @@ -57,7 +61,7 @@ operations.set('abortTransaction', async ({ entities, operation }) => { operations.set('aggregate', async ({ entities, operation }) => { const dbOrCollection = entities.get(operation.object) as Db | Collection; if (!(dbOrCollection instanceof Db || dbOrCollection instanceof Collection)) { - throw new Error(`Operation object '${operation.object}' must be a db or collection`); + throw new AssertionError(`Operation object '${operation.object}' must be a db or collection`); } const { pipeline, ...opts } = operation.arguments!; const cursor = dbOrCollection.aggregate(pipeline, opts); @@ -226,7 +230,7 @@ operations.set('close', async ({ entities, operation }) => { } catch {} /* eslint-enable no-empty */ - throw new Error(`No closable entity with key ${operation.object}`); + throw new AssertionError(`No closable entity with key ${operation.object}`); }); operations.set('commitTransaction', async ({ entities, operation }) => { @@ -237,7 +241,7 @@ operations.set('commitTransaction', async ({ entities, operation }) => { operations.set('createChangeStream', async ({ entities, operation }) => { const watchable = entities.get(operation.object); if (watchable == null || !('watch' in watchable)) { - throw new Error(`Entity ${operation.object} must be watchable`); + throw new AssertionError(`Entity ${operation.object} must be watchable`); } const { pipeline, ...args } = operation.arguments!; @@ -354,6 +358,9 @@ operations.set('failPoint', async ({ entities, operation }) => { operations.set('insertOne', async ({ entities, operation }) => { const collection = entities.getEntity('collection', operation.object); const { document, ...opts } = operation.arguments!; + if (!document) { + throw new MalformedOperationError('No document defined in the arguments for insertOne'); + } // Looping exposes the fact that we can generate _ids for inserted // documents and we don't want the original operation to get modified // and use the same _id for each insert. @@ -384,7 +391,7 @@ operations.set('iterateOnce', async ({ entities, operation }) => { operations.set('listCollections', async ({ entities, operation }) => { const db = entities.getEntity('db', operation.object); - const { filter, ...opts } = operation.arguments!; + const { filter, ...opts } = operation.arguments ?? { filter: {} }; return db.listCollections(filter, opts).toArray(); }); @@ -519,27 +526,28 @@ operations.set('delete', async ({ entities, operation }) => { operations.set('download', async ({ entities, operation }) => { const bucket = entities.getEntity('bucket', operation.object); - const stream = bucket.openDownloadStream(operation.arguments!.id); - return new Promise((resolve, reject) => { - const chunks: any[] = []; - stream.on('data', chunk => chunks.push(...chunk)); - stream.on('error', reject); - stream.on('end', () => resolve(chunks)); - }); + const { id, ...options } = operation.arguments ?? {}; + const stream = bucket.openDownloadStream(id, options); + return Buffer.concat(await stream.toArray()); }); -operations.set('upload', async ({ entities, operation }) => { +operations.set('downloadByName', async ({ entities, operation }) => { const bucket = entities.getEntity('bucket', operation.object); - const stream = bucket.openUploadStream(operation.arguments!.filename, { - chunkSizeBytes: operation.arguments?.chunkSizeBytes - }); + const { filename, ...options } = operation.arguments ?? {}; + const stream: Readable = bucket.openDownloadStreamByName(filename, options); - const data = Buffer.from(operation.arguments!.source.$$hexBytes, 'hex'); - const willFinish = once(stream, 'finish'); - stream.end(data); - await willFinish; + return Buffer.concat(await stream.toArray()); +}); + +operations.set('upload', async ({ entities, operation }) => { + const bucket = entities.getEntity('bucket', operation.object); + const { filename, source, ...options } = operation.arguments ?? {}; + const stream = bucket.openUploadStream(operation.arguments!.filename, options); + const filestream = Readable.from(Buffer.from(operation.arguments!.source.$$hexBytes, 'hex')); + + await pipeline(filestream, stream); return stream.gridFSFile?._id; }); @@ -579,7 +587,7 @@ operations.set('waitForEvent', async ({ entities, operation }) => { eventPromise, sleep(10000).then(() => Promise.reject( - new Error( + new AssertionError( `Timed out waiting for ${eventName}; captured [${mongoClient .getCapturedEvents('all') .map(e => e.constructor.name) @@ -674,7 +682,7 @@ operations.set('waitForPrimaryChange', async ({ entities, operation }) => { await Promise.race([ newPrimaryPromise, sleep(timeoutMS ?? 10000).then(() => - Promise.reject(new Error(`Timed out waiting for primary change on ${client}`)) + Promise.reject(new AssertionError(`Timed out waiting for primary change on ${client}`)) ) ]); }); @@ -694,7 +702,9 @@ operations.set('waitForThread', async ({ entities, operation }) => { const thread = entities.getEntity('thread', threadId, true); await Promise.race([ thread.finish(), - sleep(10000).then(() => Promise.reject(new Error(`Timed out waiting for thread: ${threadId}`))) + sleep(10000).then(() => + Promise.reject(new AssertionError(`Timed out waiting for thread: ${threadId}`)) + ) ]); }); @@ -747,10 +757,11 @@ operations.set('estimatedDocumentCount', async ({ entities, operation }) => { operations.set('runCommand', async ({ entities, operation }: OperationFunctionParams) => { const db = entities.getEntity('db', operation.object); - if (operation.arguments?.command == null) throw new Error('runCommand requires a command'); + if (operation.arguments?.command == null) + throw new AssertionError('runCommand requires a command'); const { command } = operation.arguments; - if (operation.arguments.timeoutMS != null) throw new Error('timeoutMS not supported'); + if (operation.arguments.timeoutMS != null) throw new AssertionError('timeoutMS not supported'); const options = { readPreference: operation.arguments.readPreference, @@ -946,7 +957,7 @@ export async function executeOperationAndCheck( if (operation.expectError) { expectErrorCheck(error, operation.expectError, entities); return; - } else if (!operation.ignoreResultAndError) { + } else if (!operation.ignoreResultAndError || error instanceof MalformedOperationError) { throw error; } } diff --git a/test/tools/unified-spec-runner/runner.ts b/test/tools/unified-spec-runner/runner.ts index 1c12611a84..e27d072f19 100644 --- a/test/tools/unified-spec-runner/runner.ts +++ b/test/tools/unified-spec-runner/runner.ts @@ -1,9 +1,16 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { expect } from 'chai'; +import { AssertionError, expect } from 'chai'; import { gte as semverGte, satisfies as semverSatisfies } from 'semver'; import type { MongoClient } from '../../mongodb'; -import { MONGODB_ERROR_CODES, ns, ReadPreference, TopologyType } from '../../mongodb'; +import { + MONGODB_ERROR_CODES, + MongoParseError, + MongoServerError, + ns, + ReadPreference, + TopologyType +} from '../../mongodb'; import { ejson } from '../utils'; import { AstrolabeResultsWriter } from './astrolabe_results_writer'; import { EntitiesMap, type UnifiedMongoClient } from './entities'; @@ -18,9 +25,15 @@ export function trace(message: string): void { } } +async function isAtlasDataLake(client: MongoClient): Promise { + const buildInfo = await client.db('admin').admin().buildInfo(); + return 'dataLake' in buildInfo; +} + async function terminateOpenTransactions(client: MongoClient) { // Note: killAllSession is not supported on serverless, see CLOUDP-84298 - if (process.env.SERVERLESS) { + // killAllSession is not allowed in ADL either. + if (process.env.SERVERLESS || (await isAtlasDataLake(client))) { return; } // TODO(NODE-3491): on sharded clusters this has to be run on each mongos @@ -101,7 +114,9 @@ async function runUnifiedTest( await terminateOpenTransactions(utilClient); // Must fetch parameters before checking runOnRequirements - ctx.configuration.parameters = await utilClient.db().admin().command({ getParameter: '*' }); + ctx.configuration.parameters = (await isAtlasDataLake(utilClient)) + ? {} + : await utilClient.db().admin().command({ getParameter: '*' }); // If test.runOnRequirements is specified, the test runner MUST skip the test unless one or more // runOnRequirement objects are satisfied. @@ -298,13 +313,28 @@ async function runUnifiedTest( */ export function runUnifiedSuite( specTests: uni.UnifiedSuite[], - skipFilter: uni.TestFilter = () => false + skipFilter: uni.TestFilter = () => false, + expectRuntimeError = false ): void { for (const unifiedSuite of specTests) { context(String(unifiedSuite.description), function () { for (const [index, test] of unifiedSuite.tests.entries()) { it(String(test.description === '' ? `Test ${index}` : test.description), async function () { - await runUnifiedTest(this, unifiedSuite, test, skipFilter); + if (expectRuntimeError) { + const error = await runUnifiedTest(this, unifiedSuite, test, skipFilter).catch( + error => error + ); + expect(error).to.satisfy(value => { + return ( + value instanceof AssertionError || + value instanceof MongoServerError || + value instanceof TypeError || + value instanceof MongoParseError + ); + }); + } else { + await runUnifiedTest(this, unifiedSuite, test, skipFilter); + } }); } }); diff --git a/test/tools/unified-spec-runner/unified-utils.ts b/test/tools/unified-spec-runner/unified-utils.ts index 2f36409875..25a5115a6d 100644 --- a/test/tools/unified-spec-runner/unified-utils.ts +++ b/test/tools/unified-spec-runner/unified-utils.ts @@ -1,5 +1,5 @@ import { EJSON } from 'bson'; -import { expect } from 'chai'; +import { AssertionError, expect } from 'chai'; import ConnectionString from 'mongodb-connection-string-url'; import { gte as semverGte, lte as semverLte } from 'semver'; import { isDeepStrictEqual } from 'util'; @@ -12,11 +12,13 @@ import { type DbOptions, type Document, getMongoDBClientEncryption, - type MongoClient + type MongoClient, + ReturnDocument } from '../../mongodb'; import { shouldRunServerlessTest } from '../../tools/utils'; import type { CmapEvent, CommandEvent, EntitiesMap, SdamEvent } from './entities'; import { matchesEvents } from './match'; +import { MalformedOperationError } from './operations'; import type { ClientEncryptionEntity, CollectionOrDatabaseOptions, @@ -51,7 +53,7 @@ export async function topologySatisfies( }[config.topologyType]; if (!Array.isArray(r.topologies)) { - throw new Error('Topology specification must be an array'); + throw new AssertionError('Topology specification must be an array'); } if (r.topologies.includes('sharded-replicaset') && topologyType === 'sharded') { @@ -61,7 +63,7 @@ export async function topologySatisfies( skipReason = `requires sharded-replicaset but shards.length=${shards.length}`; } } else { - if (!topologyType) throw new Error(`Topology undiscovered: ${config.topologyType}`); + if (!topologyType) throw new AssertionError(`Topology undiscovered: ${config.topologyType}`); ok &&= r.topologies.includes(topologyType); if (!ok && skipReason == null) { skipReason = `requires ${r.topologies} but discovered a ${topologyType} topology`; @@ -83,7 +85,8 @@ export async function topologySatisfies( } if (r.serverParameters) { - if (!config.parameters) throw new Error('Configuration does not have server parameters'); + if (!config.parameters) + throw new AssertionError('Configuration does not have server parameters'); for (const [name, value] of Object.entries(r.serverParameters)) { if (name in config.parameters) { ok &&= isDeepStrictEqual(config.parameters[name], value); @@ -199,7 +202,13 @@ export function patchCollectionOptions( export function translateOptions(options: Document): Document { const translatedOptions = { ...options }; if (options.returnDocument) { - translatedOptions.returnDocument = options.returnDocument.toLowerCase(); + const returnDocument = options.returnDocument.toLowerCase(); + if (![ReturnDocument.BEFORE, ReturnDocument.AFTER].includes(returnDocument)) { + throw new MalformedOperationError( + 'Return document must be specified as either "before" or "after"' + ); + } + translatedOptions.returnDocument = returnDocument; } return translatedOptions as Document; } @@ -250,7 +259,7 @@ export function getCSFLETestDataFromEnvironment(environment: Record { getMongoDBClientEncryption(); const { clientEncryptionOpts } = entity; @@ -503,7 +538,7 @@ export function createClientEncryption( const clientEntity = map.getEntity('client', keyVaultClient, false); if (!clientEntity) { - throw new Error( + throw new AssertionError( 'unable to get client entity required by client encryption entity in unified test' ); } @@ -537,7 +572,13 @@ export function createClientEncryption( }, {}); } - const kmsProviders = mergeKMSProviders(kmsProvidersFromTest, kmsProvidersFromEnvironment); + let kmsProviders; + try { + kmsProviders = mergeKMSProviders(kmsProvidersFromTest, kmsProvidersFromEnvironment); + } catch (error) { + await clientEntity.close(); + throw error; + } const autoEncryptionOptions: AutoEncryptionOptions = { keyVaultClient: clientEntity, diff --git a/test/unit/client-side-encryption/auto_encrypter.test.ts b/test/unit/client-side-encryption/auto_encrypter.test.ts index 08072512c7..1e13c0b07c 100644 --- a/test/unit/client-side-encryption/auto_encrypter.test.ts +++ b/test/unit/client-side-encryption/auto_encrypter.test.ts @@ -1,5 +1,6 @@ import { expect } from 'chai'; import * as fs from 'fs'; +import * as net from 'net'; import * as sinon from 'sinon'; // eslint-disable-next-line @typescript-eslint/no-restricted-imports @@ -37,7 +38,13 @@ const MOCK_MONGOCRYPTD_RESPONSE = readExtendedJsonToBuffer( const MOCK_KEYDOCUMENT_RESPONSE = readExtendedJsonToBuffer(`${__dirname}/data/key-document.json`); const MOCK_KMS_DECRYPT_REPLY = readHttpResponse(`${__dirname}/data/kms-decrypt-reply.txt`); -class MockClient {} +class MockClient { + options: any; + + constructor(options?: any) { + this.options = { options: options || {} }; + } +} const originalAccessKeyId = process.env.AWS_ACCESS_KEY_ID; const originalSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; @@ -105,15 +112,19 @@ describe('AutoEncrypter', function () { }); context('when mongocryptdURI is not specified', () => { - it('sets the ip address family to ipv4', function () { + it('sets family options', function () { expect(autoEncrypter).to.have.nested.property('_mongocryptdClient.s.options'); const options = autoEncrypter._mongocryptdClient?.s.options; - expect(options).to.have.property('family', 4); + if (net.getDefaultAutoSelectFamily) { + expect(options).to.have.property('autoSelectFamily', true); + } else { + expect(options).to.have.property('family', 4); + } }); }); context('when mongocryptdURI is specified', () => { - it('does not set the ip address family to ipv4', function () { + it('sets autoSelectFamily options', function () { const autoEncrypter = new AutoEncrypter(client, { ...autoEncrypterOptions, extraOptions: { mongocryptdURI: MongocryptdManager.DEFAULT_MONGOCRYPTD_URI } @@ -121,7 +132,7 @@ describe('AutoEncrypter', function () { expect(autoEncrypter).to.have.nested.property('_mongocryptdClient.s.options'); const options = autoEncrypter._mongocryptdClient?.s.options; - expect(options).not.to.have.property('family', 4); + expect(options).to.have.property('autoSelectFamily', true); }); }); }); diff --git a/test/unit/client-side-encryption/client_encryption.test.ts b/test/unit/client-side-encryption/client_encryption.test.ts index c83383d4e4..2ecf634771 100644 --- a/test/unit/client-side-encryption/client_encryption.test.ts +++ b/test/unit/client-side-encryption/client_encryption.test.ts @@ -19,6 +19,11 @@ import { Binary, BSON, deserialize } from '../../mongodb'; const { EJSON } = BSON; class MockClient { + options: any; + + constructor(options?: any) { + this.options = { options: options || {} }; + } db(dbName) { return { async createCollection(name, options) { diff --git a/test/unit/client-side-encryption/state_machine.test.ts b/test/unit/client-side-encryption/state_machine.test.ts index 518e63a26d..baec0cbece 100644 --- a/test/unit/client-side-encryption/state_machine.test.ts +++ b/test/unit/client-side-encryption/state_machine.test.ts @@ -148,6 +148,30 @@ describe('StateMachine', function () { }); }); + context('when socket options are provided', function () { + const stateMachine = new StateMachine({ + socketOptions: { autoSelectFamily: true, autoSelectFamilyAttemptTimeout: 300 } + } as any); + const request = new MockRequest(Buffer.from('foobar'), -1); + let connectOptions; + + it('passes them through to the socket', async function () { + sandbox.stub(tls, 'connect').callsFake((options, callback) => { + connectOptions = options; + this.fakeSocket = new MockSocket(callback); + return this.fakeSocket; + }); + const kmsRequestPromise = stateMachine.kmsRequest(request); + + await setTimeoutAsync(0); + this.fakeSocket.emit('data', Buffer.alloc(0)); + + await kmsRequestPromise; + expect(connectOptions.autoSelectFamily).to.equal(true); + expect(connectOptions.autoSelectFamilyAttemptTimeout).to.equal(300); + }); + }); + context('when tls options are provided', function () { context('when the options are insecure', function () { [ diff --git a/test/unit/error.test.ts b/test/unit/error.test.ts index c57ee71da6..6bab40d031 100644 --- a/test/unit/error.test.ts +++ b/test/unit/error.test.ts @@ -740,4 +740,33 @@ describe('MongoErrors', () => { }); }); }); + + describe('MongoWriteConcernError constructor', function () { + context('when no top-level code is provided', function () { + it('error.code is set to writeConcernError.code', function () { + const res = { + writeConcernError: { + code: 81, // nested code + errmsg: 'fake msg' + }, + ok: 1 + }; + expect(new MongoWriteConcernError(res).code).to.equal(81); + }); + }); + context('when top-level code is provided and writeConcernError.code exists', function () { + it('error.code equals the top-level code', function () { + const topLevelCode = 10; + const res = { + writeConcernError: { + code: 81, // nested code + errmsg: 'fake msg' + }, + ok: 1, + code: topLevelCode + }; + expect(new MongoWriteConcernError(res).code).to.equal(topLevelCode); + }); + }); + }); }); diff --git a/test/unit/index.test.ts b/test/unit/index.test.ts index 1478fa5ffc..980747c8c7 100644 --- a/test/unit/index.test.ts +++ b/test/unit/index.test.ts @@ -109,6 +109,7 @@ const EXPECTED_EXPORTS = [ 'MongoTransactionError', 'MongoUnexpectedServerResponseError', 'MongoWriteConcernError', + 'WriteConcernErrorResult', 'ObjectId', 'OrderedBulkOperation', 'ProfilingLevel', diff --git a/test/unit/tools/unifed-utils.test.ts b/test/unit/tools/unifed-utils.test.ts index ea8513940f..9745f1c570 100644 --- a/test/unit/tools/unifed-utils.test.ts +++ b/test/unit/tools/unifed-utils.test.ts @@ -4,19 +4,16 @@ import { mergeKMSProviders } from '../../tools/unified-spec-runner/unified-utils describe('parseOptions', function () { context('aws providers', function () { - it('does not configure the provider if none is given', function () { - const parsedProviders = mergeKMSProviders({}, {}); - expect(parsedProviders).not.to.have.property('aws'); + it('throws if none is given', function () { + expect(() => { + mergeKMSProviders({}, {}); + }).to.throw(); }); - it('configures the provider without credentials if an empty object is supplied', function () { - const parsedProviders = mergeKMSProviders( - { - aws: {} - }, - {} - ); - expect(parsedProviders.aws).deep.equal({}); + it('throws if an empty object is supplied', function () { + expect(() => { + mergeKMSProviders({ aws: {} }, {}); + }).to.throw(); }); it('replaces a $$placeholder value with the value from the environment', function () { @@ -37,18 +34,19 @@ describe('parseOptions', function () { }); }); - it('omits required fields if the field is not present in the kmsProviders', function () { - const parsedProviders = mergeKMSProviders( - { - aws: { - accessKeyId: { $$placeholder: 1 } + it('throws if required field is not present in the kmsProviders', function () { + expect(() => { + mergeKMSProviders( + { + aws: { + accessKeyId: { $$placeholder: 1 } + } + }, + { + aws: { accessKeyId: 'accessKeyId' } } - }, - { - aws: { accessKeyId: 'accessKeyId' } - } - ); - expect(parsedProviders.aws).not.to.have.property('secretAccessKey'); + ); + }).to.throw(); }); it('configures the provider with the exact credentials from the test', function () { @@ -76,9 +74,10 @@ describe('parseOptions', function () { }); }); context('local providers', function () { - it('does not configure the provider if none is given', function () { - const parsedProviders = mergeKMSProviders({}, {}); - expect(parsedProviders).not.to.have.property('local'); + it('throws if none is given', function () { + expect(() => { + mergeKMSProviders({}, {}); + }).to.throw(); }); it('configures the provider without credentials if an empty object is supplied', function () { @@ -127,19 +126,16 @@ describe('parseOptions', function () { }); context('azure', function () { - it('does not configure the provider if none is given', function () { - const parsedProviders = mergeKMSProviders({}, {}); - expect(parsedProviders).not.to.have.property('azure'); + it('throws if none is given', function () { + expect(() => { + mergeKMSProviders({}, {}); + }).to.throw(); }); - it('configures the provider without credentials if an empty object is supplied', function () { - const parsedProviders = mergeKMSProviders( - { - azure: {} - }, - {} - ); - expect(parsedProviders.azure).deep.equal({}); + it('throws if an empty object is supplied', function () { + expect(() => { + mergeKMSProviders({ azure: {} }, {}); + }).to.throw(); }); it('replaces a $$placeholder value with the value from the environment', function () { @@ -166,18 +162,19 @@ describe('parseOptions', function () { }); }); - it('omits required fields if the field is not present in the kmsProviders', function () { - const parsedProviders = mergeKMSProviders( - { - azure: { - tenantId: 'tenantId', - clientSecret: 'clientSecret', - identityPlatformEndpoint: 'identifyPlatformEndpoint' - } - }, - {} - ); - expect(parsedProviders.azure).not.to.have.property('clientId'); + it('throws if required field is not present in the kmsProviders', function () { + expect(() => { + mergeKMSProviders( + { + azure: { + tenantId: 'tenantId', + clientSecret: 'clientSecret', + identityPlatformEndpoint: 'identifyPlatformEndpoint' + } + }, + {} + ); + }).to.throw(); }); it('configures the provider with the exact credentials from the test otherwise', function () { @@ -209,19 +206,21 @@ describe('parseOptions', function () { }); context('gcp', function () { - it('does not configure the provider if none is given', function () { - const parsedProviders = mergeKMSProviders({}, {}); - expect(parsedProviders).not.to.have.property('gcp'); + it('throws if none is given', function () { + expect(() => { + mergeKMSProviders({}, {}); + }).throw(); }); - it('configures the provider without credentials if an empty object is supplied', function () { - const parsedProviders = mergeKMSProviders( - { - gcp: {} - }, - {} - ); - expect(parsedProviders.gcp).deep.equal({}); + it('throws if an empty object is supplied', function () { + expect(() => { + mergeKMSProviders( + { + gcp: {} + }, + {} + ); + }).to.throw(); }); it('replaces a $$placeholder value with the value from the environment', function () { @@ -246,17 +245,18 @@ describe('parseOptions', function () { }); }); - it('omits required fields if the field is not present in the kmsProviders', function () { - const parsedProviders = mergeKMSProviders( - { - gcp: { - email: 'email', - endPoint: 'endPoint' - } - }, - {} - ); - expect(parsedProviders.gcp).not.to.have.property('privateKey'); + it('throws if required field is not present in the kmsProviders', function () { + expect(() => { + mergeKMSProviders( + { + gcp: { + email: 'email', + endPoint: 'endPoint' + } + }, + {} + ); + }).to.throw(); }); it('configures the provider with the exact credentials from the test otherwise', function () { @@ -285,9 +285,10 @@ describe('parseOptions', function () { }); context('kmip', function () { - it('does not configure the provider if none is given', function () { - const parsedProviders = mergeKMSProviders({}, {}); - expect(parsedProviders).not.to.have.property('kmip'); + it('throws if none is given', function () { + expect(() => { + mergeKMSProviders({}, {}); + }).to.throw(); }); it('configures the provider without credentials if an empty object is supplied', function () {