Skip to content

Commit d6678eb

Browse files
committed
test: add unresumable error test
1 parent 00baff4 commit d6678eb

File tree

1 file changed

+76
-4
lines changed

1 file changed

+76
-4
lines changed

test/integration/change-streams/change_stream.test.ts

+76-4
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ import { promisify } from 'util';
1010
import {
1111
AbstractCursor,
1212
ChangeStream,
13-
ChangeStreamCursor,
14-
ChangeStreamDocument,
15-
ChangeStreamInsertDocument,
1613
ChangeStreamOptions,
1714
Collection,
1815
CommandStartedEvent,
@@ -2151,8 +2148,50 @@ describe('ChangeStream resumability', function () {
21512148
* unhappy path - it errors out
21522149
* resumable error - continues but also throws the error out
21532150
*/
2151+
for (const { error, code, message } of resumableErrorCodes) {
2152+
it(
2153+
`resumes on error code ${code} (${error})`,
2154+
{ requires: { topology: '!single', mongodb: '<4.2' } },
2155+
async function () {
2156+
changeStream = collection.watch([]);
2157+
await initIteratorMode(changeStream);
2158+
2159+
// on 3.6 servers, no postBatchResumeToken is sent back in the initial aggregate response.
2160+
// This means that a resume token isn't cached until the first change has been iterated.
2161+
// In order to test the resume, we need to ensure that at least one document has
2162+
// been iterated so we have a resume token to resume on.
2163+
2164+
// insert the doc
2165+
await collection.insertOne({ city: 'New York City' });
2166+
2167+
// fail the call
2168+
const mock = sinon
2169+
.stub(changeStream.cursor, '_getMore')
2170+
.callsFake((_batchSize, callback) => {
2171+
mock.restore();
2172+
const error = new MongoServerError({ message });
2173+
error.code = code;
2174+
callback(error);
2175+
});
2176+
2177+
// insert another doc
2178+
await collection.insertOne({ city: 'New York City' });
2179+
2180+
let total_changes = 0;
2181+
for await (const change of changeStream) {
2182+
total_changes++;
2183+
if (total_changes === 2) {
2184+
changeStream.close();
2185+
}
2186+
}
2187+
2188+
expect(aggregateEvents).to.have.lengthOf(2);
2189+
}
2190+
);
2191+
}
2192+
21542193
// happy path
2155-
it('happy path', async function () {
2194+
it('happy path', { requires: { topology: '!single', mongodb: '>=4.2' } }, async function () {
21562195
changeStream = collection.watch([]);
21572196
await initIteratorMode(changeStream);
21582197

@@ -2166,10 +2205,43 @@ describe('ChangeStream resumability', function () {
21662205

21672206
count++;
21682207
if (count === 3) {
2208+
expect(docs.length).to.equal(count);
21692209
changeStream.close();
21702210
}
21712211
}
21722212
});
2213+
2214+
// unhappy path
2215+
it(
2216+
'unhappy path',
2217+
{ requires: { topology: '!single', mongodb: '>=4.2' } },
2218+
async function () {
2219+
changeStream = collection.watch([]);
2220+
await initIteratorMode(changeStream);
2221+
2222+
const unresumableErrorCode = 1000;
2223+
await client.db('admin').command({
2224+
configureFailPoint: is4_2Server(this.configuration.version)
2225+
? 'failCommand'
2226+
: 'failGetMoreAfterCursorCheckout',
2227+
mode: { times: 1 },
2228+
data: {
2229+
failCommands: ['getMore'],
2230+
errorCode: unresumableErrorCode
2231+
}
2232+
} as FailPoint);
2233+
2234+
await collection.insertOne({ city: 'New York City' });
2235+
2236+
try {
2237+
for await (const change of changeStream) {
2238+
// should not run
2239+
}
2240+
} catch (error) {
2241+
expect(error).to.be.instanceOf(MongoServerError);
2242+
}
2243+
}
2244+
);
21732245
});
21742246
});
21752247

0 commit comments

Comments
 (0)