From c593393f6f7c97cb02fbeed9ef21335409d2ed38 Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Fri, 9 Jun 2023 16:13:13 -0400 Subject: [PATCH 01/14] test(NODE-5342): modernize explain tests --- test/integration/crud/explain.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/integration/crud/explain.test.ts b/test/integration/crud/explain.test.ts index d00caff025d..254781d0a41 100644 --- a/test/integration/crud/explain.test.ts +++ b/test/integration/crud/explain.test.ts @@ -74,6 +74,7 @@ describe('CRUD API explain option', function () { afterEach(async function () { await collection.drop(); await client.close(); + commandsStarted = []; }); for (const explainValue of explain) { From 8f6efbafc4d812fd1ba473cb4feb746911d23baa Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Tue, 13 Jun 2023 13:19:54 -0400 Subject: [PATCH 02/14] grouped aggregates under context block --- test/integration/crud/explain.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/test/integration/crud/explain.test.ts b/test/integration/crud/explain.test.ts index 254781d0a41..d00caff025d 100644 --- a/test/integration/crud/explain.test.ts +++ b/test/integration/crud/explain.test.ts @@ -74,7 +74,6 @@ describe('CRUD API explain option', function () { afterEach(async function () { await collection.drop(); await client.close(); - commandsStarted = []; }); for (const explainValue of explain) { From 956d4b85a1a0fd61d68324899e9ac9578fa748f7 Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Tue, 13 Jun 2023 13:27:57 -0400 Subject: [PATCH 03/14] fixed formatting --- test/integration/crud/explain.test.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/test/integration/crud/explain.test.ts b/test/integration/crud/explain.test.ts index d00caff025d..6b1c30166ef 100644 --- a/test/integration/crud/explain.test.ts +++ b/test/integration/crud/explain.test.ts @@ -1,13 +1,7 @@ import { expect } from 'chai'; import { once } from 'events'; -import { - type Collection, - type CommandStartedEvent, - type Db, - type MongoClient, - MongoServerError -} from '../../mongodb'; +import { type Collection, type Db, type MongoClient, MongoServerError } from '../../mongodb'; const explain = [true, false, 'queryPlanner', 'allPlansExecution', 'executionStats', 'invalid']; From f6cfc42b3526490ffb71629525c16b2b12a2136e Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Fri, 23 Jun 2023 13:53:03 -0400 Subject: [PATCH 04/14] Added all operations, is still giving test errors --- test/integration/crud/explain.test.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/integration/crud/explain.test.ts b/test/integration/crud/explain.test.ts index 6b1c30166ef..d00caff025d 100644 --- a/test/integration/crud/explain.test.ts +++ b/test/integration/crud/explain.test.ts @@ -1,7 +1,13 @@ import { expect } from 'chai'; import { once } from 'events'; -import { type Collection, type Db, type MongoClient, MongoServerError } from '../../mongodb'; +import { + type Collection, + type CommandStartedEvent, + type Db, + type MongoClient, + MongoServerError +} from '../../mongodb'; const explain = [true, false, 'queryPlanner', 'allPlansExecution', 'executionStats', 'invalid']; From 17a44454d161ff7aabf41f064c5db4cd92881fda Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Wed, 28 Jun 2023 13:10:41 -0400 Subject: [PATCH 05/14] added optional chaining --- test/integration/crud/explain.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/crud/explain.test.ts b/test/integration/crud/explain.test.ts index d00caff025d..b3c50bd521a 100644 --- a/test/integration/crud/explain.test.ts +++ b/test/integration/crud/explain.test.ts @@ -11,7 +11,7 @@ import { const explain = [true, false, 'queryPlanner', 'allPlansExecution', 'executionStats', 'invalid']; -describe('CRUD API explain option', function () { +describe.only('CRUD API explain option', function () { let client: MongoClient; let db: Db; let collection: Collection; From 1e53b9182edc3a13bfdf337d216fa997db266ffd Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Wed, 28 Jun 2023 13:22:58 -0400 Subject: [PATCH 06/14] removed .only --- test/integration/crud/explain.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/crud/explain.test.ts b/test/integration/crud/explain.test.ts index b3c50bd521a..d00caff025d 100644 --- a/test/integration/crud/explain.test.ts +++ b/test/integration/crud/explain.test.ts @@ -11,7 +11,7 @@ import { const explain = [true, false, 'queryPlanner', 'allPlansExecution', 'executionStats', 'invalid']; -describe.only('CRUD API explain option', function () { +describe('CRUD API explain option', function () { let client: MongoClient; let db: Db; let collection: Collection; From e9d298dad7f6d2d032970ce4105e87e0e78a530e Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Thu, 29 Jun 2023 16:42:50 -0400 Subject: [PATCH 07/14] added async behavior to executeCommand added CommandCallbackOperation class changed executeCommand to executeCommandCallback --- src/operations/command.ts | 70 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/src/operations/command.ts b/src/operations/command.ts index 7880ad95a2d..104add0f332 100644 --- a/src/operations/command.ts +++ b/src/operations/command.ts @@ -1,3 +1,5 @@ +import { promisify } from 'util'; + import type { BSONSerializeOptions, Document } from '../bson'; import { MongoInvalidArgumentError } from '../error'; import { Explain, type ExplainOptions } from '../explain'; @@ -111,8 +113,7 @@ export abstract class CommandOperation extends AbstractCallbackOperation { server: Server, session: ClientSession | undefined, cmd: Document, - callback: Callback - ): void { + ): Promise { // TODO: consider making this a non-enumerable property this.server = server; @@ -154,6 +155,71 @@ export abstract class CommandOperation extends AbstractCallbackOperation { cmd = decorateWithExplain(cmd, this.explain); } + return server.commandAsync(this.ns, cmd, options); + } +} + +export abstract class CommandCallbackOperation extends AbstractCallbackOperation { + constructor(parent?: OperationParent, options?: CommandOperationOptions) { + super(parent, options); + } + + async executeCommand( + server: Server, + session: ClientSession | undefined, + cmd: Document + ): Promise { + return promisify((callback: (e: Error, r: T) => void) => { + this.executeCommandCallback(server, session, cmd, callback as any); + })(); + } + + protected abstract executeCommandCallback( + server: Server, + session: ClientSession | undefined, + cmd: Document, + callback: Callback + ): void; { + this.server = server; + + const options = { + ...this.options, + ...this.bsonOptions, + readPreference: this.readPreference, + session + }; + + const serverWireVersion = maxWireVersion(server); + const inTransaction = this.session && this.session.inTransaction(); + + if (this.readConcern && commandSupportsReadConcern(cmd) && !inTransaction) { + Object.assign(cmd, { readConcern: this.readConcern }); + } + + if (this.trySecondaryWrite && serverWireVersion < MIN_SECONDARY_WRITE_WIRE_VERSION) { + options.omitReadPreference = true; + } + + if (this.writeConcern && this.hasAspect(Aspect.WRITE_OPERATION) && !inTransaction) { + Object.assign(cmd, { writeConcern: this.writeConcern }); + } + + if ( + options.collation && + typeof options.collation === 'object' && + !this.hasAspect(Aspect.SKIP_COLLATION) + ) { + Object.assign(cmd, { collation: options.collation }); + } + + if (typeof options.maxTimeMS === 'number') { + cmd.maxTimeMS = options.maxTimeMS; + } + + if (this.hasAspect(Aspect.EXPLAINABLE) && this.explain) { + cmd = decorateWithExplain(cmd, this.explain); + } + server.command(this.ns, cmd, options, callback); } } From 6190ed887cc6a75a79a7d3c8aac019a94163d51a Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Thu, 29 Jun 2023 17:35:01 -0400 Subject: [PATCH 08/14] modified calls to executeCommandCallback modified inheritance to CommandCallbackOperation --- src/operations/add_user.ts | 6 +++--- src/operations/aggregate.ts | 10 +++++++--- src/operations/command.ts | 12 ++++++------ src/operations/count.ts | 6 +++--- src/operations/create_collection.ts | 6 +++--- src/operations/delete.ts | 10 +++++++--- src/operations/distinct.ts | 6 +++--- src/operations/drop.ts | 10 +++++----- src/operations/estimated_document_count.ts | 6 +++--- src/operations/eval.ts | 6 +++--- src/operations/find.ts | 8 ++++++-- src/operations/find_and_modify.ts | 6 +++--- src/operations/indexes.ts | 14 +++++++------- src/operations/insert.ts | 6 +++--- src/operations/list_collections.ts | 6 +++--- src/operations/list_databases.ts | 6 +++--- src/operations/profiling_level.ts | 6 +++--- src/operations/remove_user.ts | 6 +++--- src/operations/run_command.ts | 6 +++--- src/operations/set_profiling_level.ts | 6 +++--- src/operations/stats.ts | 10 +++++----- src/operations/update.ts | 10 +++++++--- src/operations/validate_collection.ts | 6 +++--- 23 files changed, 95 insertions(+), 79 deletions(-) diff --git a/src/operations/add_user.ts b/src/operations/add_user.ts index b60381f6d42..21a4bbc8c90 100644 --- a/src/operations/add_user.ts +++ b/src/operations/add_user.ts @@ -6,7 +6,7 @@ import { MongoInvalidArgumentError } from '../error'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; import { type Callback, emitWarningOnce, getTopology } from '../utils'; -import { CommandOperation, type CommandOperationOptions } from './command'; +import { CommandCallbackOperation, type CommandOperationOptions } from './command'; import { Aspect, defineAspects } from './operation'; /** @@ -35,7 +35,7 @@ export interface AddUserOptions extends CommandOperationOptions { } /** @internal */ -export class AddUserOperation extends CommandOperation { +export class AddUserOperation extends CommandCallbackOperation { override options: AddUserOptions; db: Db; username: string; @@ -117,7 +117,7 @@ export class AddUserOperation extends CommandOperation { command.pwd = userPassword; } - super.executeCommand(server, session, command, callback); + super.executeCommandCallback(server, session, command, callback); } } diff --git a/src/operations/aggregate.ts b/src/operations/aggregate.ts index a742b6ce9fd..47e19a4d8e2 100644 --- a/src/operations/aggregate.ts +++ b/src/operations/aggregate.ts @@ -4,7 +4,11 @@ import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; import { type Callback, maxWireVersion, type MongoDBNamespace } from '../utils'; import { WriteConcern } from '../write_concern'; -import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command'; +import { + type CollationOptions, + CommandCallbackOperation, + type CommandOperationOptions +} from './command'; import { Aspect, defineAspects, type Hint } from './operation'; /** @internal */ @@ -36,7 +40,7 @@ export interface AggregateOptions extends CommandOperationOptions { } /** @internal */ -export class AggregateOperation extends CommandOperation { +export class AggregateOperation extends CommandCallbackOperation { override options: AggregateOptions; target: string | typeof DB_AGGREGATE_COLLECTION; pipeline: Document[]; @@ -133,7 +137,7 @@ export class AggregateOperation extends CommandOperation { command.cursor.batchSize = options.batchSize; } - super.executeCommand(server, session, command, callback); + super.executeCommandCallback(server, session, command, callback); } } diff --git a/src/operations/command.ts b/src/operations/command.ts index 104add0f332..c092c3d3f48 100644 --- a/src/operations/command.ts +++ b/src/operations/command.ts @@ -109,10 +109,10 @@ export abstract class CommandOperation extends AbstractCallbackOperation { return true; } - executeCommand( + async executeCommand( server: Server, session: ClientSession | undefined, - cmd: Document, + cmd: Document ): Promise { // TODO: consider making this a non-enumerable property this.server = server; @@ -159,12 +159,12 @@ export abstract class CommandOperation extends AbstractCallbackOperation { } } -export abstract class CommandCallbackOperation extends AbstractCallbackOperation { +export abstract class CommandCallbackOperation extends CommandOperation { constructor(parent?: OperationParent, options?: CommandOperationOptions) { super(parent, options); } - async executeCommand( + override executeCommand( server: Server, session: ClientSession | undefined, cmd: Document @@ -174,12 +174,12 @@ export abstract class CommandCallbackOperation extends AbstractCallback })(); } - protected abstract executeCommandCallback( + protected executeCommandCallback( server: Server, session: ClientSession | undefined, cmd: Document, callback: Callback - ): void; { + ): void { this.server = server; const options = { diff --git a/src/operations/count.ts b/src/operations/count.ts index 0b21bdd359b..9a6da8eadde 100644 --- a/src/operations/count.ts +++ b/src/operations/count.ts @@ -3,7 +3,7 @@ import type { Collection } from '../collection'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; import type { Callback, MongoDBNamespace } from '../utils'; -import { CommandOperation, type CommandOperationOptions } from './command'; +import { CommandCallbackOperation, type CommandOperationOptions } from './command'; import { Aspect, defineAspects } from './operation'; /** @public */ @@ -19,7 +19,7 @@ export interface CountOptions extends CommandOperationOptions { } /** @internal */ -export class CountOperation extends CommandOperation { +export class CountOperation extends CommandCallbackOperation { override options: CountOptions; collectionName?: string; query: Document; @@ -59,7 +59,7 @@ export class CountOperation extends CommandOperation { cmd.maxTimeMS = options.maxTimeMS; } - super.executeCommand(server, session, cmd, (err, result) => { + super.executeCommandCallback(server, session, cmd, (err, result) => { callback(err, result ? result.n : 0); }); } diff --git a/src/operations/create_collection.ts b/src/operations/create_collection.ts index ff28e77dd07..9c5a668b795 100644 --- a/src/operations/create_collection.ts +++ b/src/operations/create_collection.ts @@ -10,7 +10,7 @@ import type { PkFactory } from '../mongo_client'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; import type { Callback } from '../utils'; -import { CommandOperation, type CommandOperationOptions } from './command'; +import { CommandCallbackOperation, type CommandOperationOptions } from './command'; import { CreateIndexOperation } from './indexes'; import { Aspect, defineAspects } from './operation'; @@ -108,7 +108,7 @@ const INVALID_QE_VERSION = 'Driver support of Queryable Encryption is incompatible with server. Upgrade server to use Queryable Encryption.'; /** @internal */ -export class CreateCollectionOperation extends CommandOperation { +export class CreateCollectionOperation extends CommandCallbackOperation { override options: CreateCollectionOptions; db: Db; name: string; @@ -209,7 +209,7 @@ export class CreateCollectionOperation extends CommandOperation { } // otherwise just execute the command - super.executeCommand(server, session, cmd, done); + super.executeCommandCallback(server, session, cmd, done); }); } } diff --git a/src/operations/delete.ts b/src/operations/delete.ts index c57658e237d..ba7e6b19ee2 100644 --- a/src/operations/delete.ts +++ b/src/operations/delete.ts @@ -5,7 +5,11 @@ import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; import type { Callback, MongoDBNamespace } from '../utils'; import type { WriteConcernOptions } from '../write_concern'; -import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command'; +import { + type CollationOptions, + CommandCallbackOperation, + type CommandOperationOptions +} from './command'; import { Aspect, defineAspects, type Hint } from './operation'; /** @public */ @@ -41,7 +45,7 @@ export interface DeleteStatement { } /** @internal */ -export class DeleteOperation extends CommandOperation { +export class DeleteOperation extends CommandCallbackOperation { override options: DeleteOptions; statements: DeleteStatement[]; @@ -92,7 +96,7 @@ export class DeleteOperation extends CommandOperation { } } - super.executeCommand(server, session, command, callback); + super.executeCommandCallback(server, session, command, callback); } } diff --git a/src/operations/distinct.ts b/src/operations/distinct.ts index 6468074b155..327b7687343 100644 --- a/src/operations/distinct.ts +++ b/src/operations/distinct.ts @@ -3,7 +3,7 @@ import type { Collection } from '../collection'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; import { type Callback, decorateWithCollation, decorateWithReadConcern } from '../utils'; -import { CommandOperation, type CommandOperationOptions } from './command'; +import { CommandCallbackOperation, type CommandOperationOptions } from './command'; import { Aspect, defineAspects } from './operation'; /** @public */ @@ -13,7 +13,7 @@ export type DistinctOptions = CommandOperationOptions; * Return a list of distinct values for the given key across a collection. * @internal */ -export class DistinctOperation extends CommandOperation { +export class DistinctOperation extends CommandCallbackOperation { override options: DistinctOptions; collection: Collection; /** Field of the document to find distinct values for. */ @@ -76,7 +76,7 @@ export class DistinctOperation extends CommandOperation { return callback(err); } - super.executeCommand(server, session, cmd, (err, result) => { + super.executeCommandCallback(server, session, cmd, (err, result) => { if (err) { callback(err); return; diff --git a/src/operations/drop.ts b/src/operations/drop.ts index 69e2e698264..5c71b152152 100644 --- a/src/operations/drop.ts +++ b/src/operations/drop.ts @@ -4,7 +4,7 @@ import { MONGODB_ERROR_CODES, MongoServerError } from '../error'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; import type { Callback } from '../utils'; -import { CommandOperation, type CommandOperationOptions } from './command'; +import { CommandCallbackOperation, type CommandOperationOptions } from './command'; import { Aspect, defineAspects } from './operation'; /** @public */ @@ -14,7 +14,7 @@ export interface DropCollectionOptions extends CommandOperationOptions { } /** @internal */ -export class DropCollectionOperation extends CommandOperation { +export class DropCollectionOperation extends CommandCallbackOperation { override options: DropCollectionOptions; db: Db; name: string; @@ -83,7 +83,7 @@ export class DropCollectionOperation extends CommandOperation { session: ClientSession | undefined ): Promise { return new Promise((resolve, reject) => { - super.executeCommand(server, session, { drop: this.name }, (err, result) => { + super.executeCommandCallback(server, session, { drop: this.name }, (err, result) => { if (err) return reject(err); resolve(!!result.ok); }); @@ -95,7 +95,7 @@ export class DropCollectionOperation extends CommandOperation { export type DropDatabaseOptions = CommandOperationOptions; /** @internal */ -export class DropDatabaseOperation extends CommandOperation { +export class DropDatabaseOperation extends CommandCallbackOperation { override options: DropDatabaseOptions; constructor(db: Db, options: DropDatabaseOptions) { @@ -107,7 +107,7 @@ export class DropDatabaseOperation extends CommandOperation { session: ClientSession | undefined, callback: Callback ): void { - super.executeCommand(server, session, { dropDatabase: 1 }, (err, result) => { + super.executeCommandCallback(server, session, { dropDatabase: 1 }, (err, result) => { if (err) return callback(err); if (result.ok) return callback(undefined, true); callback(undefined, false); diff --git a/src/operations/estimated_document_count.ts b/src/operations/estimated_document_count.ts index 8a9048bbaa9..c2195af77ad 100644 --- a/src/operations/estimated_document_count.ts +++ b/src/operations/estimated_document_count.ts @@ -3,7 +3,7 @@ import type { Collection } from '../collection'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; import type { Callback } from '../utils'; -import { CommandOperation, type CommandOperationOptions } from './command'; +import { CommandCallbackOperation, type CommandOperationOptions } from './command'; import { Aspect, defineAspects } from './operation'; /** @public */ @@ -17,7 +17,7 @@ export interface EstimatedDocumentCountOptions extends CommandOperationOptions { } /** @internal */ -export class EstimatedDocumentCountOperation extends CommandOperation { +export class EstimatedDocumentCountOperation extends CommandCallbackOperation { override options: EstimatedDocumentCountOptions; collectionName: string; @@ -44,7 +44,7 @@ export class EstimatedDocumentCountOperation extends CommandOperation { cmd.comment = this.options.comment; } - super.executeCommand(server, session, cmd, (err, response) => { + super.executeCommandCallback(server, session, cmd, (err, response) => { if (err) { callback(err); return; diff --git a/src/operations/eval.ts b/src/operations/eval.ts index 1f9b5ebbc47..a32a618891f 100644 --- a/src/operations/eval.ts +++ b/src/operations/eval.ts @@ -6,7 +6,7 @@ import { ReadPreference } from '../read_preference'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; import type { Callback } from '../utils'; -import { CommandOperation, type CommandOperationOptions } from './command'; +import { CommandCallbackOperation, type CommandOperationOptions } from './command'; /** @public */ export interface EvalOptions extends CommandOperationOptions { @@ -14,7 +14,7 @@ export interface EvalOptions extends CommandOperationOptions { } /** @internal */ -export class EvalOperation extends CommandOperation { +export class EvalOperation extends CommandCallbackOperation { override options: EvalOptions; code: Code; parameters?: Document | Document[]; @@ -65,7 +65,7 @@ export class EvalOperation extends CommandOperation { } // Execute the command - super.executeCommand(server, session, cmd, (err, result) => { + super.executeCommandCallback(server, session, cmd, (err, result) => { if (err) return callback(err); if (result && result.ok === 1) { return callback(undefined, result.retval); diff --git a/src/operations/find.ts b/src/operations/find.ts index 2d2da710e11..fd3d41e8c82 100644 --- a/src/operations/find.ts +++ b/src/operations/find.ts @@ -11,7 +11,11 @@ import { type MongoDBNamespace, normalizeHintField } from '../utils'; -import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command'; +import { + type CollationOptions, + CommandCallbackOperation, + type CommandOperationOptions +} from './command'; import { Aspect, defineAspects, type Hint } from './operation'; /** @@ -71,7 +75,7 @@ export interface FindOptions } /** @internal */ -export class FindOperation extends CommandOperation { +export class FindOperation extends CommandCallbackOperation { /** * @remarks WriteConcern can still be present on the options because * we inherit options from the client/db/collection. The diff --git a/src/operations/find_and_modify.ts b/src/operations/find_and_modify.ts index a9dca92d797..d92d6efbd86 100644 --- a/src/operations/find_and_modify.ts +++ b/src/operations/find_and_modify.ts @@ -7,7 +7,7 @@ import type { ClientSession } from '../sessions'; import { formatSort, type Sort, type SortForCmd } from '../sort'; import { type Callback, decorateWithCollation, hasAtomicOperators, maxWireVersion } from '../utils'; import type { WriteConcern, WriteConcernSettings } from '../write_concern'; -import { CommandOperation, type CommandOperationOptions } from './command'; +import { CommandCallbackOperation, type CommandOperationOptions } from './command'; import { Aspect, defineAspects } from './operation'; /** @public */ @@ -122,7 +122,7 @@ function configureFindAndModifyCmdBaseUpdateOpts( } /** @internal */ -class FindAndModifyOperation extends CommandOperation { +class FindAndModifyOperation extends CommandCallbackOperation { override options: FindOneAndReplaceOptions | FindOneAndUpdateOptions | FindOneAndDeleteOptions; cmdBase: FindAndModifyCmdBase; collection: Collection; @@ -220,7 +220,7 @@ class FindAndModifyOperation extends CommandOperation { } // Execute the command - super.executeCommand(server, session, cmd, (err, result) => { + super.executeCommandCallback(server, session, cmd, (err, result) => { if (err) return callback(err); return callback(undefined, options.includeResultMetadata ? result : result.value ?? null); }); diff --git a/src/operations/indexes.ts b/src/operations/indexes.ts index 25542c98075..93b68f0718a 100644 --- a/src/operations/indexes.ts +++ b/src/operations/indexes.ts @@ -9,7 +9,7 @@ import type { ClientSession } from '../sessions'; import { type Callback, isObject, maxWireVersion, type MongoDBNamespace } from '../utils'; import { type CollationOptions, - CommandOperation, + CommandCallbackOperation, type CommandOperationOptions, type OperationParent } from './command'; @@ -206,7 +206,7 @@ export class IndexesOperation extends AbstractCallbackOperation { /** @internal */ export class CreateIndexesOperation< T extends string | string[] = string[] -> extends CommandOperation { +> extends CommandCallbackOperation { override options: CreateIndexesOptions; collectionName: string; indexes: ReadonlyArray & { key: Map }>; @@ -266,7 +266,7 @@ export class CreateIndexesOperation< // collation is set on each index, it should not be defined at the root this.options.collation = undefined; - super.executeCommand(server, session, cmd, err => { + super.executeCommandCallback(server, session, cmd, err => { if (err) { callback(err); return; @@ -348,7 +348,7 @@ export class EnsureIndexOperation extends CreateIndexOperation { export type DropIndexesOptions = CommandOperationOptions; /** @internal */ -export class DropIndexOperation extends CommandOperation { +export class DropIndexOperation extends CommandCallbackOperation { override options: DropIndexesOptions; collection: Collection; indexName: string; @@ -367,7 +367,7 @@ export class DropIndexOperation extends CommandOperation { callback: Callback ): void { const cmd = { dropIndexes: this.collection.collectionName, index: this.indexName }; - super.executeCommand(server, session, cmd, callback); + super.executeCommandCallback(server, session, cmd, callback); } } @@ -396,7 +396,7 @@ export interface ListIndexesOptions extends Omit { +export class ListIndexesOperation extends CommandCallbackOperation { /** * @remarks WriteConcern can still be present on the options because * we inherit options from the client/db/collection. The @@ -432,7 +432,7 @@ export class ListIndexesOperation extends CommandOperation { command.comment = this.options.comment; } - super.executeCommand(server, session, command, callback); + super.executeCommandCallback(server, session, command, callback); } } diff --git a/src/operations/insert.ts b/src/operations/insert.ts index ed208cad2e2..7ab61ac3091 100644 --- a/src/operations/insert.ts +++ b/src/operations/insert.ts @@ -8,12 +8,12 @@ import type { ClientSession } from '../sessions'; import type { Callback, MongoDBNamespace } from '../utils'; import { WriteConcern } from '../write_concern'; import { BulkWriteOperation } from './bulk_write'; -import { CommandOperation, type CommandOperationOptions } from './command'; +import { CommandCallbackOperation, type CommandOperationOptions } from './command'; import { prepareDocs } from './common_functions'; import { AbstractCallbackOperation, Aspect, defineAspects } from './operation'; /** @internal */ -export class InsertOperation extends CommandOperation { +export class InsertOperation extends CommandCallbackOperation { override options: BulkWriteOptions; documents: Document[]; @@ -47,7 +47,7 @@ export class InsertOperation extends CommandOperation { command.comment = options.comment; } - super.executeCommand(server, session, command, callback); + super.executeCommandCallback(server, session, command, callback); } } diff --git a/src/operations/list_collections.ts b/src/operations/list_collections.ts index 339380524a4..dddd4db274c 100644 --- a/src/operations/list_collections.ts +++ b/src/operations/list_collections.ts @@ -3,7 +3,7 @@ import type { Db } from '../db'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; import { type Callback, maxWireVersion } from '../utils'; -import { CommandOperation, type CommandOperationOptions } from './command'; +import { CommandCallbackOperation, type CommandOperationOptions } from './command'; import { Aspect, defineAspects } from './operation'; /** @public */ @@ -17,7 +17,7 @@ export interface ListCollectionsOptions extends Omit { +export class ListCollectionsOperation extends CommandCallbackOperation { /** * @remarks WriteConcern can still be present on the options because * we inherit options from the client/db/collection. The @@ -52,7 +52,7 @@ export class ListCollectionsOperation extends CommandOperation { session: ClientSession | undefined, callback: Callback ): void { - return super.executeCommand( + return super.executeCommandCallback( server, session, this.generateCommand(maxWireVersion(server)), diff --git a/src/operations/list_databases.ts b/src/operations/list_databases.ts index 6979f566e37..8605e0661a9 100644 --- a/src/operations/list_databases.ts +++ b/src/operations/list_databases.ts @@ -3,7 +3,7 @@ import type { Db } from '../db'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; import { type Callback, maxWireVersion, MongoDBNamespace } from '../utils'; -import { CommandOperation, type CommandOperationOptions } from './command'; +import { CommandCallbackOperation, type CommandOperationOptions } from './command'; import { Aspect, defineAspects } from './operation'; /** @public */ @@ -25,7 +25,7 @@ export interface ListDatabasesOptions extends CommandOperationOptions { } /** @internal */ -export class ListDatabasesOperation extends CommandOperation { +export class ListDatabasesOperation extends CommandCallbackOperation { override options: ListDatabasesOptions; constructor(db: Db, options?: ListDatabasesOptions) { @@ -59,7 +59,7 @@ export class ListDatabasesOperation extends CommandOperation { +export class ProfilingLevelOperation extends CommandCallbackOperation { override options: ProfilingLevelOptions; constructor(db: Db, options: ProfilingLevelOptions) { @@ -22,7 +22,7 @@ export class ProfilingLevelOperation extends CommandOperation { session: ClientSession | undefined, callback: Callback ): void { - super.executeCommand(server, session, { profile: -1 }, (err, doc) => { + super.executeCommandCallback(server, session, { profile: -1 }, (err, doc) => { if (err == null && doc.ok === 1) { const was = doc.was; if (was === 0) return callback(undefined, 'off'); diff --git a/src/operations/remove_user.ts b/src/operations/remove_user.ts index 1da6ebd6cde..e742fc42ee7 100644 --- a/src/operations/remove_user.ts +++ b/src/operations/remove_user.ts @@ -2,14 +2,14 @@ import type { Db } from '../db'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; import type { Callback } from '../utils'; -import { CommandOperation, type CommandOperationOptions } from './command'; +import { CommandCallbackOperation, type CommandOperationOptions } from './command'; import { Aspect, defineAspects } from './operation'; /** @public */ export type RemoveUserOptions = CommandOperationOptions; /** @internal */ -export class RemoveUserOperation extends CommandOperation { +export class RemoveUserOperation extends CommandCallbackOperation { override options: RemoveUserOptions; username: string; @@ -24,7 +24,7 @@ export class RemoveUserOperation extends CommandOperation { session: ClientSession | undefined, callback: Callback ): void { - super.executeCommand(server, session, { dropUser: this.username }, err => { + super.executeCommandCallback(server, session, { dropUser: this.username }, err => { callback(err, err ? false : true); }); } diff --git a/src/operations/run_command.ts b/src/operations/run_command.ts index c11013a3708..352965e836b 100644 --- a/src/operations/run_command.ts +++ b/src/operations/run_command.ts @@ -3,7 +3,7 @@ import type { ReadPreferenceLike } from '../read_preference'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; import { type Callback, MongoDBNamespace } from '../utils'; -import { CommandOperation, type OperationParent } from './command'; +import { CommandCallbackOperation, type OperationParent } from './command'; /** @public */ export type RunCommandOptions = { @@ -45,7 +45,7 @@ export type RunCommandOptions = { } & BSONSerializeOptions; /** @internal */ -export class RunCommandOperation extends CommandOperation { +export class RunCommandOperation extends CommandCallbackOperation { override options: RunCommandOptions; command: Document; @@ -61,7 +61,7 @@ export class RunCommandOperation extends CommandOperation { callback: Callback ): void { const command = this.command; - this.executeCommand(server, session, command, callback); + this.executeCommandCallback(server, session, command, callback); } } diff --git a/src/operations/set_profiling_level.ts b/src/operations/set_profiling_level.ts index 2d097d2d250..d4416052d89 100644 --- a/src/operations/set_profiling_level.ts +++ b/src/operations/set_profiling_level.ts @@ -4,7 +4,7 @@ import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; import type { Callback } from '../utils'; import { enumToString } from '../utils'; -import { CommandOperation, type CommandOperationOptions } from './command'; +import { CommandCallbackOperation, type CommandOperationOptions } from './command'; const levelValues = new Set(['off', 'slow_only', 'all']); @@ -22,7 +22,7 @@ export type ProfilingLevel = (typeof ProfilingLevel)[keyof typeof ProfilingLevel export type SetProfilingLevelOptions = CommandOperationOptions; /** @internal */ -export class SetProfilingLevelOperation extends CommandOperation { +export class SetProfilingLevelOperation extends CommandCallbackOperation { override options: SetProfilingLevelOptions; level: ProfilingLevel; profile: 0 | 1 | 2; @@ -64,7 +64,7 @@ export class SetProfilingLevelOperation extends CommandOperation } // TODO(NODE-3483): Determine error to put here - super.executeCommand(server, session, { profile: this.profile }, (err, doc) => { + super.executeCommandCallback(server, session, { profile: this.profile }, (err, doc) => { if (err == null && doc.ok === 1) return callback(undefined, level); return err != null ? callback(err) diff --git a/src/operations/stats.ts b/src/operations/stats.ts index 5ecdea821c0..c06d11cd9e1 100644 --- a/src/operations/stats.ts +++ b/src/operations/stats.ts @@ -4,7 +4,7 @@ import type { Db } from '../db'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; import type { Callback } from '../utils'; -import { CommandOperation, type CommandOperationOptions } from './command'; +import { CommandCallbackOperation, type CommandOperationOptions } from './command'; import { Aspect, defineAspects } from './operation'; /** @@ -21,7 +21,7 @@ export interface CollStatsOptions extends CommandOperationOptions { * Get all the collection statistics. * @internal */ -export class CollStatsOperation extends CommandOperation { +export class CollStatsOperation extends CommandCallbackOperation { override options: CollStatsOptions; collectionName: string; @@ -47,7 +47,7 @@ export class CollStatsOperation extends CommandOperation { command.scale = this.options.scale; } - super.executeCommand(server, session, command, callback); + super.executeCommandCallback(server, session, command, callback); } } @@ -58,7 +58,7 @@ export interface DbStatsOptions extends CommandOperationOptions { } /** @internal */ -export class DbStatsOperation extends CommandOperation { +export class DbStatsOperation extends CommandCallbackOperation { override options: DbStatsOptions; constructor(db: Db, options: DbStatsOptions) { @@ -76,7 +76,7 @@ export class DbStatsOperation extends CommandOperation { command.scale = this.options.scale; } - super.executeCommand(server, session, command, callback); + super.executeCommandCallback(server, session, command, callback); } } diff --git a/src/operations/update.ts b/src/operations/update.ts index 2312353044b..7a25a429847 100644 --- a/src/operations/update.ts +++ b/src/operations/update.ts @@ -5,7 +5,11 @@ import type { InferIdType } from '../mongo_types'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; import { type Callback, hasAtomicOperators, type MongoDBNamespace } from '../utils'; -import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command'; +import { + type CollationOptions, + CommandCallbackOperation, + type CommandOperationOptions +} from './command'; import { Aspect, defineAspects, type Hint } from './operation'; /** @public */ @@ -60,7 +64,7 @@ export interface UpdateStatement { } /** @internal */ -export class UpdateOperation extends CommandOperation { +export class UpdateOperation extends CommandCallbackOperation { override options: UpdateOptions & { ordered?: boolean }; statements: UpdateStatement[]; @@ -120,7 +124,7 @@ export class UpdateOperation extends CommandOperation { } } - super.executeCommand(server, session, command, callback); + super.executeCommandCallback(server, session, command, callback); } } diff --git a/src/operations/validate_collection.ts b/src/operations/validate_collection.ts index c47a0b81b58..3b48bbdce2d 100644 --- a/src/operations/validate_collection.ts +++ b/src/operations/validate_collection.ts @@ -4,7 +4,7 @@ import { MongoRuntimeError } from '../error'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; import type { Callback } from '../utils'; -import { CommandOperation, type CommandOperationOptions } from './command'; +import { CommandCallbackOperation, type CommandOperationOptions } from './command'; /** @public */ export interface ValidateCollectionOptions extends CommandOperationOptions { @@ -13,7 +13,7 @@ export interface ValidateCollectionOptions extends CommandOperationOptions { } /** @internal */ -export class ValidateCollectionOperation extends CommandOperation { +export class ValidateCollectionOperation extends CommandCallbackOperation { override options: ValidateCollectionOptions; collectionName: string; command: Document; @@ -41,7 +41,7 @@ export class ValidateCollectionOperation extends CommandOperation { ): void { const collectionName = this.collectionName; - super.executeCommand(server, session, this.command, (err, doc) => { + super.executeCommandCallback(server, session, this.command, (err, doc) => { if (err != null) return callback(err); // TODO(NODE-3483): Replace these with MongoUnexpectedServerResponseError From b075b9e6587b4334ff2d6cb0a2ed695a68b0c10d Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Fri, 30 Jun 2023 12:11:29 -0400 Subject: [PATCH 09/14] removed executeCommand in CommandCallback --- src/operations/command.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/operations/command.ts b/src/operations/command.ts index c092c3d3f48..e67ce49355d 100644 --- a/src/operations/command.ts +++ b/src/operations/command.ts @@ -1,5 +1,3 @@ -import { promisify } from 'util'; - import type { BSONSerializeOptions, Document } from '../bson'; import { MongoInvalidArgumentError } from '../error'; import { Explain, type ExplainOptions } from '../explain'; @@ -164,16 +162,6 @@ export abstract class CommandCallbackOperation extends CommandOperation super(parent, options); } - override executeCommand( - server: Server, - session: ClientSession | undefined, - cmd: Document - ): Promise { - return promisify((callback: (e: Error, r: T) => void) => { - this.executeCommandCallback(server, session, cmd, callback as any); - })(); - } - protected executeCommandCallback( server: Server, session: ClientSession | undefined, From 966244a321c400331c02c35b96ee4655a514a22c Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Fri, 30 Jun 2023 12:14:15 -0400 Subject: [PATCH 10/14] tested that executeCommand invokes server.Command --- test/unit/operations/abstract_command.test.ts | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 test/unit/operations/abstract_command.test.ts diff --git a/test/unit/operations/abstract_command.test.ts b/test/unit/operations/abstract_command.test.ts new file mode 100644 index 00000000000..f1d16407127 --- /dev/null +++ b/test/unit/operations/abstract_command.test.ts @@ -0,0 +1,58 @@ +import { expect } from 'chai'; +import * as sinon from 'sinon'; + +import { + type Callback, + type ClientSession, + CommandOperation, + type CommandOperationOptions, +type Document, + type OperationParent, + Server, + ServerDescription +} from '../../mongodb'; +import { topologyWithPlaceholderClient } from '../../tools/utils'; + +class ConcreteCommand extends CommandOperation { + constructor(parent?: OperationParent, options?: CommandOperationOptions) { + super(parent, options); + } + + async executeCommand( + server: Server, + session: ClientSession | undefined, + cmd: Document + ): Promise { + return super.executeCommand(server, session, cmd); + } + + protected executeCallback( + server: Server, + session: ClientSession | undefined, + callback: Callback + ) { + return [server, session, callback]; + } +} + +describe('class CommandOperation', () => { + let server: Server; + beforeEach(() => { + server = new Server( + topologyWithPlaceholderClient([], {} as any), + new ServerDescription('a:1'), + {} as any + ); + }); + + context('when a server is created', () => { + it('calls server.commandAsync when executeCommand is invoked', async () => { + const operation = new ConcreteCommand(); + const serverSpy = sinon.stub(server, 'commandAsync'); + const commandPromise = operation.executeCommand(server, undefined, { ping: 1 }); + expect(commandPromise).to.be.instanceOf(Promise); + await commandPromise; + expect(serverSpy).to.have.been.calledOnce; + }); + }); +}); From 4eb8fb451f2d7cb0ea0cec389f5a87bfd00cffd4 Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Fri, 30 Jun 2023 13:37:08 -0400 Subject: [PATCH 11/14] fixed lint and formatting errors --- src/index.ts | 1 + src/operations/command.ts | 1 + test/unit/operations/abstract_command.test.ts | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index daf30704a16..edcc43610d8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -388,6 +388,7 @@ export type { CommandOperationOptions, OperationParent } from './operations/command'; +export type { CommandCallbackOperation } from './operations/command'; export type { IndexInformationOptions } from './operations/common_functions'; export type { CountOptions } from './operations/count'; export type { CountDocumentsOptions } from './operations/count_documents'; diff --git a/src/operations/command.ts b/src/operations/command.ts index e67ce49355d..a801d207a64 100644 --- a/src/operations/command.ts +++ b/src/operations/command.ts @@ -157,6 +157,7 @@ export abstract class CommandOperation extends AbstractCallbackOperation { } } +/** @internal */ export abstract class CommandCallbackOperation extends CommandOperation { constructor(parent?: OperationParent, options?: CommandOperationOptions) { super(parent, options); diff --git a/test/unit/operations/abstract_command.test.ts b/test/unit/operations/abstract_command.test.ts index f1d16407127..8011f30fe7d 100644 --- a/test/unit/operations/abstract_command.test.ts +++ b/test/unit/operations/abstract_command.test.ts @@ -6,7 +6,7 @@ import { type ClientSession, CommandOperation, type CommandOperationOptions, -type Document, + type Document, type OperationParent, Server, ServerDescription From b1d20167df2644ce67121c0645dee09ba1eec4a9 Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Wed, 5 Jul 2023 15:50:43 -0400 Subject: [PATCH 12/14] implemented executeCallback executeCallbackCommand now invokes executeCommand --- src/operations/command.ts | 47 ++----------------- src/sdam/server.ts | 9 ++-- test/unit/operations/abstract_command.test.ts | 7 ++- 3 files changed, 13 insertions(+), 50 deletions(-) diff --git a/src/operations/command.ts b/src/operations/command.ts index a801d207a64..29bd2970f71 100644 --- a/src/operations/command.ts +++ b/src/operations/command.ts @@ -111,7 +111,7 @@ export abstract class CommandOperation extends AbstractCallbackOperation { server: Server, session: ClientSession | undefined, cmd: Document - ): Promise { + ): Promise { // TODO: consider making this a non-enumerable property this.server = server; @@ -169,46 +169,9 @@ export abstract class CommandCallbackOperation extends CommandOperation cmd: Document, callback: Callback ): void { - this.server = server; - - const options = { - ...this.options, - ...this.bsonOptions, - readPreference: this.readPreference, - session - }; - - const serverWireVersion = maxWireVersion(server); - const inTransaction = this.session && this.session.inTransaction(); - - if (this.readConcern && commandSupportsReadConcern(cmd) && !inTransaction) { - Object.assign(cmd, { readConcern: this.readConcern }); - } - - if (this.trySecondaryWrite && serverWireVersion < MIN_SECONDARY_WRITE_WIRE_VERSION) { - options.omitReadPreference = true; - } - - if (this.writeConcern && this.hasAspect(Aspect.WRITE_OPERATION) && !inTransaction) { - Object.assign(cmd, { writeConcern: this.writeConcern }); - } - - if ( - options.collation && - typeof options.collation === 'object' && - !this.hasAspect(Aspect.SKIP_COLLATION) - ) { - Object.assign(cmd, { collation: options.collation }); - } - - if (typeof options.maxTimeMS === 'number') { - cmd.maxTimeMS = options.maxTimeMS; - } - - if (this.hasAspect(Aspect.EXPLAINABLE) && this.explain) { - cmd = decorateWithExplain(cmd, this.explain); - } - - server.command(this.ns, cmd, options, callback); + super.executeCommand(server, session, cmd).then( + res => callback(undefined, res), + err => callback(err, undefined) + ); } } diff --git a/src/sdam/server.ts b/src/sdam/server.ts index 43f9d1ab6e0..f76f8c9a8c0 100644 --- a/src/sdam/server.ts +++ b/src/sdam/server.ts @@ -118,11 +118,7 @@ export class Server extends TypedEventEmitter { pool: ConnectionPool; serverApi?: ServerApi; hello?: Document; - commandAsync: ( - ns: MongoDBNamespace, - cmd: Document, - options: CommandOptions - ) => Promise; + commandAsync: (ns: MongoDBNamespace, cmd: Document, options: CommandOptions) => Promise; [kMonitor]: Monitor | null; /** @event */ @@ -151,7 +147,8 @@ export class Server extends TypedEventEmitter { ns: MongoDBNamespace, cmd: Document, options: CommandOptions, - callback: Callback + // callback type defines Document result because result is never nullish when it succeeds, otherwise promise rejects + callback: (error: Error | undefined, result: Document) => void ) => this.command(ns, cmd, options, callback as any) ); diff --git a/test/unit/operations/abstract_command.test.ts b/test/unit/operations/abstract_command.test.ts index 8011f30fe7d..9f465266c32 100644 --- a/test/unit/operations/abstract_command.test.ts +++ b/test/unit/operations/abstract_command.test.ts @@ -31,7 +31,10 @@ class ConcreteCommand extends CommandOperation { session: ClientSession | undefined, callback: Callback ) { - return [server, session, callback]; + super.execute(server, session).then( + res => callback(undefined, res), + err => callback(err, undefined) + ); } } @@ -50,7 +53,7 @@ describe('class CommandOperation', () => { const operation = new ConcreteCommand(); const serverSpy = sinon.stub(server, 'commandAsync'); const commandPromise = operation.executeCommand(server, undefined, { ping: 1 }); - expect(commandPromise).to.be.instanceOf(Promise); + expect(commandPromise).to.be.instanceOf(Promise); await commandPromise; expect(serverSpy).to.have.been.calledOnce; }); From f76c355fb8ba01439685a6284b280c8beb937073 Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Thu, 6 Jul 2023 10:49:14 -0400 Subject: [PATCH 13/14] updated test cases --- src/operations/command.ts | 2 +- test/unit/operations/abstract_command.test.ts | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/operations/command.ts b/src/operations/command.ts index 29bd2970f71..f6ec6cbe021 100644 --- a/src/operations/command.ts +++ b/src/operations/command.ts @@ -163,7 +163,7 @@ export abstract class CommandCallbackOperation extends CommandOperation super(parent, options); } - protected executeCommandCallback( + executeCommandCallback( server: Server, session: ClientSession | undefined, cmd: Document, diff --git a/test/unit/operations/abstract_command.test.ts b/test/unit/operations/abstract_command.test.ts index 9f465266c32..0b39bf7bea5 100644 --- a/test/unit/operations/abstract_command.test.ts +++ b/test/unit/operations/abstract_command.test.ts @@ -4,7 +4,7 @@ import * as sinon from 'sinon'; import { type Callback, type ClientSession, - CommandOperation, + CommandCallbackOperation, type CommandOperationOptions, type Document, type OperationParent, @@ -13,7 +13,7 @@ import { } from '../../mongodb'; import { topologyWithPlaceholderClient } from '../../tools/utils'; -class ConcreteCommand extends CommandOperation { +class ConcreteCommand extends CommandCallbackOperation { constructor(parent?: OperationParent, options?: CommandOperationOptions) { super(parent, options); } @@ -49,12 +49,12 @@ describe('class CommandOperation', () => { }); context('when a server is created', () => { - it('calls server.commandAsync when executeCommand is invoked', async () => { + it('calls executeCommand, which calls server.commandAsync, when executeCommandCallback is invoked', async () => { const operation = new ConcreteCommand(); const serverSpy = sinon.stub(server, 'commandAsync'); - const commandPromise = operation.executeCommand(server, undefined, { ping: 1 }); - expect(commandPromise).to.be.instanceOf(Promise); - await commandPromise; + operation.executeCommandCallback(server, undefined, { ping: 1 }, (err, res) => { + err ? err : res; + }); expect(serverSpy).to.have.been.calledOnce; }); }); From a971726cd283dfa2b93b0d8efbfe2b20d7e8f5d2 Mon Sep 17 00:00:00 2001 From: Malik Javaid Date: Thu, 6 Jul 2023 13:57:08 -0400 Subject: [PATCH 14/14] changed sinon.spy to use prototype --- test/unit/operations/abstract_command.test.ts | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/test/unit/operations/abstract_command.test.ts b/test/unit/operations/abstract_command.test.ts index 0b39bf7bea5..c024db08a9c 100644 --- a/test/unit/operations/abstract_command.test.ts +++ b/test/unit/operations/abstract_command.test.ts @@ -5,8 +5,8 @@ import { type Callback, type ClientSession, CommandCallbackOperation, + CommandOperation, type CommandOperationOptions, - type Document, type OperationParent, Server, ServerDescription @@ -18,14 +18,6 @@ class ConcreteCommand extends CommandCallbackOperation { super(parent, options); } - async executeCommand( - server: Server, - session: ClientSession | undefined, - cmd: Document - ): Promise { - return super.executeCommand(server, session, cmd); - } - protected executeCallback( server: Server, session: ClientSession | undefined, @@ -48,14 +40,18 @@ describe('class CommandOperation', () => { ); }); - context('when a server is created', () => { - it('calls executeCommand, which calls server.commandAsync, when executeCommandCallback is invoked', async () => { + context('when an operation uses CommandCallbackOperation', () => { + it('calls executeCommand when executeCommandCallback is invoked', done => { const operation = new ConcreteCommand(); - const serverSpy = sinon.stub(server, 'commandAsync'); - operation.executeCommandCallback(server, undefined, { ping: 1 }, (err, res) => { - err ? err : res; + const operationSpy = sinon.spy(CommandOperation.prototype, 'executeCommand'); + operation.executeCommandCallback(server, undefined, { ping: 1 }, () => { + try { + expect(operationSpy).to.have.been.calledOnceWithExactly(server, undefined, { ping: 1 }); + done(); + } catch (error) { + done(error); + } }); - expect(serverSpy).to.have.been.calledOnce; }); }); });