From 8bfc97c83a0c0127a20530480543785d0fc18d7c Mon Sep 17 00:00:00 2001 From: emadum Date: Tue, 9 Feb 2021 14:46:22 -0500 Subject: [PATCH] add versioned api tests to evergreen --- .evergreen/config.yml | 26 ++++++- .evergreen/config.yml.in | 7 +- .evergreen/generate_evergreen_tasks.js | 22 ++++++ .evergreen/run-tests.sh | 2 +- src/cmap/auth/scram.ts | 11 ++- src/cmap/connect.ts | 13 +++- src/cmap/connection.ts | 7 +- src/connection_string.ts | 12 ++- src/mongo_client.ts | 19 ++--- src/operations/command.ts | 20 ++++- src/operations/find.ts | 6 +- src/operations/update.ts | 2 +- src/sdam/server.ts | 4 +- src/sdam/topology.ts | 9 ++- src/transactions.ts | 5 ++ test/functional/abstract_cursor.test.js | 8 +- test/functional/apm.test.js | 11 ++- test/functional/bulk.test.js | 8 +- test/functional/cmap/connection.test.js | 76 ++++++++++--------- test/functional/collations.test.js | 2 +- test/functional/core/topology.test.js | 23 +++--- test/functional/crud_spec.test.js | 4 + test/functional/cursor.test.js | 7 +- test/functional/gridfs_stream.test.js | 10 ++- test/functional/insert.test.js | 5 +- test/functional/max_staleness.test.js | 8 +- test/functional/operation_example.test.js | 7 +- .../operation_generators_example.test.js | 6 +- .../operation_promises_example.test.js | 2 +- test/functional/promote_values.test.js | 1 + test/functional/spec-runner/index.js | 3 +- .../unified-spec-runner/entities.ts | 8 +- test/functional/unified-spec-runner/match.ts | 9 +-- test/functional/unified-spec-runner/runner.ts | 7 +- .../unified-spec-runner/unified-utils.ts | 4 +- test/functional/uri.test.js | 2 +- test/functional/versioned-api.test.js | 23 +++--- test/functional/view.test.js | 2 +- test/tools/runner/config.js | 17 +++-- .../runner/filters/api_version_filter.js | 37 +++++++++ test/tools/runner/index.js | 10 ++- test/unit/legacy_compat.test.js | 11 ++- 42 files changed, 334 insertions(+), 142 deletions(-) create mode 100755 test/tools/runner/filters/api_version_filter.js diff --git a/.evergreen/config.yml b/.evergreen/config.yml index eb5ca2092c..8156eac593 100644 --- a/.evergreen/config.yml +++ b/.evergreen/config.yml @@ -81,6 +81,7 @@ functions: MONGODB_VERSION=${VERSION} TOPOLOGY=${TOPOLOGY} \ AUTH=${AUTH} SSL=${SSL} \ ORCHESTRATION_FILE=${ORCHESTRATION_FILE} \ + REQUIRE_API_VERSION=${REQUIRE_API_VERSION} \ bash ${DRIVERS_TOOLS}/.evergreen/run-orchestration.sh - command: expansions.update params: @@ -126,8 +127,10 @@ functions: rm -f ./prepare_client_encryption.sh fi - AUTH=${AUTH} SSL=${SSL} UNIFIED=${UNIFIED} MONGODB_URI="${MONGODB_URI}" \ - NODE_VERSION=${NODE_VERSION} SKIP_DEPS=1 NO_EXIT=1 \ + MONGODB_URI="${MONGODB_URI}" \ + AUTH=${AUTH} SSL=${SSL} UNIFIED=${UNIFIED} \ + MONGODB_API_VERSION="${MONGODB_API_VERSION}" \ + NODE_VERSION=${NODE_VERSION} SKIP_DEPS=${SKIP_DEPS|1} NO_EXIT=${NO_EXIT|1} \ bash ${PROJECT_DIRECTORY}/.evergreen/run-tests.sh run checks: - command: shell.exec @@ -777,6 +780,22 @@ tasks: VERSION: '2.6' TOPOLOGY: sharded_cluster - func: run tests + - name: test-latest-server-v1-api + tags: + - latest + - server + - v1-api + commands: + - func: install dependencies + - func: bootstrap mongo-orchestration + vars: + VERSION: latest + TOPOLOGY: server + REQUIRE_API_VERSION: '1' + - func: run tests + vars: + MONGODB_API_VERSION: '1' + NO_EXIT: '' - name: test-atlas-connectivity tags: - atlas-connect @@ -1195,6 +1214,7 @@ buildvariants: - test-2.6-server - test-2.6-replica_set - test-2.6-sharded_cluster + - test-latest-server-v1-api - test-atlas-connectivity - test-atlas-data-lake - test-auth-kerberos @@ -1261,6 +1281,7 @@ buildvariants: - test-2.6-server - test-2.6-replica_set - test-2.6-sharded_cluster + - test-latest-server-v1-api - test-atlas-connectivity - test-atlas-data-lake - test-auth-kerberos @@ -1356,6 +1377,7 @@ buildvariants: - test-3.2-server - test-3.2-replica_set - test-3.2-sharded_cluster + - test-latest-server-v1-api - test-atlas-connectivity - test-atlas-data-lake - test-auth-kerberos diff --git a/.evergreen/config.yml.in b/.evergreen/config.yml.in index f40c5b3b09..f44c43fd39 100644 --- a/.evergreen/config.yml.in +++ b/.evergreen/config.yml.in @@ -98,6 +98,7 @@ functions: MONGODB_VERSION=${VERSION} TOPOLOGY=${TOPOLOGY} \ AUTH=${AUTH} SSL=${SSL} \ ORCHESTRATION_FILE=${ORCHESTRATION_FILE} \ + REQUIRE_API_VERSION=${REQUIRE_API_VERSION} \ bash ${DRIVERS_TOOLS}/.evergreen/run-orchestration.sh # run-orchestration generates expansion file with the MONGODB_URI for the cluster - command: expansions.update @@ -146,8 +147,10 @@ functions: rm -f ./prepare_client_encryption.sh fi - AUTH=${AUTH} SSL=${SSL} UNIFIED=${UNIFIED} MONGODB_URI="${MONGODB_URI}" \ - NODE_VERSION=${NODE_VERSION} SKIP_DEPS=1 NO_EXIT=1 \ + MONGODB_URI="${MONGODB_URI}" \ + AUTH=${AUTH} SSL=${SSL} UNIFIED=${UNIFIED} \ + MONGODB_API_VERSION="${MONGODB_API_VERSION}" \ + NODE_VERSION=${NODE_VERSION} SKIP_DEPS=${SKIP_DEPS|1} NO_EXIT=${NO_EXIT|1} \ bash ${PROJECT_DIRECTORY}/.evergreen/run-tests.sh "run checks": diff --git a/.evergreen/generate_evergreen_tasks.js b/.evergreen/generate_evergreen_tasks.js index f45e40095b..c01b2d7b04 100644 --- a/.evergreen/generate_evergreen_tasks.js +++ b/.evergreen/generate_evergreen_tasks.js @@ -88,6 +88,28 @@ const BASE_TASKS = []; MONGODB_VERSIONS.forEach(mongoVersion => { TOPOLOGIES.forEach(topology => BASE_TASKS.push(makeTask({ mongoVersion, topology }))); }); +BASE_TASKS.push({ + name: `test-latest-server-v1-api`, + tags: ['latest', 'server', 'v1-api'], + commands: [ + { func: 'install dependencies' }, + { + func: 'bootstrap mongo-orchestration', + vars: { + VERSION: 'latest', + TOPOLOGY: 'server', + REQUIRE_API_VERSION: '1' + } + }, + { + func: 'run tests', + vars: { + MONGODB_API_VERSION: '1', + NO_EXIT: '' + } + } + ] +}); // manually added tasks Array.prototype.push.apply(TASKS, [ diff --git a/.evergreen/run-tests.sh b/.evergreen/run-tests.sh index dbb756b559..447f543ee8 100755 --- a/.evergreen/run-tests.sh +++ b/.evergreen/run-tests.sh @@ -56,4 +56,4 @@ else npm install mongodb-client-encryption fi -MONGODB_UNIFIED_TOPOLOGY=${UNIFIED} MONGODB_URI=${MONGODB_URI} npm run ${TEST_NPM_SCRIPT} +MONGODB_API_VERSION=${MONGODB_API_VERSION} MONGODB_UNIFIED_TOPOLOGY=${UNIFIED} MONGODB_URI=${MONGODB_URI} npm run ${TEST_NPM_SCRIPT} diff --git a/src/cmap/auth/scram.ts b/src/cmap/auth/scram.ts index d7362d8132..fa2e8d9848 100644 --- a/src/cmap/auth/scram.ts +++ b/src/cmap/auth/scram.ts @@ -2,7 +2,7 @@ import * as crypto from 'crypto'; import { Binary, Document } from '../../bson'; import { MongoError, AnyError } from '../../error'; import { AuthProvider, AuthContext } from './auth_provider'; -import { Callback, ns } from '../../utils'; +import { Callback, ns, applyServerApiVersion } from '../../utils'; import type { MongoCredentials } from './mongo_credentials'; import type { HandshakeDocument } from '../connect'; @@ -112,6 +112,9 @@ function executeScram(cryptoMethod: CryptoMethod, authContext: AuthContext, call const db = credentials.source; const saslStartCmd = makeFirstMessage(cryptoMethod, credentials, nonce); + if (connection.serverApi) { + applyServerApiVersion(saslStartCmd, connection.serverApi); + } connection.command(ns(`${db}.$cmd`), saslStartCmd, undefined, (_err, result) => { const err = resolveError(_err, result); if (err) { @@ -197,6 +200,9 @@ function continueScramConversation( conversationId: response.conversationId, payload: new Binary(Buffer.from(clientFinal)) }; + if (connection.serverApi) { + applyServerApiVersion(saslContinueCmd, connection.serverApi); + } connection.command(ns(`${db}.$cmd`), saslContinueCmd, undefined, (_err, r) => { const err = resolveError(_err, r); @@ -219,6 +225,9 @@ function continueScramConversation( conversationId: r.conversationId, payload: Buffer.alloc(0) }; + if (connection.serverApi) { + applyServerApiVersion(retrySaslContinueCmd, connection.serverApi); + } connection.command(ns(`${db}.$cmd`), retrySaslContinueCmd, undefined, callback); }); diff --git a/src/cmap/connect.ts b/src/cmap/connect.ts index 5673180dce..6e89a70b26 100644 --- a/src/cmap/connect.ts +++ b/src/cmap/connect.ts @@ -4,7 +4,14 @@ import { Connection, ConnectionOptions, CryptoConnection } from './connection'; import { MongoError, MongoNetworkError, MongoNetworkTimeoutError, AnyError } from '../error'; import { AUTH_PROVIDERS, AuthMechanism } from './auth/defaultAuthProviders'; import { AuthContext } from './auth/auth_provider'; -import { makeClientMetadata, ClientMetadata, Callback, CallbackWithType, ns } from '../utils'; +import { + makeClientMetadata, + ClientMetadata, + Callback, + CallbackWithType, + ns, + applyServerApiVersion +} from '../utils'; import { MAX_SUPPORTED_WIRE_VERSION, MAX_SUPPORTED_SERVER_VERSION, @@ -96,6 +103,10 @@ function performInitialHandshake( handshakeOptions.socketTimeout = options.connectTimeoutMS; } + if (conn.serverApi) { + applyServerApiVersion(handshakeDoc, conn.serverApi); + } + const start = new Date().getTime(); conn.command(ns('admin.$cmd'), handshakeDoc, handshakeOptions, (err, response) => { if (err) { diff --git a/src/cmap/connection.ts b/src/cmap/connection.ts index 3063444c07..62060ba90b 100644 --- a/src/cmap/connection.ts +++ b/src/cmap/connection.ts @@ -11,8 +11,7 @@ import { Callback, MongoDBNamespace, maxWireVersion, - HostAddress, - applyServerApiVersion + HostAddress } from '../utils'; import { AnyError, @@ -367,10 +366,6 @@ export class Connection extends EventEmitter { const inTransaction = session && (session.inTransaction() || isTransactionCommand(finalCmd)); - if (!inTransaction && !finalCmd.getMore && this.serverApi) { - applyServerApiVersion(finalCmd, this.serverApi); - } - const commandResponseHandler = inTransaction ? (err?: AnyError, ...args: Document[]) => { // We need to add a TransientTransactionError errorLabel, as stated in the transaction spec. diff --git a/src/connection_string.ts b/src/connection_string.ts index 133b7b8940..0772f37b42 100644 --- a/src/connection_string.ts +++ b/src/connection_string.ts @@ -21,7 +21,8 @@ import { MongoClient, MongoClientOptions, MongoOptions, - PkFactory + PkFactory, + ServerApi } from './mongo_client'; import { MongoCredentials } from './cmap/auth/mongo_credentials'; import type { TagSet } from './sdam/server_description'; @@ -572,6 +573,15 @@ export const OPTIONS = { autoEncryption: { type: 'record' }, + serverApi: { + target: 'serverApi', + transform({ values: [version] }): ServerApi { + if (typeof version === 'string') { + return { version }; + } + return version as ServerApi; + } + }, checkKeys: { type: 'boolean' }, diff --git a/src/mongo_client.ts b/src/mongo_client.ts index e5bd762feb..a549cf9bf2 100644 --- a/src/mongo_client.ts +++ b/src/mongo_client.ts @@ -222,6 +222,8 @@ export interface MongoClientOptions extends BSONSerializeOptions, SupportedNodeC logger?: Logger; /** Enable command monitoring for this client */ monitorCommands?: boolean; + /** Server API version */ + serverApi?: ServerApiVersion | ServerApi; /** Optionally enable client side auto encryption */ autoEncryption?: AutoEncryptionOptions; /** Allows a wrapping driver to amend the client metadata generated by the driver to include information about the wrapping driver */ @@ -243,13 +245,13 @@ export interface MongoClientPrivate { readConcern?: ReadConcern; writeConcern?: WriteConcern; readPreference: ReadPreference; + serverApi: ServerApi; bsonOptions: BSONSerializeOptions; namespace: MongoDBNamespace; logger: Logger; } const kOptions = Symbol('options'); -const kServerApi = Symbol('serverApi'); /** * The **MongoClient** class is a class that allows for making Connections to MongoDB. @@ -302,24 +304,17 @@ export class MongoClient extends EventEmitter { */ [kOptions]: MongoOptions; - /** - * The MongoDB Server API version - * @internal - * */ - [kServerApi]: ServerApi; - // debugging originalUri; originalOptions; - constructor(url: string, options?: MongoClientOptions, serverApi?: ServerApi) { + constructor(url: string, options?: MongoClientOptions) { super(); this.originalUri = url; this.originalOptions = options; this[kOptions] = parseOptions(url, this, options); - this[kServerApi] = Object.freeze({ version: ServerApiVersion.v1, ...serverApi }); // The internal state this.s = { @@ -329,6 +324,7 @@ export class MongoClient extends EventEmitter { readConcern: this[kOptions].readConcern, writeConcern: this[kOptions].writeConcern, readPreference: this[kOptions].readPreference, + serverApi: this[kOptions].serverApi, bsonOptions: resolveBSONOptions(this[kOptions]), namespace: ns('admin'), logger: this[kOptions].logger @@ -339,8 +335,8 @@ export class MongoClient extends EventEmitter { return Object.freeze({ ...this[kOptions] }); } - get serverApi(): Readonly { - return this[kServerApi]; + get serverApi(): Readonly { + return this[kOptions].serverApi && Object.freeze({ ...this[kOptions].serverApi }); } get autoEncrypter(): AutoEncrypter | undefined { @@ -652,6 +648,7 @@ export interface MongoOptions credentials?: MongoCredentials; readPreference: ReadPreference; readConcern: ReadConcern; + serverApi: ServerApi; writeConcern: WriteConcern; dbName: string; metadata: ClientMetadata; diff --git a/src/operations/command.ts b/src/operations/command.ts index 199862c4b2..7af1799dbf 100644 --- a/src/operations/command.ts +++ b/src/operations/command.ts @@ -1,7 +1,13 @@ import { Aspect, AbstractOperation, OperationOptions } from './operation'; import { ReadConcern } from '../read_concern'; import { WriteConcern, WriteConcernOptions } from '../write_concern'; -import { maxWireVersion, MongoDBNamespace, Callback, decorateWithExplain } from '../utils'; +import { + applyServerApiVersion, + maxWireVersion, + MongoDBNamespace, + Callback, + decorateWithExplain +} from '../utils'; import type { ReadPreference } from '../read_preference'; import { ClientSession, commandSupportsReadConcern } from '../sessions'; import { MongoError } from '../error'; @@ -173,6 +179,18 @@ export abstract class CommandOperation extends AbstractOperation { } } + // if an API version was declared, add the apiVersion option to every command, except: + // a. only in the initial command of a transaction + // b. only in a Cursor's initiating command, not subsequent getMore commands + if ( + server.serverApi && + (!inTransaction || this.session.transaction.isStarting) && + !cmd.commitTransaction && + !cmd.getMore + ) { + applyServerApiVersion(cmd, server.serverApi); + } + server.command(this.ns, cmd, { fullResult: !!this.fullResponse, ...options }, callback); } } diff --git a/src/operations/find.ts b/src/operations/find.ts index 93864c8948..c3939ec563 100644 --- a/src/operations/find.ts +++ b/src/operations/find.ts @@ -4,7 +4,8 @@ import { MongoDBNamespace, Callback, normalizeHintField, - decorateWithExplain + decorateWithExplain, + applyServerApiVersion } from '../utils'; import { MongoError } from '../error'; import type { Document } from '../bson'; @@ -153,6 +154,9 @@ export class FindOperation extends CommandOperation { if (this.explain) { findCommand = decorateWithExplain(findCommand, this.explain); } + if (server.serverApi) { + applyServerApiVersion(findCommand, server.serverApi); + } server.command( this.ns, diff --git a/src/operations/update.ts b/src/operations/update.ts index 197c934ab8..b3057ebaeb 100644 --- a/src/operations/update.ts +++ b/src/operations/update.ts @@ -274,7 +274,7 @@ export function makeUpdateStatement( op.upsert = options.upsert; } - if (typeof options.multi === 'boolean') { + if (options.multi) { op.multi = options.multi; } diff --git a/src/sdam/server.ts b/src/sdam/server.ts index 7c495b6896..d37d97f491 100644 --- a/src/sdam/server.ts +++ b/src/sdam/server.ts @@ -44,6 +44,7 @@ import type { ServerHeartbeatSucceededEvent } from './events'; import type { ClientSession } from '../sessions'; import type { Document, Long } from '../bson'; import type { AutoEncrypter } from '../deps'; +import type { ServerApi } from '../mongo_client'; // Used for filtering out fields for logging const DEBUG_FIELDS = [ @@ -106,6 +107,7 @@ export interface ServerPrivate { export class Server extends EventEmitter { /** @internal */ s: ServerPrivate; + serverApi?: ServerApi; clusterTime?: ClusterTime; ismaster?: Document; [kMonitor]: Monitor; @@ -131,7 +133,7 @@ export class Server extends EventEmitter { constructor(topology: Topology, description: ServerDescription, options: ServerOptions) { super(); - options.serverApi = topology.serverApi; + this.serverApi = options.serverApi = topology.serverApi; const poolOptions = { hostAddress: description.hostAddress, ...options }; diff --git a/src/sdam/topology.ts b/src/sdam/topology.ts index 58f5f245af..216c497e66 100644 --- a/src/sdam/topology.ts +++ b/src/sdam/topology.ts @@ -22,7 +22,8 @@ import { ClientMetadata, Callback, HostAddress, - ns + ns, + applyServerApiVersion } from '../utils'; import { TopologyType, @@ -381,7 +382,11 @@ export class Topology extends EventEmitter { // TODO: NODE-2471 if (server && this.s.credentials) { - server.command(ns('admin.$cmd'), { ping: 1 }, err => { + const pingCmd = { ping: 1 }; + if (server.serverApi) { + applyServerApiVersion(pingCmd, server.serverApi); + } + server.command(ns('admin.$cmd'), pingCmd, err => { if (err) { typeof callback === 'function' ? callback(err) : this.emit(Topology.ERROR, err); return; diff --git a/src/transactions.ts b/src/transactions.ts index 7830049030..9e65704654 100644 --- a/src/transactions.ts +++ b/src/transactions.ts @@ -113,6 +113,11 @@ export class Transaction { return !!this.server; } + /** @returns Whether the transaction has started */ + get isStarting(): boolean { + return this.state === TxnState.STARTING_TRANSACTION; + } + /** * @returns Whether this session is presently in a transaction */ diff --git a/test/functional/abstract_cursor.test.js b/test/functional/abstract_cursor.test.js index c0c18b1c06..53e6951ed4 100644 --- a/test/functional/abstract_cursor.test.js +++ b/test/functional/abstract_cursor.test.js @@ -143,9 +143,9 @@ describe('AbstractCursor', function () { }); context('#tryNext', function () { - it( - 'should return control to the user if an empty batch is returned', - withClientV2(function (client, done) { + it('should return control to the user if an empty batch is returned', { + metadata: { requires: { apiVersion: false } }, + test: withClientV2(function (client, done) { const db = client.db(); db.createCollection('try_next', { capped: true, size: 10000000 }, () => { const coll = db.collection('try_next'); @@ -173,7 +173,7 @@ describe('AbstractCursor', function () { }); }); }) - ); + }); }); context('#clone', function () { diff --git a/test/functional/apm.test.js b/test/functional/apm.test.js index 347a570b23..94b3b582cb 100644 --- a/test/functional/apm.test.js +++ b/test/functional/apm.test.js @@ -332,7 +332,7 @@ describe('APM', function () { ); it('should correctly receive the APM events for a find with getmore and killcursor', { - metadata: { requires: { topology: ['single', 'replicaset'] } }, + metadata: { requires: { apiVersion: false, topology: ['single', 'replicaset'] } }, test: function () { const self = this; @@ -786,7 +786,9 @@ describe('APM', function () { }); it('should correctly decorate the apm result for listCollections with cursorId', { - metadata: { requires: { topology: ['single', 'replicaset'], mongodb: '>=3.0.0' } }, + metadata: { + requires: { apiVersion: false, topology: ['single', 'replicaset'], mongodb: '>=3.0.0' } + }, test: function () { const self = this; const started = []; @@ -1061,6 +1063,11 @@ describe('APM', function () { ); } + // FIXME: NODE-2950 + if (test.description.match(/event with a getmore/)) { + requirements.apiVersion = false; + } + it(test.description, { metadata: { requires: requirements }, test: function () { diff --git a/test/functional/bulk.test.js b/test/functional/bulk.test.js index bdef079b9f..a6db63d578 100644 --- a/test/functional/bulk.test.js +++ b/test/functional/bulk.test.js @@ -68,7 +68,7 @@ describe('Bulk', function () { var op = error.getOperation(); test.equal(2, op.q.b); test.equal(1, op.u['$set'].a); - test.equal(false, op.multi); + expect(op.multi).to.not.be.true; test.equal(true, op.upsert); // Get the first error @@ -324,7 +324,7 @@ describe('Bulk', function () { test.ok(error.errmsg != null); test.equal(2, error.getOperation().q.b); test.equal(1, error.getOperation().u['$set'].a); - test.equal(false, error.getOperation().multi); + expect(error.getOperation().multi).to.not.be.true; test.equal(true, error.getOperation().upsert); // Finish up test @@ -698,7 +698,7 @@ describe('Bulk', function () { var op = error.getOperation(); test.equal(2, op.q.b); test.equal(1, op.u['$set'].a); - test.equal(false, op.multi); + expect(op.multi).to.not.be.true; test.equal(true, op.upsert); // Get the first error @@ -1180,7 +1180,6 @@ describe('Bulk', function () { expect(batches[1].operations[0]).to.containSubset({ q: { b: 2 }, u: { $set: { a: 1 } }, - multi: false, upsert: true }); expect(batches[2].operations[0]).to.containSubset({ b: 3, a: 2 }); @@ -1283,7 +1282,6 @@ describe('Bulk', function () { expect(batches[1].operations[0]).to.containSubset({ q: { b: 2 }, u: { $set: { a: 1 } }, - multi: false, upsert: true }); client.close(done); diff --git a/test/functional/cmap/connection.test.js b/test/functional/cmap/connection.test.js index f59a128d5e..4e46c4c746 100644 --- a/test/functional/cmap/connection.test.js +++ b/test/functional/cmap/connection.test.js @@ -11,48 +11,54 @@ describe('Connection - functional/cmap', function () { return setupDatabase(this.configuration); }); - it('should execute a command against a server', function (done) { - const connectOptions = Object.assign( - { connectionType: Connection }, - this.configuration.options - ); - - connect(connectOptions, (err, conn) => { - expect(err).to.not.exist; - this.defer(_done => conn.destroy(_done)); + it('should execute a command against a server', { + metadata: { requires: { apiVersion: false } }, + test: function (done) { + const connectOptions = Object.assign( + { connectionType: Connection }, + this.configuration.options + ); - conn.command(ns('admin.$cmd'), { ismaster: 1 }, undefined, (err, ismaster) => { + connect(connectOptions, (err, conn) => { expect(err).to.not.exist; - expect(ismaster).to.exist; - expect(ismaster.ok).to.equal(1); - done(); + this.defer(_done => conn.destroy(_done)); + + conn.command(ns('admin.$cmd'), { ismaster: 1 }, undefined, (err, ismaster) => { + expect(err).to.not.exist; + expect(ismaster).to.exist; + expect(ismaster.ok).to.equal(1); + done(); + }); }); - }); + } }); - it('should emit command monitoring events', function (done) { - const connectOptions = Object.assign( - { connectionType: Connection, monitorCommands: true }, - this.configuration.options - ); - - connect(connectOptions, (err, conn) => { - expect(err).to.not.exist; - this.defer(_done => conn.destroy(_done)); - - const events = []; - conn.on('commandStarted', event => events.push(event)); - conn.on('commandSucceeded', event => events.push(event)); - conn.on('commandFailed', event => events.push(event)); + it('should emit command monitoring events', { + metadata: { requires: { apiVersion: false } }, + test: function (done) { + const connectOptions = Object.assign( + { connectionType: Connection, monitorCommands: true }, + this.configuration.options + ); - conn.command(ns('admin.$cmd'), { ismaster: 1 }, undefined, (err, ismaster) => { + connect(connectOptions, (err, conn) => { expect(err).to.not.exist; - expect(ismaster).to.exist; - expect(ismaster.ok).to.equal(1); - expect(events).to.have.length(2); - done(); + this.defer(_done => conn.destroy(_done)); + + const events = []; + conn.on('commandStarted', event => events.push(event)); + conn.on('commandSucceeded', event => events.push(event)); + conn.on('commandFailed', event => events.push(event)); + + conn.command(ns('admin.$cmd'), { ismaster: 1 }, undefined, (err, ismaster) => { + expect(err).to.not.exist; + expect(ismaster).to.exist; + expect(ismaster.ok).to.equal(1); + expect(events).to.have.length(2); + done(); + }); }); - }); + } }); it.skip('should support socket timeouts', { @@ -78,7 +84,7 @@ describe('Connection - functional/cmap', function () { }); it('should support calling back multiple times on exhaust commands', { - metadata: { requires: { mongodb: '>=4.2.0', topology: ['single'] } }, + metadata: { requires: { apiVersion: false, mongodb: '>=4.2.0', topology: ['single'] } }, test: function (done) { const namespace = ns(`${this.configuration.db}.$cmd`); const connectOptions = Object.assign( diff --git a/test/functional/collations.test.js b/test/functional/collations.test.js index 85468f7049..41fe8e2349 100644 --- a/test/functional/collations.test.js +++ b/test/functional/collations.test.js @@ -687,7 +687,7 @@ describe('Collation', function () { .collection('test') .createIndex({ a: 1 }, { collation: { caseLevel: true } }) .then(() => { - expect(commandResult).to.eql({ + expect(commandResult).to.containSubset({ createIndexes: 'test', indexes: [{ name: 'a_1', key: { a: 1 }, collation: { caseLevel: true } }] }); diff --git a/test/functional/core/topology.test.js b/test/functional/core/topology.test.js index aca9f80c9b..980c5b94a0 100644 --- a/test/functional/core/topology.test.js +++ b/test/functional/core/topology.test.js @@ -2,18 +2,21 @@ const expect = require('chai').expect; describe('Topology', function () { - it('should correctly track states of a topology', function (done) { - const topology = this.configuration.newTopology(); + it('should correctly track states of a topology', { + metadata: { requires: { apiVersion: false } }, + test: function (done) { + const topology = this.configuration.newTopology(); - const states = []; - topology.on('stateChanged', (_, newState) => states.push(newState)); - topology.connect(err => { - expect(err).to.not.exist; - topology.destroy(err => { + const states = []; + topology.on('stateChanged', (_, newState) => states.push(newState)); + topology.connect(err => { expect(err).to.not.exist; - expect(states).to.eql(['connecting', 'connected', 'closing', 'closed']); - done(); + topology.destroy(err => { + expect(err).to.not.exist; + expect(states).to.eql(['connecting', 'connected', 'closing', 'closed']); + done(); + }); }); - }); + } }); }); diff --git a/test/functional/crud_spec.test.js b/test/functional/crud_spec.test.js index 563ca1124b..88af384033 100644 --- a/test/functional/crud_spec.test.js +++ b/test/functional/crud_spec.test.js @@ -69,6 +69,10 @@ describe('CRUD spec', function () { describe(scenarioName, function () { scenario.tests.forEach(scenarioTest => { beforeEach(() => testContext.db.dropDatabase()); + // FIXME: NODE-2950 + if (scenarioTest.description.match(/Find with limit, sort, and batchsize/)) { + metadata.requires.apiVersion = false; + } it(scenarioTest.description, { metadata, test: function () { diff --git a/test/functional/cursor.test.js b/test/functional/cursor.test.js index f33ebd1063..a63c65a964 100644 --- a/test/functional/cursor.test.js +++ b/test/functional/cursor.test.js @@ -2762,7 +2762,10 @@ describe('Cursor', function () { // Add a tag that our runner can trigger on // in this case we are setting that node needs to be higher than 0.10.X to run metadata: { - requires: { topology: ['single', 'replicaset', 'sharded', 'ssl', 'heap', 'wiredtiger'] } + requires: { + apiVersion: false, + topology: ['single', 'replicaset', 'sharded', 'ssl', 'heap', 'wiredtiger'] + } }, test: function (done) { @@ -3676,6 +3679,7 @@ describe('Cursor', function () { { metadata: { requires: { + apiVersion: false, topology: ['single', 'replicaset', 'sharded', 'ssl', 'heap', 'wiredtiger'], mongodb: '>=3.6.0' } @@ -3710,6 +3714,7 @@ describe('Cursor', function () { { metadata: { requires: { + apiVersion: false, topology: ['single', 'replicaset', 'sharded', 'ssl', 'heap', 'wiredtiger'], mongodb: '>=3.6.0' } diff --git a/test/functional/gridfs_stream.test.js b/test/functional/gridfs_stream.test.js index dc3d793863..1423feb77b 100644 --- a/test/functional/gridfs_stream.test.js +++ b/test/functional/gridfs_stream.test.js @@ -601,7 +601,7 @@ describe('GridFS Stream', function () { * @example-method abort */ it('Destroying a download stream', { - metadata: { requires: { topology: ['single'] } }, + metadata: { requires: { topology: ['single'], apiVersion: false } }, test: function (done) { var configuration = this.configuration; @@ -669,7 +669,9 @@ describe('GridFS Stream', function () { * @example-method delete */ it('Deleting a file using promises', { - metadata: { requires: { topology: ['single'], node: '>12.0.0' } }, + metadata: { + requires: { topology: ['single'], node: '>12.0.0', sessions: { skipLeakTests: true } } + }, test: function (done) { var configuration = this.configuration; @@ -718,7 +720,7 @@ describe('GridFS Stream', function () { }); it('find()', { - metadata: { requires: { topology: ['single'] } }, + metadata: { requires: { topology: ['single'], sessions: { skipLeakTests: true } } }, test: function (done) { var configuration = this.configuration; @@ -759,7 +761,7 @@ describe('GridFS Stream', function () { * @example-method drop */ it('drop example', { - metadata: { requires: { topology: ['single'] } }, + metadata: { requires: { topology: ['single'], sessions: { skipLeakTests: true } } }, test: function (done) { var configuration = this.configuration; diff --git a/test/functional/insert.test.js b/test/functional/insert.test.js index d5d83471cf..8a469a8b3c 100644 --- a/test/functional/insert.test.js +++ b/test/functional/insert.test.js @@ -1840,7 +1840,10 @@ describe('Insert', function () { // Add a tag that our runner can trigger on // in this case we are setting that node needs to be higher than 0.10.X to run metadata: { - requires: { topology: ['single', 'replicaset', 'sharded', 'ssl', 'heap', 'wiredtiger'] } + requires: { + apiVersion: false, + topology: ['single', 'replicaset', 'sharded', 'ssl', 'heap', 'wiredtiger'] + } }, test: function (done) { diff --git a/test/functional/max_staleness.test.js b/test/functional/max_staleness.test.js index d87f4336ad..3de4377fd9 100644 --- a/test/functional/max_staleness.test.js +++ b/test/functional/max_staleness.test.js @@ -63,7 +63,7 @@ describe('Max Staleness', function () { .find({}) .toArray(function (err) { expect(err).to.not.exist; - expect(test.checkCommand).to.eql({ + expect(test.checkCommand).to.containSubset({ $query: { find: 'test', filter: {} }, $readPreference: { mode: 'secondary', maxStalenessSeconds: 250 } }); @@ -98,7 +98,7 @@ describe('Max Staleness', function () { .find({}) .toArray(function (err) { expect(err).to.not.exist; - expect(test.checkCommand).to.eql({ + expect(test.checkCommand).to.containSubset({ $query: { find: 'test', filter: {} }, $readPreference: { mode: 'secondary', maxStalenessSeconds: 250 } }); @@ -134,7 +134,7 @@ describe('Max Staleness', function () { .find({}) .toArray(function (err) { expect(err).to.not.exist; - expect(test.checkCommand).to.eql({ + expect(test.checkCommand).to.containSubset({ $query: { find: 'test', filter: {} }, $readPreference: { mode: 'secondary', maxStalenessSeconds: 250 } }); @@ -169,7 +169,7 @@ describe('Max Staleness', function () { .withReadPreference(readPreference) .toArray(function (err) { expect(err).to.not.exist; - expect(test.checkCommand).to.eql({ + expect(test.checkCommand).to.containSubset({ $query: { find: 'test', filter: {} }, $readPreference: { mode: 'secondary', maxStalenessSeconds: 250 } }); diff --git a/test/functional/operation_example.test.js b/test/functional/operation_example.test.js index 2d645cd61d..8d720fb0a8 100644 --- a/test/functional/operation_example.test.js +++ b/test/functional/operation_example.test.js @@ -117,6 +117,7 @@ describe('Operation Examples', function () { // in this case we are setting that node needs to be higher than 0.10.X to run metadata: { requires: { + apiVersion: false, mongodb: '>2.1.0', topology: ['single', 'replicaset', 'sharded', 'ssl', 'heap', 'wiredtiger'] } @@ -203,6 +204,7 @@ describe('Operation Examples', function () { // in this case we are setting that node needs to be higher than 0.10.X to run metadata: { requires: { + apiVersion: false, mongodb: '>2.1.0', topology: ['single', 'replicaset', 'sharded', 'ssl', 'heap', 'wiredtiger'] } @@ -378,6 +380,7 @@ describe('Operation Examples', function () { // in this case we are setting that node needs to be higher than 0.10.X to run metadata: { requires: { + apiVersion: false, mongodb: '>2.1.0', topology: ['single', 'replicaset', 'sharded', 'ssl', 'heap', 'wiredtiger'] } @@ -466,6 +469,7 @@ describe('Operation Examples', function () { // in this case we are setting that node needs to be higher than 0.10.X to run metadata: { requires: { + apiVersion: false, mongodb: '>2.1.0', topology: ['single', 'replicaset', 'sharded', 'ssl', 'heap', 'wiredtiger'] } @@ -560,6 +564,7 @@ describe('Operation Examples', function () { // in this case we are setting that node needs to be higher than 0.10.X to run metadata: { requires: { + apiVersion: false, mongodb: '>2.1.0', topology: ['single', 'replicaset', 'sharded', 'ssl', 'heap', 'wiredtiger'] } @@ -3513,7 +3518,7 @@ describe('Operation Examples', function () { * @example-method removeUser */ it('shouldCorrectlyAddAndRemoveUser', { - metadata: { requires: { topology: 'single' } }, + metadata: { requires: { apiVersion: false, topology: 'single' } }, test: function (done) { var configuration = this.configuration; diff --git a/test/functional/operation_generators_example.test.js b/test/functional/operation_generators_example.test.js index e9faf7c23a..1b280ab442 100644 --- a/test/functional/operation_generators_example.test.js +++ b/test/functional/operation_generators_example.test.js @@ -24,7 +24,9 @@ describe('Operation (Generators)', function () { it('aggregationExample2WithGenerators', { // Add a tag that our runner can trigger on // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { requires: { generators: true, mongodb: '>2.1.0', topology: ['single'] } }, + metadata: { + requires: { apiVersion: false, generators: true, mongodb: '>2.1.0', topology: ['single'] } + }, test: function () { var configuration = this.configuration; @@ -2561,7 +2563,7 @@ describe('Operation (Generators)', function () { * @example-method removeUser */ it('shouldCorrectlyAddAndRemoveUserWithGenerators', { - metadata: { requires: { generators: true, topology: 'single' } }, + metadata: { requires: { apiVersion: false, generators: true, topology: 'single' } }, test: function () { var configuration = this.configuration; diff --git a/test/functional/operation_promises_example.test.js b/test/functional/operation_promises_example.test.js index 9414fdcf53..0d7ecad1e4 100644 --- a/test/functional/operation_promises_example.test.js +++ b/test/functional/operation_promises_example.test.js @@ -33,7 +33,7 @@ describe('Operation (Promises)', function () { it('aggregationExample2WithPromises', { // Add a tag that our runner can trigger on // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { requires: { mongodb: '>2.1.0', topology: ['single'] } }, + metadata: { requires: { apiVersion: false, mongodb: '>2.1.0', topology: ['single'] } }, test: function () { var configuration = this.configuration; diff --git a/test/functional/promote_values.test.js b/test/functional/promote_values.test.js index c301a1c497..5ee64ac49d 100644 --- a/test/functional/promote_values.test.js +++ b/test/functional/promote_values.test.js @@ -208,6 +208,7 @@ describe('Promote Values', function () { it('Should correctly promoteValues when calling getMore on queries', { metadata: { requires: { + apiVersion: false, topology: ['single', 'ssl', 'wiredtiger'] } }, diff --git a/test/functional/spec-runner/index.js b/test/functional/spec-runner/index.js index 1e6bc40ea9..77d92a0caa 100644 --- a/test/functional/spec-runner/index.js +++ b/test/functional/spec-runner/index.js @@ -125,7 +125,8 @@ function generateTopologyTests(testSuites, testContext, filter) { environmentRequirementList.forEach(requires => { const suiteName = `${testSuite.name} - ${requires.topology.join()}`; describe(suiteName, { - metadata: { requires }, + // FIXME: calling this.skip() inside tests triggers the leak checker, disable until fixed + metadata: { requires, sessions: { skipLeakTests: true } }, test: function () { beforeEach(() => prepareDatabaseForSuite(testSuite, testContext)); afterEach(() => testContext.cleanupAfterSuite()); diff --git a/test/functional/unified-spec-runner/entities.ts b/test/functional/unified-spec-runner/entities.ts index 32df9a3f31..6eff0a283c 100644 --- a/test/functional/unified-spec-runner/entities.ts +++ b/test/functional/unified-spec-runner/entities.ts @@ -37,7 +37,13 @@ export class UnifiedMongoClient extends MongoClient { } as const; constructor(url: string, description: ClientEntity) { - super(url, { monitorCommands: true, ...description.uriOptions }, description.serverApi); + super(url, { + monitorCommands: true, + ...description.uriOptions, + serverApi: + description.serverApi || + (process.env.MONGODB_API_VERSION && { version: process.env.MONGODB_API_VERSION }) + }); this.events = []; this.failPoints = []; this.ignoredEvents = [ diff --git a/test/functional/unified-spec-runner/match.ts b/test/functional/unified-spec-runner/match.ts index 609bac590c..671344ed7b 100644 --- a/test/functional/unified-spec-runner/match.ts +++ b/test/functional/unified-spec-runner/match.ts @@ -129,11 +129,10 @@ export function resultCheck( if (depth > 1) { expect(actual, `Expected actual to exist at ${path.join('')}`).to.exist; - // expect( - // Object.keys(actual), - // `[${Object.keys(actual)}] length !== [${Object.keys(expected)}]` - // ).to.have.lengthOf(Object.keys(expected).length); - expect(Object.keys(actual)).to.include.members(Object.keys(expected)); + expect( + Object.keys(actual), + `[${Object.keys(actual)}] length !== [${Object.keys(expected)}]` + ).to.have.lengthOf(Object.keys(expected).length); } for (const [key, value] of expectedEntries) { diff --git a/test/functional/unified-spec-runner/runner.ts b/test/functional/unified-spec-runner/runner.ts index d4dfc378f6..1d3e5b9cba 100644 --- a/test/functional/unified-spec-runner/runner.ts +++ b/test/functional/unified-spec-runner/runner.ts @@ -76,11 +76,12 @@ export async function runUnifiedTest( ...(test.runOnRequirements ?? []) ]; - let doesNotMeetRunOnRequirement = allRequirements.length > 0; + let doesNotMeetRunOnRequirement = false; for (const requirement of allRequirements) { - if (await topologySatisfies(ctx.configuration, requirement, utilClient)) { - doesNotMeetRunOnRequirement = false; // it does meet a run on requirement! + const met = await topologySatisfies(ctx.configuration, requirement, utilClient); + if (!met) { + doesNotMeetRunOnRequirement = true; // it doesn't meet a run on requirement break; } } diff --git a/test/functional/unified-spec-runner/unified-utils.ts b/test/functional/unified-spec-runner/unified-utils.ts index e55ea46881..420df85cbb 100644 --- a/test/functional/unified-spec-runner/unified-utils.ts +++ b/test/functional/unified-spec-runner/unified-utils.ts @@ -33,9 +33,9 @@ export async function topologySatisfies( Sharded: 'sharded' }[config.topologyType]; - if (r.topologies.includes('sharded-replicaset')) { + if (r.topologies.includes('sharded-replicaset') && topologyType === 'sharded') { const shards = await utilClient.db('config').collection('shards').find({}).toArray(); - ok &&= shards.every(shard => shard.host.split(',').length > 1); + ok &&= shards.length > 0 && shards.every(shard => shard.host.split(',').length > 1); } else { if (!topologyType) throw new Error(`Topology undiscovered: ${config.topologyType}`); ok &&= r.topologies.includes(topologyType); diff --git a/test/functional/uri.test.js b/test/functional/uri.test.js index 90787b9b4d..9f887c7289 100644 --- a/test/functional/uri.test.js +++ b/test/functional/uri.test.js @@ -74,7 +74,7 @@ describe('URI', function () { it('should correctly connect using uri encoded username and password', { // Add a tag that our runner can trigger on // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { requires: { topology: 'single' } }, + metadata: { requires: { topology: 'single', apiVersion: false } }, test: function (done) { var self = this; diff --git a/test/functional/versioned-api.test.js b/test/functional/versioned-api.test.js index 6372e5b84b..06d94d709d 100644 --- a/test/functional/versioned-api.test.js +++ b/test/functional/versioned-api.test.js @@ -9,16 +9,19 @@ describe('Versioned API', function () { expect(versionedApiTest).to.exist; context(String(versionedApiTest.description), function () { for (const test of versionedApiTest.tests) { - it(String(test.description), async function () { - try { - await runUnifiedTest(this, versionedApiTest, test); - } catch (error) { - if (error.message.includes('not implemented.')) { - console.log(`${test.description}: was skipped due to missing functionality`); - console.log(error.stack); - this.skip(); - } else { - throw error; + it(String(test.description), { + metadata: { sessions: { skipLeakTests: true } }, + test: async function () { + try { + await runUnifiedTest(this, versionedApiTest, test); + } catch (error) { + if (error.message.includes('not implemented.')) { + console.log(`${test.description}: was skipped due to missing functionality`); + console.log(error.stack); + this.skip(); + } else { + throw error; + } } } }); diff --git a/test/functional/view.test.js b/test/functional/view.test.js index d853a7812c..4fee4d454d 100644 --- a/test/functional/view.test.js +++ b/test/functional/view.test.js @@ -58,7 +58,7 @@ describe('Views', function () { ) { expect(r).to.exist; expect(err).to.not.exist; - expect(commandResult).to.eql({ + expect(commandResult).to.containSubset({ create: 'test', viewOn: 'users', pipeline: [{ $match: {} }] diff --git a/test/tools/runner/config.js b/test/tools/runner/config.js index 56aac6d622..34b2435fe9 100644 --- a/test/tools/runner/config.js +++ b/test/tools/runner/config.js @@ -34,13 +34,13 @@ function convertToConnStringMap(obj) { } class TestConfiguration { - constructor(uri, context, serverApiVersion) { + constructor(uri, context) { const { url, hosts } = parseURI(uri); const hostAddresses = hosts.map(HostAddress.fromString); this.topologyType = context.topologyType; this.version = context.version; - this.serverApiVersion = serverApiVersion; this.clientSideEncryption = context.clientSideEncryption; + this.serverApi = context.serverApi; this.parameters = undefined; this.options = { hosts, @@ -97,17 +97,17 @@ class TestConfiguration { } newClient(dbOptions, serverOptions) { + const defaultOptions = { minHeartbeatFrequencyMS: 100 }; + if (this.serverApi) { + Object.assign(defaultOptions, { serverApi: this.serverApi }); + } // support MongoClient constructor form (url, options) for `newClient` if (typeof dbOptions === 'string') { - return new MongoClient( - dbOptions, - Object.assign({ minHeartbeatFrequencyMS: 100 }, serverOptions), - { version: this.serverApiVersion } - ); + return new MongoClient(dbOptions, Object.assign(defaultOptions, serverOptions)); } dbOptions = dbOptions || {}; - serverOptions = Object.assign({}, { minHeartbeatFrequencyMS: 100 }, serverOptions); + serverOptions = Object.assign({}, defaultOptions, serverOptions); // Fall back let dbHost = (serverOptions && serverOptions.host) || this.options.host; @@ -166,6 +166,7 @@ class TestConfiguration { if (Reflect.has(serverOptions, 'host') || Reflect.has(serverOptions, 'port')) { throw new Error(`Cannot use options to specify host/port, must be in ${connectionString}`); } + return new MongoClient(connectionString, serverOptions); } diff --git a/test/tools/runner/filters/api_version_filter.js b/test/tools/runner/filters/api_version_filter.js new file mode 100755 index 0000000000..83c00b20b7 --- /dev/null +++ b/test/tools/runner/filters/api_version_filter.js @@ -0,0 +1,37 @@ +'use strict'; + +/** + * Filter for the MongoDB API Version required for the test + * + * example: + * metadata: { + * requires: { + * apiVersion: '1' + * } + * } + */ +class ApiVersionFilter { + constructor() { + // Get environmental variables that are known + this.apiVersion = process.env.MONGODB_API_VERSION; + } + + filter(test) { + if (!test.metadata) return true; + if (!test.metadata.requires) return true; + const apiVersion = test.metadata.requires.apiVersion; + + // setting to false skips this test when an apiVersion is required + if (apiVersion === false) return !this.apiVersion; + // setting to true requires some apiVersion be specified + if (apiVersion === true) return !!this.apiVersion; + + // if there's no metadata requirement, always run + if (apiVersion == null) return true; + + // otherwise attempt a direct match + return apiVersion === this.apiVersion; + } +} + +module.exports = ApiVersionFilter; diff --git a/test/tools/runner/index.js b/test/tools/runner/index.js index 14586caf6c..1caa6fa6b0 100644 --- a/test/tools/runner/index.js +++ b/test/tools/runner/index.js @@ -61,7 +61,8 @@ before(function (_done) { // )} topology` // ); - const client = new MongoClient(MONGODB_URI); + const options = MONGODB_API_VERSION ? { serverApi: MONGODB_API_VERSION } : {}; + const client = new MongoClient(MONGODB_URI, options); const done = err => client.close(err2 => _done(err || err2)); client.connect(err => { @@ -76,9 +77,14 @@ before(function (_done) { return; } + // Ensure test MongoClients set a serverApi parameter when required + if (MONGODB_API_VERSION) { + Object.assign(context, { serverApi: MONGODB_API_VERSION }); + } + // replace this when mocha supports dynamic skipping with `afterEach` filterOutTests(this._runnable.parent); - this.configuration = new TestConfiguration(MONGODB_URI, context, MONGODB_API_VERSION); + this.configuration = new TestConfiguration(MONGODB_URI, context); done(); }); }); diff --git a/test/unit/legacy_compat.test.js b/test/unit/legacy_compat.test.js index 8d7a4e0f8d..d8fd20a6c3 100644 --- a/test/unit/legacy_compat.test.js +++ b/test/unit/legacy_compat.test.js @@ -1,11 +1,10 @@ 'use strict'; const { expect } = require('chai'); -const { MongoClient } = require('../../src'); describe('Legacy 3.x features', function () { it('Should have bson defined on topology', function () { - const client = new MongoClient(this.configuration.url()); + const client = this.configuration.newClient(this.configuration.url()); return client .connect() .then(client => { @@ -18,13 +17,13 @@ describe('Legacy 3.x features', function () { it('Should allow legacy option useUnifiedTopology', function () { const url = this.configuration.url(); - expect(() => new MongoClient(url, { useUnifiedTopology: true })).to.not.throw; - expect(() => new MongoClient(url, { useUnifiedTopology: false })).to.not.throw; + expect(() => this.configuration.newClient(url, { useUnifiedTopology: true })).to.not.throw; + expect(() => this.configuration.newClient(url, { useUnifiedTopology: false })).to.not.throw; }); it('Should allow legacy option useNewUrlParser', function () { const url = this.configuration.url(); - expect(() => new MongoClient(url, { useNewUrlParser: true })).to.not.throw; - expect(() => new MongoClient(url, { useNewUrlParser: false })).to.not.throw; + expect(() => this.configuration.newClient(url, { useNewUrlParser: true })).to.not.throw; + expect(() => this.configuration.newClient(url, { useNewUrlParser: false })).to.not.throw; }); });