Skip to content

Commit ce50731

Browse files
committed
add new tests
1 parent 1a4feab commit ce50731

File tree

1 file changed

+208
-1
lines changed

1 file changed

+208
-1
lines changed

test/integration/client-side-operations-timeout/node_csot.test.ts

Lines changed: 208 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ import * as sinon from 'sinon';
55
import {
66
type ClientSession,
77
type Collection,
8+
type CommandStartedEvent,
9+
CountOperation,
810
type Db,
911
type FindCursor,
1012
LEGACY_HELLO_COMMAND,
11-
type MongoClient,
13+
MongoClient,
14+
MongoError,
1215
MongoOperationTimeoutError
1316
} from '../../mongodb';
1417

@@ -166,4 +169,208 @@ describe('CSOT driver tests', () => {
166169
});
167170
});
168171
});
172+
173+
describe('retryable reads', () => {
174+
let configClient: MongoClient;
175+
let client: MongoClient;
176+
const FAIL_COMMAND = {
177+
configureFailPoint: 'failCommand',
178+
mode: 'alwaysOn',
179+
data: {
180+
failCommands: ['count'],
181+
errorCode: 10107,
182+
closeConnection: false
183+
}
184+
};
185+
186+
const DISABLE_FAIL_COMMAND = {
187+
configureFailPoint: 'failCommand',
188+
mode: 'off',
189+
data: {
190+
failCommands: ['count'],
191+
errorCode: 10107,
192+
closeConnection: false
193+
}
194+
};
195+
196+
beforeEach(async function () {
197+
configClient = new MongoClient(this.configuration.url());
198+
await configClient.db().admin().command(FAIL_COMMAND);
199+
});
200+
201+
afterEach(async function () {
202+
await configClient.db().admin().command(DISABLE_FAIL_COMMAND);
203+
await configClient.close();
204+
205+
await client.close();
206+
});
207+
208+
context('when timeoutMS is undefined and retryable operation fails', () => {
209+
const commandStartedEvents = [];
210+
let maybeErr: Error | null;
211+
212+
beforeEach(async function () {
213+
client = this.configuration.newClient(this.configuration.url(), {
214+
timeoutMS: undefined,
215+
monitorCommands: true
216+
});
217+
218+
client.on('commandStarted', (ev: CommandStartedEvent) => {
219+
if (Object.hasOwn(ev.command, 'count')) commandStartedEvents.push(ev.command);
220+
});
221+
maybeErr = await client
222+
.db('test')
223+
.collection('test')
224+
.count()
225+
.then(
226+
() => null,
227+
e => e
228+
);
229+
});
230+
231+
it('makes exactly two total attempts and throws an error', async function () {
232+
expect(maybeErr).to.be.instanceof(MongoError);
233+
expect(commandStartedEvents).to.have.length(2);
234+
});
235+
});
236+
237+
context('when timeoutMS is a number and operation fails', () => {
238+
const commandStartedEvents = [];
239+
let start: number, end: number;
240+
let maybeErr: Error | null;
241+
242+
beforeEach(async function () {
243+
client = this.configuration.newClient(this.configuration.url(), {
244+
timeoutMS: 50,
245+
monitorCommands: true
246+
});
247+
248+
client.on('commandStarted', (ev: CommandStartedEvent) => {
249+
if (Object.hasOwn(ev.command, 'count')) commandStartedEvents.push(ev.command);
250+
});
251+
252+
start = performance.now();
253+
maybeErr = await client
254+
.db('test')
255+
.collection('test')
256+
.count()
257+
.then(
258+
() => null,
259+
e => e
260+
);
261+
end = performance.now();
262+
});
263+
264+
it('throws MongoOperationTimeoutError after timeoutMS', async function () {
265+
expect(end - start).to.be.greaterThanOrEqual(client.options.timeoutMS);
266+
expect(maybeErr).to.be.instanceof(MongoOperationTimeoutError);
267+
});
268+
269+
it('attempts the command more than twice', async function () {
270+
expect(commandStartedEvents).to.have.length.greaterThan(2);
271+
});
272+
});
273+
});
274+
275+
describe('retryable writes', () => {
276+
let configClient: MongoClient;
277+
let client: MongoClient;
278+
const FAIL_COMMAND = {
279+
configureFailPoint: 'failCommand',
280+
mode: 'alwaysOn',
281+
data: {
282+
failCommands: ['insert'],
283+
errorCode: 10107,
284+
closeConnection: false
285+
}
286+
};
287+
288+
const DISABLE_FAIL_COMMAND = {
289+
configureFailPoint: 'failCommand',
290+
mode: 'off',
291+
data: {
292+
failCommands: ['insert'],
293+
errorCode: 10107,
294+
closeConnection: false
295+
}
296+
};
297+
298+
beforeEach(async function () {
299+
configClient = new MongoClient(this.configuration.url());
300+
await configClient.db().admin().command(FAIL_COMMAND);
301+
});
302+
303+
afterEach(async function () {
304+
await configClient.db().admin().command(DISABLE_FAIL_COMMAND);
305+
await configClient.close();
306+
307+
await client.close();
308+
});
309+
310+
context('when timeoutMS is undefined and retryable operation fails', () => {
311+
const commandStartedEvents = [];
312+
let maybeErr: Error | null;
313+
314+
beforeEach(async function () {
315+
client = this.configuration.newClient(this.configuration.url(), {
316+
timeoutMS: undefined,
317+
monitorCommands: true
318+
});
319+
320+
client.on('commandStarted', (ev: CommandStartedEvent) => {
321+
if (Object.hasOwn(ev.command, 'insert')) commandStartedEvents.push(ev.command);
322+
});
323+
maybeErr = await client
324+
.db('test')
325+
.collection('test')
326+
.insertOne({ a: 10 })
327+
.then(
328+
() => null,
329+
e => e
330+
);
331+
});
332+
333+
it('makes exactly two total attempts and throws an error', async function () {
334+
expect(maybeErr).to.be.instanceof(MongoError);
335+
expect(commandStartedEvents).to.have.length(2);
336+
});
337+
});
338+
339+
context('when timeoutMS is a number and operation fails', () => {
340+
const commandStartedEvents = [];
341+
let start: number, end: number;
342+
let maybeErr: Error | null;
343+
344+
beforeEach(async function () {
345+
client = this.configuration.newClient(this.configuration.url(), {
346+
timeoutMS: 50,
347+
monitorCommands: true
348+
});
349+
350+
client.on('commandStarted', (ev: CommandStartedEvent) => {
351+
if (Object.hasOwn(ev.command, 'insert')) commandStartedEvents.push(ev.command);
352+
});
353+
354+
start = performance.now();
355+
maybeErr = await client
356+
.db('test')
357+
.collection('test')
358+
.insertOne({ a: 10 })
359+
.then(
360+
() => null,
361+
e => e
362+
);
363+
end = performance.now();
364+
});
365+
366+
it('throws MongoOperationTimeoutError after timeoutMS', async function () {
367+
expect(end - start).to.be.greaterThanOrEqual(client.options.timeoutMS);
368+
expect(maybeErr).to.be.instanceof(MongoOperationTimeoutError);
369+
});
370+
371+
it('attempts the command more than twice', async function () {
372+
expect(commandStartedEvents).to.have.length.greaterThan(2);
373+
});
374+
});
375+
});
169376
});

0 commit comments

Comments
 (0)