diff --git a/test/functional/cursor_tests.js b/test/functional/cursor_tests.js index abfb937c0c..e1fef49b45 100644 --- a/test/functional/cursor_tests.js +++ b/test/functional/cursor_tests.js @@ -6,7 +6,7 @@ var expect = require('chai').expect; describe('Cursor', function() { before(function() { - return setupDatabase(this.configuration); + return setupDatabase(this.configuration, ['cursorkilltest1']); }); /** @@ -4163,6 +4163,95 @@ describe('Cursor', function() { } }); + it('Should properly kill a cursor', { + metadata: { + requires: { + topology: ['single', 'replicaset', 'sharded', 'ssl', 'heap', 'wiredtiger'], + mongodb: '>=3.2.0' + } + }, + + // The actual test we wish to run + test: function() { + // Load up the documents + const docs = []; + for (let i = 0; i < 1000; i += 1) { + docs.push({ + a: i + }); + } + + const configuration = this.configuration; + const client = configuration.newClient(configuration.writeConcernMax(), { poolSize: 1 }); + let cleanup = () => {}; + let caughtError = undefined; + + return ( + client + // Connect + .connect() + .then(function(client) { + cleanup = () => client.close(); + const db = client.db(configuration.db); + const collection = db.collection('cursorkilltest1'); + + // Insert 1000 documents + return collection.insert(docs).then(() => { + // Generate cursor for find operation + const cursor = collection.find({}); + + // Iterate cursor past first element + return cursor + .next() + .then(() => cursor.next()) + .then(() => { + // Confirm that cursorId is non-zero + let id = cursor.cursorState.cursorId; + if (typeof id !== 'number') { + expect(id) + .to.be.an('object') + .and.to.haveOwnProperty('_bsontype', 'Long'); + id = id.toNumber(); + } + + expect(id).to.not.equal(0); + + // Kill cursor + return new Promise((resolve, reject) => { + cursor.kill((err, response) => { + if (err) { + return reject(err); + } + return resolve(response); + }); + }).then(response => { + // Ensure correct response from cursor kill + expect(response) + .to.be.an('object') + .and.to.deep.include({ + ok: 1, + cursorsAlive: [], + cursorsNotFound: [], + cursorsUnknown: [], + cursorsKilled: [id] + }); + }); + }); + }); + }) + + // Clean up. Make sure that even in case of error, we still always clean up connection + .catch(e => (caughtError = e)) + .then(cleanup) + .then(() => { + if (caughtError) { + throw caughtError; + } + }) + ); + } + }); + // NOTE: This is skipped because I don't think its correct or adds value. The expected error // is not an error with hasNext (from server), but rather a local TypeError which should // be caught anyway. The only solution here would be to wrap the entire top level call