Skip to content

Commit 5c8a670

Browse files
minor cleanup
1 parent 728d8aa commit 5c8a670

File tree

1 file changed

+86
-73
lines changed

1 file changed

+86
-73
lines changed

test/unit/assorted/server_discovery_and_monitoring.spec.test.ts

Lines changed: 86 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ function assertMonitoringOutcome(outcome: any): asserts outcome is MonitoringOut
191191
expect(outcome).to.have.property('events').that.is.an('array');
192192
}
193193

194-
describe.only('Server Discovery and Monitoring (spec)', function () {
194+
describe('Server Discovery and Monitoring (spec)', function () {
195195
let serverConnect: sinon.SinonStub;
196196

197197
before(() => {
@@ -314,87 +314,100 @@ const SDAM_EVENTS = [
314314
...HEARTBEAT_EVENTS
315315
];
316316

317-
function checkoutStubImpl(appError: ApplicationError) {
318-
return async function () {
319-
const connectionPoolGeneration = this.generation;
320-
const fakeConnection = {
321-
generation:
322-
typeof appError.generation === 'number' ? appError.generation : connectionPoolGeneration,
323-
async command(_, __, ___) {
324-
switch (appError.type) {
325-
case 'network':
326-
throw new MongoNetworkError('test generated');
327-
case 'timeout':
328-
throw new MongoNetworkTimeoutError('xxx timed out');
329-
case 'command':
330-
throw new MongoServerError(appError.response);
331-
default:
332-
throw new Error(
333-
// @ts-expect-error `.type` is never, but we want to access it in this unreachable code to
334-
// throw an error message.
335-
`SDAM unit test runner error: unexpected appError.type field: ${appError.type}`
336-
);
337-
}
338-
}
339-
};
340-
return fakeConnection as any as Connection;
341-
};
342-
}
343-
344-
function stubConnectionEstablishment(appError: ApplicationError) {
345-
const stubs = [];
346-
if (appError.when === 'afterHandshakeCompletes') {
347-
const checkOutStub = sinon
348-
.stub(ConnectionPool.prototype, 'checkOut')
349-
.callsFake(checkoutStubImpl(appError));
350-
stubs.push(checkOutStub);
351-
return stubs;
317+
function makeConnectionsError(appError: ApplicationError): sinon.SinonStub[] {
318+
switch (appError.when) {
319+
case 'beforeHandshakeCompletes':
320+
return stubBeforeHandshake(appError);
321+
case 'afterHandshakeCompletes':
322+
return [
323+
sinon.stub(ConnectionPool.prototype, 'checkOut').callsFake(checkoutStubImpl(appError))
324+
];
325+
default:
326+
throw new Error('unexpected value for `.when`: ' + appError.when);
352327
}
353328

354-
// eslint-disable-next-line @typescript-eslint/no-require-imports
355-
const net: typeof import('net') = require('net');
356-
357-
const netStub = sinon.stub(net, 'createConnection');
329+
// if `appError.when === 'beforeHandshake`:
330+
// "Simulate this mock error as if it occurred during a new connection's handshake for an application operation."
331+
// This function mocks the basic `createConnection` API to return an unconnected socket, and uses a special connection
332+
// subclass that always throws when `command()` is executed.
333+
function stubBeforeHandshake(appError: ApplicationError) {
334+
const stubs = [];
335+
// eslint-disable-next-line @typescript-eslint/no-require-imports
336+
const net: typeof import('net') = require('net');
337+
338+
const netStub = sinon.stub(net, 'createConnection');
339+
340+
netStub.callsFake(function createConnectionStub() {
341+
const socket = new net.Socket();
342+
process.nextTick(() => socket.emit('connect'));
343+
return socket;
344+
});
358345

359-
netStub.callsFake(function createConnectionStub() {
360-
const socket = new net.Socket();
361-
process.nextTick(() => socket.emit('connect'));
362-
return socket;
363-
});
346+
stubs.push(netStub);
347+
348+
class StubbedConnection extends Connection {
349+
override command(
350+
_ns: unknown,
351+
command: Document,
352+
_options?: unknown,
353+
_responseType?: unknown
354+
): Promise<any> {
355+
if (command.hello || command[LEGACY_HELLO_COMMAND]) {
356+
throw new MongoNetworkError(`error executing command`, { beforeHandshake: true });
357+
}
364358

365-
stubs.push(netStub);
366-
367-
class StubbedConnection extends Connection {
368-
override command(
369-
_ns: unknown,
370-
command: Document,
371-
_options?: unknown,
372-
_responseType?: unknown
373-
): Promise<any> {
374-
if (command.hello || command[LEGACY_HELLO_COMMAND]) {
375-
throw new MongoNetworkError(`error executing command`, { beforeHandshake: true });
359+
throw new Error('unexpected command: ', command);
376360
}
377-
378-
throw new Error('unexpected command: ', command);
379361
}
380-
}
381362

382-
// eslint-disable-next-line @typescript-eslint/no-require-imports
383-
const connectionUtils: typeof import('../../../src/cmap/connect') = require('../../../src/cmap/connect');
363+
// eslint-disable-next-line @typescript-eslint/no-require-imports
364+
const connectionUtils: typeof import('../../../src/cmap/connect') = require('../../../src/cmap/connect');
365+
366+
const wrapped = sinon
367+
.stub(connectionUtils, 'connect')
368+
.callsFake(async function connect(options) {
369+
const generation =
370+
typeof appError.generation === 'number' ? appError.generation : options.generation;
371+
return wrapped.wrappedMethod({
372+
...options,
373+
generation,
374+
connectionType: StubbedConnection
375+
});
376+
});
384377

385-
const wrapped = sinon.stub(connectionUtils, 'connect').callsFake(async function connect(options) {
386-
const generation =
387-
typeof appError.generation === 'number' ? appError.generation : options.generation;
388-
return wrapped.wrappedMethod({
389-
...options,
390-
generation,
391-
connectionType: StubbedConnection
392-
});
393-
});
378+
stubs.push(wrapped);
394379

395-
stubs.push(wrapped);
380+
return stubs;
381+
}
396382

397-
return stubs;
383+
// "Simulate this mock error as if it occurred on an established connection for an application operation (i.e. after the connection pool check out succeeds)."
384+
// This one is simple - return a stubbed connection that always throws. No need to worry about the internals of `connect()`.
385+
function checkoutStubImpl(appError: ApplicationError) {
386+
return async function () {
387+
const connectionPoolGeneration = this.generation;
388+
const fakeConnection = {
389+
generation:
390+
typeof appError.generation === 'number' ? appError.generation : connectionPoolGeneration,
391+
async command(_, __, ___) {
392+
switch (appError.type) {
393+
case 'network':
394+
throw new MongoNetworkError('test generated');
395+
case 'timeout':
396+
throw new MongoNetworkTimeoutError('xxx timed out');
397+
case 'command':
398+
throw new MongoServerError(appError.response);
399+
default:
400+
throw new Error(
401+
// @ts-expect-error `.type` is never, but we want to access it in this unreachable code to
402+
// throw a helpful error message.
403+
`SDAM unit test runner error: unexpected appError.type field: ${appError.type}`
404+
);
405+
}
406+
}
407+
};
408+
return fakeConnection as any as Connection;
409+
};
410+
}
398411
}
399412

400413
async function executeSDAMTest(testData: SDAMTest) {
@@ -424,7 +437,7 @@ async function executeSDAMTest(testData: SDAMTest) {
424437
for (const appError of phase.applicationErrors) {
425438
// Stub will return appError to SDAM machinery
426439

427-
const stubs = stubConnectionEstablishment(appError);
440+
const stubs = makeConnectionsError(appError);
428441

429442
const server = client.topology.s.servers.get(appError.address);
430443

0 commit comments

Comments
 (0)