From 8ec6dcbe73bc842eb7a5ce3ea338d690a072f729 Mon Sep 17 00:00:00 2001 From: Daria Pardue Date: Thu, 11 Aug 2022 20:23:04 -0400 Subject: [PATCH] test: unify event collection in unified runner --- test/tools/unified-spec-runner/entities.ts | 89 +++++++++----------- test/tools/unified-spec-runner/match.ts | 10 +-- test/tools/unified-spec-runner/operations.ts | 8 +- test/tools/unified-spec-runner/runner.ts | 14 +-- 4 files changed, 51 insertions(+), 70 deletions(-) diff --git a/test/tools/unified-spec-runner/entities.ts b/test/tools/unified-spec-runner/entities.ts index 28bc11aff67..6f2c7fd4be6 100644 --- a/test/tools/unified-spec-runner/entities.ts +++ b/test/tools/unified-spec-runner/entities.ts @@ -48,8 +48,7 @@ export interface UnifiedChangeStream extends ChangeStream { eventCollector: InstanceType; } -export type CommandEvent = CommandStartedEvent | CommandSucceededEvent | CommandFailedEvent; -export type CmapEvent = +export type CapturedEvent = | ConnectionPoolCreatedEvent | ConnectionPoolClosedEvent | ConnectionCreatedEvent @@ -59,21 +58,20 @@ export type CmapEvent = | ConnectionCheckOutFailedEvent | ConnectionCheckedOutEvent | ConnectionCheckedInEvent - | ConnectionPoolClearedEvent; + | ConnectionPoolClearedEvent + | CommandStartedEvent + | CommandSucceededEvent + | CommandFailedEvent; function getClient(address) { return new MongoClient(`mongodb://${address}`, getEnvironmentalOptions()); } -type PushFunction = (e: any) => void; - export class UnifiedMongoClient extends MongoClient { - commandEvents: CommandEvent[]; - cmapEvents: CmapEvent[]; + capturedEvents: CapturedEvent[]; failPoints: Document[]; ignoredEvents: string[]; - observedCommandEvents: ('commandStarted' | 'commandSucceeded' | 'commandFailed')[]; - observedCmapEvents: ( + observedEvents: ( | 'connectionPoolCreated' | 'connectionPoolClosed' | 'connectionPoolCleared' @@ -84,16 +82,13 @@ export class UnifiedMongoClient extends MongoClient { | 'connectionCheckOutFailed' | 'connectionCheckedOut' | 'connectionCheckedIn' + | 'commandStarted' + | 'commandSucceeded' + | 'commandFailed' )[]; _credentials: MongoCredentials | null; - static COMMAND_EVENT_NAME_LOOKUP = { - commandStartedEvent: 'commandStarted', - commandSucceededEvent: 'commandSucceeded', - commandFailedEvent: 'commandFailed' - } as const; - - static CMAP_EVENT_NAME_LOOKUP = { + static EVENT_NAME_LOOKUP = { poolCreatedEvent: 'connectionPoolCreated', poolClosedEvent: 'connectionPoolClosed', poolClearedEvent: 'connectionPoolCleared', @@ -103,7 +98,10 @@ export class UnifiedMongoClient extends MongoClient { connectionCheckOutStartedEvent: 'connectionCheckOutStarted', connectionCheckOutFailedEvent: 'connectionCheckOutFailed', connectionCheckedOutEvent: 'connectionCheckedOut', - connectionCheckedInEvent: 'connectionCheckedIn' + connectionCheckedInEvent: 'connectionCheckedIn', + commandStartedEvent: 'commandStarted', + commandSucceededEvent: 'commandSucceeded', + commandFailedEvent: 'commandFailed' } as const; constructor(uri: string, description: ClientEntity) { @@ -114,60 +112,49 @@ export class UnifiedMongoClient extends MongoClient { ...(description.serverApi ? { serverApi: description.serverApi } : {}) }); - this.commandEvents = []; - this.cmapEvents = []; + this.capturedEvents = []; this.failPoints = []; this.ignoredEvents = [ ...(description.ignoreCommandMonitoringEvents ?? []), 'configureFailPoint' ]; - this.observedCommandEvents = (description.observeEvents ?? []) - .map(e => UnifiedMongoClient.COMMAND_EVENT_NAME_LOOKUP[e]) + this.observedEvents = (description.observeEvents ?? []) + .map(e => UnifiedMongoClient.EVENT_NAME_LOOKUP[e]) .filter(e => !!e); - this.observedCmapEvents = (description.observeEvents ?? []) - .map(e => UnifiedMongoClient.CMAP_EVENT_NAME_LOOKUP[e]) + this.observedEvents = (description.observeEvents ?? []) + .map(e => UnifiedMongoClient.EVENT_NAME_LOOKUP[e]) .filter(e => !!e); - for (const eventName of this.observedCommandEvents) { - this.on(eventName, this.pushCommandEvent); + for (const eventName of this.observedEvents) { + this.on(eventName, this.pushEvent); } - for (const eventName of this.observedCmapEvents) { - this.on(eventName, this.pushCmapEvent); + for (const eventName of this.observedEvents) { + this.on(eventName, this.pushEvent); } } - isIgnored(e: CommandEvent): boolean { - return this.ignoredEvents.includes(e.commandName); + isIgnored(e: CapturedEvent): boolean { + const commandName = (e as any).commandName; + if (!commandName) { + return false; + } + return this.ignoredEvents.includes(commandName); } - // NOTE: pushCommandEvent must be an arrow function - pushCommandEvent: (e: CommandEvent) => void = e => { + // NOTE: pushEvent must be an arrow function + pushEvent: (e: CapturedEvent) => void = e => { if (!this.isIgnored(e)) { - this.commandEvents.push(e); + this.capturedEvents.push(e); } }; - // NOTE: pushCmapEvent must be an arrow function - pushCmapEvent: (e: CmapEvent) => void = e => { - this.cmapEvents.push(e); - }; - - stopCapturingEvents(pushFn: PushFunction): void { - const observedEvents = [...this.observedCommandEvents, ...this.observedCmapEvents]; + /** Disables command monitoring for the client and returns a list of the captured events. */ + stopCapturingEvents(): CapturedEvent[] { + const observedEvents = [...this.observedEvents, ...this.observedEvents]; for (const eventName of observedEvents) { - this.off(eventName, pushFn); + this.off(eventName, this.pushEvent); } - } - - /** Disables command monitoring for the client and returns a list of the captured events. */ - stopCapturingCommandEvents(): CommandEvent[] { - this.stopCapturingEvents(this.pushCommandEvent); - return this.commandEvents; - } - - stopCapturingCmapEvents(): CmapEvent[] { - this.stopCapturingEvents(this.pushCmapEvent); - return this.cmapEvents; + return this.capturedEvents; } } diff --git a/test/tools/unified-spec-runner/match.ts b/test/tools/unified-spec-runner/match.ts index 4aaad51a8e0..458ef3c2f0e 100644 --- a/test/tools/unified-spec-runner/match.ts +++ b/test/tools/unified-spec-runner/match.ts @@ -30,7 +30,7 @@ import { ConnectionReadyEvent } from '../../../src/cmap/connection_pool_events'; import { ejson } from '../utils'; -import { CmapEvent, CommandEvent, EntitiesMap } from './entities'; +import { CapturedEvent, EntitiesMap } from './entities'; import { ExpectedCmapEvent, ExpectedCommandEvent, @@ -340,7 +340,7 @@ const EMPTY_CMAP_EVENTS = { function validEmptyCmapEvent( expected: ExpectedCommandEvent | ExpectedCmapEvent, - actual: CommandEvent | CmapEvent + actual: CapturedEvent | CapturedEvent ) { return Object.values(EMPTY_CMAP_EVENTS).some(value => { return actual instanceof value; @@ -348,7 +348,7 @@ function validEmptyCmapEvent( } function failOnMismatchedCount( - actual: CommandEvent[] | CmapEvent[], + actual: CapturedEvent[] | CapturedEvent[], expected: (ExpectedCommandEvent & ExpectedCmapEvent)[] ) { const actualNames = actual.map(a => a.constructor.name); @@ -423,7 +423,7 @@ function compareCommandFailedEvents( } function compareEvents( - actual: CommandEvent[] | CmapEvent[], + actual: CapturedEvent[] | CapturedEvent[], expected: (ExpectedCommandEvent & ExpectedCmapEvent)[], entities: EntitiesMap ) { @@ -477,7 +477,7 @@ function compareEvents( export function matchesEvents( { events: expected, ignoreExtraEvents }: ExpectedEventsForClient, - actual: CommandEvent[] | CmapEvent[], + actual: CapturedEvent[] | CapturedEvent[], entities: EntitiesMap ): void { ignoreExtraEvents = ignoreExtraEvents ?? false; diff --git a/test/tools/unified-spec-runner/operations.ts b/test/tools/unified-spec-runner/operations.ts index 0c3e155cfac..d35d8363a00 100644 --- a/test/tools/unified-spec-runner/operations.ts +++ b/test/tools/unified-spec-runner/operations.ts @@ -96,9 +96,9 @@ operations.set('assertIndexNotExists', async ({ operation, client }) => { operations.set('assertDifferentLsidOnLastTwoCommands', async ({ entities, operation }) => { const client = entities.getEntity('client', operation.arguments!.client); - expect(client.observedCommandEvents.includes('commandStarted')).to.be.true; + expect(client.observedEvents.includes('commandStarted')).to.be.true; - const startedEvents = client.commandEvents.filter( + const startedEvents = client.capturedEvents.filter( ev => ev instanceof CommandStartedEvent ) as CommandStartedEvent[]; @@ -115,9 +115,9 @@ operations.set('assertDifferentLsidOnLastTwoCommands', async ({ entities, operat operations.set('assertSameLsidOnLastTwoCommands', async ({ entities, operation }) => { const client = entities.getEntity('client', operation.arguments!.client); - expect(client.observedCommandEvents.includes('commandStarted')).to.be.true; + expect(client.observedEvents.includes('commandStarted')).to.be.true; - const startedEvents = client.commandEvents.filter( + const startedEvents = client.capturedEvents.filter( ev => ev instanceof CommandStartedEvent ) as CommandStartedEvent[]; diff --git a/test/tools/unified-spec-runner/runner.ts b/test/tools/unified-spec-runner/runner.ts index 31990d99d71..fb138dd0e27 100644 --- a/test/tools/unified-spec-runner/runner.ts +++ b/test/tools/unified-spec-runner/runner.ts @@ -8,7 +8,7 @@ import { ReadPreference } from '../../../src/read_preference'; import { TopologyType } from '../../../src/sdam/common'; import { ns } from '../../../src/utils'; import { ejson } from '../utils'; -import { CmapEvent, CommandEvent, EntitiesMap } from './entities'; +import { CapturedEvent, EntitiesMap } from './entities'; import { matchesEvents } from './match'; import { executeOperationAndCheck } from './operations'; import * as uni from './schema'; @@ -198,23 +198,17 @@ async function runUnifiedTest( } } - const clientCommandEvents = new Map(); - const clientCmapEvents = new Map(); + const clientEvents = new Map(); // If any event listeners were enabled on any client entities, // the test runner MUST now disable those event listeners. for (const [id, client] of entities.mapOf('client')) { - clientCommandEvents.set(id, client.stopCapturingCommandEvents()); - clientCmapEvents.set(id, client.stopCapturingCmapEvents()); + clientEvents.set(id, client.stopCapturingEvents()); } if (test.expectEvents) { for (const expectedEventsForClient of test.expectEvents) { const clientId = expectedEventsForClient.client; - const eventType = expectedEventsForClient.eventType; - // If no event type is provided it defaults to 'command', so just - // check for 'cmap' here for now. - const actualEvents = - eventType === 'cmap' ? clientCmapEvents.get(clientId) : clientCommandEvents.get(clientId); + const actualEvents = clientEvents.get(clientId); expect(actualEvents, `No client entity found with id ${clientId}`).to.exist; matchesEvents(expectedEventsForClient, actualEvents!, entities);