From 2b16d0f944f30e19fbca6ee790d9b679ef881338 Mon Sep 17 00:00:00 2001 From: Pavel Safronov Date: Tue, 21 Oct 2025 11:23:19 -0700 Subject: [PATCH 1/5] migrate to src and promises --- test/integration/crud/misc_cursors.test.js | 3352 ++++++++------------ 1 file changed, 1278 insertions(+), 2074 deletions(-) diff --git a/test/integration/crud/misc_cursors.test.js b/test/integration/crud/misc_cursors.test.js index 3e3ef1a2f8..3408fb2db5 100644 --- a/test/integration/crud/misc_cursors.test.js +++ b/test/integration/crud/misc_cursors.test.js @@ -10,9 +10,10 @@ const sinon = require('sinon'); const { Writable } = require('stream'); const { once, on } = require('events'); const { setTimeout } = require('timers'); -const { ReadPreference } = require('../../mongodb'); -const { ServerType, MongoClientClosedError } = require('../../mongodb'); -const { formatSort } = require('../../mongodb'); +const { ReadPreference } = require('../../../src/read_preference'); +const { ServerType } = require('../../../src/sdam/common'); +const { MongoClientClosedError } = require('../../../src/error'); +const { formatSort } = require('../../../src/sort'); describe('Cursor', function () { before(function () { @@ -23,6 +24,9 @@ describe('Cursor', function () { ]); }); + /** + * @type {import('../../../src/mongo_client').MongoClient} + */ let client; beforeEach(async function () { @@ -64,34 +68,21 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('close_on_next', (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('close_on_next'); - collection.insert( - [{ a: 1 }, { a: 1 }, { a: 1 }], - configuration.writeConcernMax(), - err => { - expect(err).to.not.exist; + await collection.insert([{ a: 1 }, { a: 1 }, { a: 1 }], configuration.writeConcernMax()); - var cursor = collection.find({}); - this.defer(() => cursor.close()); + var cursor = collection.find({}); + // this.defer(() => cursor.close()); - cursor.batchSize(2); - cursor.next(err => { - expect(err).to.not.exist; - done(); - }); - } - ); - }); - }); + cursor.batchSize(2); + await cursor.next(); + await cursor.close(); } }); @@ -102,31 +93,19 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('trigger_get_more', (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('trigger_get_more'); - collection.insert( - [{ a: 1 }, { a: 1 }, { a: 1 }], - configuration.writeConcernMax(), - err => { - expect(err).to.not.exist; - const cursor = collection.find({}).batchSize(2); - this.defer(() => cursor.close()); - cursor.toArray(err => { - expect(err).to.not.exist; - done(); - }); - } - ); - }); - }); + await collection.insert([{ a: 1 }, { a: 1 }, { a: 1 }], configuration.writeConcernMax()); + + const cursor = collection.find({}).batchSize(2); + + await cursor.toArray(); + await cursor.close(); } }); @@ -137,27 +116,18 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('test_explain', (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('test_explain'); - collection.insert({ a: 1 }, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + await collection.insert({ a: 1 }, configuration.writeConcernMax()); - collection.find({ a: 1 }).explain((err, explanation) => { - expect(err).to.not.exist; - expect(explanation).to.exist; - done(); - }); - }); - }); - }); + const explanation = await collection.find({ a: 1 }).explain(); + + expect(explanation).to.exist; } }); @@ -168,79 +138,48 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('test_count', (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('test_count'); + await collection.find().count(); - collection.find().count(err => { - expect(err).to.not.exist; + async function insert() { + for (var i = 0; i < 10; i++) { + await collection.insert({ x: i }, configuration.writeConcernMax()); + } + } - function insert(callback) { - var total = 10; + async function finished() { + let count = await collection.find().count(); + test.equal(10, count); + test.ok(count.constructor === Number); - for (var i = 0; i < 10; i++) { - collection.insert({ x: i }, configuration.writeConcernMax(), e => { - expect(e).to.not.exist; - total = total - 1; - if (total === 0) callback(); - }); - } - } + count = await collection.find({}, { limit: 5 }).count(); + test.equal(5, count); - function finished() { - collection.find().count((err, count) => { - expect(err).to.not.exist; - test.equal(10, count); - test.ok(count.constructor === Number); - - collection.find({}, { limit: 5 }).count((err, count) => { - expect(err).to.not.exist; - test.equal(5, count); - - collection.find({}, { skip: 5 }).count((err, count) => { - expect(err).to.not.exist; - test.equal(5, count); - - db.collection('acollectionthatdoesn').count((err, count) => { - expect(err).to.not.exist; - test.equal(0, count); - - var cursor = collection.find(); - cursor.count((err, count) => { - expect(err).to.not.exist; - test.equal(10, count); - - cursor.forEach( - () => {}, - err => { - expect(err).to.not.exist; - cursor.count((err, count2) => { - expect(err).to.not.exist; - expect(count2).to.equal(10); - expect(count2).to.equal(count); - done(); - }); - } - ); - }); - }); - }); - }); - }); - } + count = await collection.find({}, { skip: 5 }).count(); + test.equal(5, count); - insert(function () { - finished(); - }); - }); - }); - }); + count = await db.collection('acollectionthatdoesn').count(); + + test.equal(0, count); + + var cursor = collection.find(); + count = await cursor.count(); + test.equal(10, count); + + await cursor.forEach(() => { }); + + const count2 = await cursor.count(); + expect(count2).to.equal(10); + expect(count2).to.equal(count); + } + + await insert(); + await finished(); } }); @@ -271,79 +210,47 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('test_count.ext', (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('test_count.ext'); - collection.find().count(err => { - expect(err).to.not.exist; + await collection.find().count(); - function insert(callback) { - var total = 10; + async function insert() { + for (var i = 0; i < 10; i++) { + await collection.insert({ x: i }, configuration.writeConcernMax()); + } + } - for (var i = 0; i < 10; i++) { - collection.insert({ x: i }, configuration.writeConcernMax(), e => { - expect(e).to.not.exist; - total = total - 1; - if (total === 0) callback(); - }); - } - } + async function finished() { + let count = await collection.find().count(); + test.equal(10, count); + test.ok(count.constructor === Number); - function finished() { - collection.find().count((err, count) => { - expect(err).to.not.exist; - test.equal(10, count); - test.ok(count.constructor === Number); - - collection.find({}, { limit: 5 }).count((err, count) => { - expect(err).to.not.exist; - test.equal(5, count); - - collection.find({}, { skip: 5 }).count((err, count) => { - expect(err).to.not.exist; - test.equal(5, count); - - db.collection('acollectionthatdoesn').count((err, count) => { - expect(err).to.not.exist; - test.equal(0, count); - - var cursor = collection.find(); - cursor.count((err, count) => { - expect(err).to.not.exist; - test.equal(10, count); - - cursor.forEach( - () => {}, - err => { - expect(err).to.not.exist; - cursor.count((err, count2) => { - expect(err).to.not.exist; - expect(count2).to.equal(10); - expect(count2).to.equal(count); - done(); - }); - } - ); - }); - }); - }); - }); - }); - } + count = await collection.find({}, { limit: 5 }).count(); + test.equal(5, count); - insert(function () { - finished(); - }); - }); - }); - }); + count = await collection.find({}, { skip: 5 }).count(); + test.equal(5, count); + + count = await db.collection('acollectionthatdoesn').count(); + test.equal(0, count); + + var cursor = collection.find(); + count = await cursor.count(); + test.equal(10, count); + + await cursor.forEach(() => { }); + + const count2 = await cursor.count(); + expect(count2).to.equal(10); + expect(count2).to.equal(count); + } + await insert(); + await finished(); } }); @@ -354,42 +261,29 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('test_each', (err, collection) => { - expect(err).to.not.exist; - function insert(callback) { - var total = 10; - - for (var i = 0; i < 10; i++) { - collection.insert({ x: i }, configuration.writeConcernMax(), e => { - expect(e).to.not.exist; - total = total - 1; - if (total === 0) callback(); - }); - } - } + const db = client.db(configuration.db); + const collection = await db.createCollection('test_each'); + async function insert() { + for (var i = 0; i < 10; i++) { + await collection.insert({ x: i }, configuration.writeConcernMax()); + } + } - function finished() { - const cursor = collection.find(); + function finished() { + const cursor = collection.find(); - test.throws(function () { - cursor.forEach(); - }); + test.throws(function () { + cursor.forEach(); + }); + } - done(); - } + await insert(); - insert(function () { - finished(); - }); - }); - }); + finished(); } }); @@ -400,44 +294,25 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('test_cursor_limit', (err, collection) => { - function insert(callback) { - var total = 10; - - for (var i = 0; i < 10; i++) { - collection.insert({ x: i }, configuration.writeConcernMax(), e => { - expect(e).to.not.exist; - total = total - 1; - if (total === 0) callback(); - }); - } - } + const db = client.db(configuration.db); + const collection = await db.createCollection('test_cursor_limit'); - function finished() { - collection - .find() - .limit(5) - .toArray((err, items) => { - test.equal(5, items.length); - - // Let's close the db - expect(err).to.not.exist; - done(); - }); - } + async function insert() { + for (var i = 0; i < 10; i++) { + await collection.insert({ x: i }, configuration.writeConcernMax()); + } + } - insert(function () { - finished(); - }); - }); - }); + async function finished() { + const items = await collection.find().limit(5).toArray(); + test.equal(5, items.length); + } + await insert(); + await finished(); } }); @@ -448,45 +323,26 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('test_cursor_negative_one_limit', (err, collection) => { - expect(err).to.not.exist; - function insert(callback) { - var total = 10; - - for (var i = 0; i < 10; i++) { - collection.insert({ x: i }, configuration.writeConcernMax(), e => { - expect(e).to.not.exist; - total = total - 1; - if (total === 0) callback(); - }); - } - } + const db = client.db(configuration.db); + const collection = await db.createCollection('test_cursor_negative_one_limit'); - function finished() { - collection - .find() - .limit(-1) - .toArray((err, items) => { - expect(err).to.not.exist; - test.equal(1, items.length); - - // Let's close the db - done(); - }); - } + async function insert() { + for (var i = 0; i < 10; i++) { + await collection.insert({ x: i }, configuration.writeConcernMax()); + } + } - insert(function () { - finished(); - }); - }); - }); + async function finished() { + const items = await collection.find().limit(-1).toArray(); + test.equal(1, items.length); + } + + await insert(); + await finished(); } }); @@ -497,45 +353,25 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('test_cursor_any_negative_limit', (err, collection) => { - expect(err).to.not.exist; - function insert(callback) { - var total = 10; - - for (var i = 0; i < 10; i++) { - collection.insert({ x: i }, configuration.writeConcernMax(), e => { - expect(e).to.not.exist; - total = total - 1; - if (total === 0) callback(); - }); - } - } + const db = client.db(configuration.db); + const collection = await db.createCollection('test_cursor_any_negative_limit'); - function finished() { - collection - .find() - .limit(-5) - .toArray((err, items) => { - expect(err).to.not.exist; - test.equal(5, items.length); - - // Let's close the db - done(); - }); - } + async function insert() { + for (var i = 0; i < 10; i++) { + await collection.insert({ x: i }, configuration.writeConcernMax()); + } + } - insert(function () { - finished(); - }); - }); - }); + async function finished() { + const items = await collection.find().limit(-5).toArray(); + test.equal(5, items.length); + } + await insert(); + await finished(); } }); @@ -546,31 +382,25 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('test_limit_exceptions_2', (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('test_limit_exceptions_2'); - collection.insert({ a: 1 }, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; - const cursor = collection.find(); - this.defer(() => cursor.close()); + await collection.insert({ a: 1 }, configuration.writeConcernMax()); - try { - cursor.limit('not-an-integer'); - } catch (err) { - test.equal('Operation "limit" requires an integer', err.message); - } + const cursor = collection.find(); + // this.defer(() => cursor.close()); - done(); - }); - }); - }); + try { + cursor.limit('not-an-integer'); + } catch (err) { + test.equal('Operation "limit" requires an integer', err.message); + } + + await cursor.clone(); } }); @@ -581,33 +411,22 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); - - const db = client.db(configuration.db); - db.createCollection('test_limit_exceptions', (err, collection) => { - expect(err).to.not.exist; + await client.connect(); - collection.insert({ a: 1 }, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('test_limit_exceptions'); - const cursor = collection.find(); - this.defer(() => cursor.close()); + await collection.insert({ a: 1 }, configuration.writeConcernMax()); - cursor.next(err => { - expect(err).to.not.exist; - expect(() => { - cursor.limit(1); - }).to.throw(/Cursor is already initialized/); + const cursor = collection.find(); + // this.defer(() => cursor.close()); - done(); - }); - }); - }); - }); + await cursor.next(); + expect(() => { + cursor.limit(1); + }).to.throw(/Cursor is already initialized/); } }); @@ -619,31 +438,20 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); - - const db = client.db(configuration.db); - db.createCollection('test_limit_exceptions_1', (err, collection) => { - expect(err).to.not.exist; + await client.connect(); - collection.insert({ a: 1 }, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('test_limit_exceptions_1'); - const cursor = collection.find(); - cursor.close(err => { - expect(err).to.not.exist; - expect(() => { - cursor.limit(1); - }).to.throw(/not extensible/); + await collection.insert({ a: 1 }, configuration.writeConcernMax()); - done(); - }); - }); - }); - }); + const cursor = collection.find(); + await cursor.close(); + expect(() => { + cursor.limit(1); + }).to.throw(/not extensible/); } }); @@ -654,66 +462,46 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('test_skip', (err, collection) => { - expect(err).to.not.exist; - - const insert = callback => { - var total = 10; - for (var i = 0; i < 10; i++) { - collection.insert({ x: i }, configuration.writeConcernMax(), e => { - expect(e).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('test_skip'); - total = total - 1; - if (total === 0) callback(); - }); - } - }; + const insert = async () => { + for (var i = 0; i < 10; i++) { + await collection.insert({ x: i }, configuration.writeConcernMax()); + } + }; - insert(() => { - const cursor = collection.find(); - this.defer(() => cursor.close()); + await insert(); + const cursor = collection.find(); + // this.defer(() => cursor.close()); - cursor.count((err, count) => { - expect(err).to.not.exist; - test.equal(10, count); - }); + let count = await cursor.count(); + test.equal(10, count); - const cursor2 = collection.find(); - this.defer(() => cursor2.close()); + const cursor2 = collection.find(); + // this.defer(() => cursor2.close()); - cursor2.toArray((err, items) => { - expect(err).to.not.exist; - test.equal(10, items.length); + const items = await cursor2.toArray(); + test.equal(10, items.length); - collection - .find() - .skip(2) - .toArray((err, items2) => { - expect(err).to.not.exist; - test.equal(8, items2.length); + const items2 = await collection.find().skip(2).toArray(); + test.equal(8, items2.length); - // Check that we have the same elements - var numberEqual = 0; - var sliced = items.slice(2, 10); + // Check that we have the same elements + var numberEqual = 0; + var sliced = items.slice(2, 10); - for (var i = 0; i < sliced.length; i++) { - if (sliced[i].x === items2[i].x) numberEqual = numberEqual + 1; - } + for (var i = 0; i < sliced.length; i++) { + if (sliced[i].x === items2[i].x) numberEqual = numberEqual + 1; + } - test.equal(8, numberEqual); - done(); - }); - }); - }); - }); - }); + test.equal(8, numberEqual); + await cursor.close(); + await cursor2.close(); } }); @@ -724,48 +512,36 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('test_skip_exceptions', (err, collection) => { - expect(err).to.not.exist; - collection.insert({ a: 1 }, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('test_skip_exceptions'); - try { - collection.find().skip('not-an-integer'); - } catch (err) { - test.equal('Operation "skip" requires an integer', err.message); - } + await collection.insert({ a: 1 }, configuration.writeConcernMax()); - const cursor = collection.find(); - cursor.next(err => { - expect(err).to.not.exist; + try { + collection.find().skip('not-an-integer'); + } catch (err) { + test.equal('Operation "skip" requires an integer', err.message); + } - // NOTE: who cares what you set when closed, if not initialized - // expect(() => { - // cursor.skip(1); - // }).to.throw(/not extensible/); + const cursor = collection.find(); + await cursor.next(); - const cursor2 = collection.find(); - cursor2.close(err => { - expect(err).to.not.exist; + // NOTE: who cares what you set when closed, if not initialized + // expect(() => { + // cursor.skip(1); + // }).to.throw(/not extensible/); - // NOTE: who cares what you set when closed, if not initialized - // expect(() => { - // cursor2.skip(1); - // }).to.throw(/not extensible/); + const cursor2 = collection.find(); + await cursor2.close(); - done(); - }); - }); - }); - }); - }); + // NOTE: who cares what you set when closed, if not initialized + // expect(() => { + // cursor2.skip(1); + // }).to.throw(/not extensible/); } }); @@ -776,56 +552,41 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); - - const db = client.db(configuration.db); - db.createCollection('test_batchSize_exceptions', (err, collection) => { - expect(err).to.not.exist; - collection.insert({ a: 1 }, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + await client.connect(); - let cursor = collection.find(); - try { - cursor.batchSize('not-an-integer'); - test.ok(false); - } catch (err) { - test.equal('Operation "batchSize" requires an integer', err.message); - } + const db = client.db(configuration.db); + const collection = await db.createCollection('test_batchSize_exceptions'); + await collection.insert({ a: 1 }, configuration.writeConcernMax()); + + let cursor = collection.find(); + try { + cursor.batchSize('not-an-integer'); + test.ok(false); + } catch (err) { + test.equal('Operation "batchSize" requires an integer', err.message); + } - cursor = collection.find(); - cursor.next(err => { - expect(err).to.not.exist; + cursor = collection.find(); + await cursor.next(); - cursor.next(err => { - expect(err).to.not.exist; + await cursor.next(); - // NOTE: who cares what you set when closed, if not initialized - // expect(() => { - // cursor.batchSize(1); - // }).to.throw(/not extensible/); + // NOTE: who cares what you set when closed, if not initialized + // expect(() => { + // cursor.batchSize(1); + // }).to.throw(/not extensible/); - const cursor2 = collection.find(); - cursor2.close(err => { - expect(err).to.not.exist; + const cursor2 = collection.find(); + await cursor2.close(); - // NOTE: who cares what you set when closed, if not initialized - // expect(() => { - // cursor2.batchSize(1); - // }).to.throw(/not extensible/); - - done(); - }); - }); - }); - }); - }); - }); - } - }); + // NOTE: who cares what you set when closed, if not initialized + // expect(() => { + // cursor2.batchSize(1); + // }).to.throw(/not extensible/); + } + }); it('shouldCorrectlyHandleBatchSize', { // Add a tag that our runner can trigger on @@ -834,67 +595,49 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('test_multiple_batch_size', (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('test_multiple_batch_size'); - //test with the last batch that is a multiple of batchSize - var records = 4; - var batchSize = 2; - var docs = []; - for (var i = 0; i < records; i++) { - docs.push({ a: i }); - } + //test with the last batch that is a multiple of batchSize + var records = 4; + var batchSize = 2; + var docs = []; + for (var i = 0; i < records; i++) { + docs.push({ a: i }); + } - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + await collection.insert(docs, configuration.writeConcernMax()); - const cursor = collection.find({}, { batchSize: batchSize }); - - //1st - cursor.next((err, items) => { - expect(err).to.not.exist; - test.equal(1, cursor.bufferedCount()); - test.ok(items != null); - - //2nd - cursor.next((err, items) => { - expect(err).to.not.exist; - test.equal(0, cursor.bufferedCount()); - test.ok(items != null); - - //3rd - cursor.next((err, items) => { - expect(err).to.not.exist; - test.equal(1, cursor.bufferedCount()); - test.ok(items != null); - - //4th - cursor.next((err, items) => { - expect(err).to.not.exist; - test.equal(0, cursor.bufferedCount()); - test.ok(items != null); - - //No more - cursor.next((err, items) => { - expect(err).to.not.exist; - test.ok(items == null); - test.ok(cursor.closed); - done(); - }); - }); - }); - }); - }); - }); - }); - }); + const cursor = collection.find({}, { batchSize: batchSize }); + + //1st + let items = await cursor.next(); + test.equal(1, cursor.bufferedCount()); + test.ok(items != null); + + //2nd + items = await cursor.next(); + test.equal(0, cursor.bufferedCount()); + test.ok(items != null); + + //3rd + items = await cursor.next(); + test.equal(1, cursor.bufferedCount()); + test.ok(items != null); + + //4th + items = await cursor.next(); + test.equal(0, cursor.bufferedCount()); + test.ok(items != null); + + //No more + items = await cursor.next(); + test.ok(items == null); + test.ok(cursor.closed); } }); @@ -905,61 +648,43 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('test_limit_greater_than_batch_size', (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('test_limit_greater_than_batch_size'); - var limit = 4; - var records = 10; - var batchSize = 3; - var docs = []; - for (var i = 0; i < records; i++) { - docs.push({ a: i }); - } + var limit = 4; + var records = 10; + var batchSize = 3; + var docs = []; + for (var i = 0; i < records; i++) { + docs.push({ a: i }); + } - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + await collection.insert(docs, configuration.writeConcernMax()); - var cursor = collection.find({}, { batchSize: batchSize, limit: limit }); - //1st - cursor.next(err => { - expect(err).to.not.exist; - test.equal(2, cursor.bufferedCount()); - - //2nd - cursor.next(err => { - expect(err).to.not.exist; - test.equal(1, cursor.bufferedCount()); - - //3rd - cursor.next(err => { - expect(err).to.not.exist; - test.equal(0, cursor.bufferedCount()); - - //4th - cursor.next(err => { - expect(err).to.not.exist; - - //No more - cursor.next((err, items) => { - expect(err).to.not.exist; - test.ok(items == null); - test.ok(cursor.closed); - done(); - }); - }); - }); - }); - }); - }); - }); - }); + var cursor = collection.find({}, { batchSize: batchSize, limit: limit }); + //1st + await cursor.next(); + test.equal(2, cursor.bufferedCount()); + + //2nd + await cursor.next(); + test.equal(1, cursor.bufferedCount()); + + //3rd + await cursor.next(); + test.equal(0, cursor.bufferedCount()); + + //4th + await cursor.next(); + + //No more + const items = await cursor.next(); + test.ok(items == null); + test.ok(cursor.closed); } }); @@ -970,50 +695,37 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('test_limit_less_than_batch_size', (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('test_limit_less_than_batch_size'); - var limit = 2; - var records = 10; - var batchSize = 4; - var docs = []; - for (var i = 0; i < records; i++) { - docs.push({ a: i }); - } + var limit = 2; + var records = 10; + var batchSize = 4; + var docs = []; + for (var i = 0; i < records; i++) { + docs.push({ a: i }); + } - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + await collection.insert(docs, configuration.writeConcernMax()); - var cursor = collection.find({}, { batchSize: batchSize, limit: limit }); - //1st - cursor.next(err => { - expect(err).to.not.exist; - test.equal(1, cursor.bufferedCount()); - - //2nd - cursor.next(err => { - expect(err).to.not.exist; - test.equal(0, cursor.bufferedCount()); - - //No more - cursor.next((err, items) => { - expect(err).to.not.exist; - test.ok(items == null); - test.ok(cursor.closed); - done(); - }); - }); - }); - }); - }); - }); + var cursor = collection.find({}, { batchSize: batchSize, limit: limit }); + //1st + await cursor.next(); + test.equal(1, cursor.bufferedCount()); + + //2nd + await cursor.next(); + test.equal(0, cursor.bufferedCount()); + + //No more + const items = await cursor.next(); + + test.ok(items == null); + test.ok(cursor.closed); } }); @@ -1024,57 +736,37 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); - - const db = client.db(configuration.db); - var collection = db.collection('shouldHandleSkipLimitChaining'); + await client.connect(); - function insert(callback) { - var total = 10; + const db = client.db(configuration.db); + var collection = db.collection('shouldHandleSkipLimitChaining'); - for (var i = 0; i < 10; i++) { - collection.insert({ x: i }, configuration.writeConcernMax(), e => { - expect(e).to.not.exist; - total = total - 1; - if (total === 0) callback(); - }); - } + async function insert() { + for (var i = 0; i < 10; i++) { + await collection.insert({ x: i }, configuration.writeConcernMax()); } + } - function finished() { - collection.find().toArray((err, items) => { - expect(err).to.not.exist; - test.equal(10, items.length); - - collection - .find() - .limit(5) - .skip(3) - .toArray(function (err, items2) { - expect(err).to.not.exist; - test.equal(5, items2.length); - - // Check that we have the same elements - var numberEqual = 0; - var sliced = items.slice(3, 8); - - for (var i = 0; i < sliced.length; i++) { - if (sliced[i].x === items2[i].x) numberEqual = numberEqual + 1; - } - test.equal(5, numberEqual); - done(); - }); - }); - } + async function finished() { + const items = await collection.find().toArray(); + test.equal(10, items.length); - insert(function () { - finished(); - }); - }); + const items2 = await collection.find().limit(5).skip(3).toArray(); + test.equal(5, items2.length); + + // Check that we have the same elements + var numberEqual = 0; + var sliced = items.slice(3, 8); + + for (var i = 0; i < sliced.length; i++) { + if (sliced[i].x === items2[i].x) numberEqual = numberEqual + 1; + } + test.equal(5, numberEqual); + } + await insert(); + await finished(); } }); @@ -1085,59 +777,37 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('test_limit_skip_chaining_inline', (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('test_limit_skip_chaining_inline'); - function insert(callback) { - var total = 10; + async function insert() { + for (var i = 0; i < 10; i++) { + await collection.insert({ x: i }, configuration.writeConcernMax()); + } + } - for (var i = 0; i < 10; i++) { - collection.insert({ x: i }, configuration.writeConcernMax(), e => { - expect(e).to.not.exist; - total = total - 1; - if (total === 0) callback(); - }); - } - } + async function finished() { + const items = await collection.find().toArray(); + test.equal(10, items.length); - function finished() { - collection.find().toArray((err, items) => { - expect(err).to.not.exist; - test.equal(10, items.length); - - collection - .find() - .limit(5) - .skip(3) - .toArray(function (err, items2) { - expect(err).to.not.exist; - test.equal(5, items2.length); - - // Check that we have the same elements - var numberEqual = 0; - var sliced = items.slice(3, 8); - - for (var i = 0; i < sliced.length; i++) { - if (sliced[i].x === items2[i].x) numberEqual = numberEqual + 1; - } - test.equal(5, numberEqual); - done(); - }); - }); - } + const items2 = await collection.find().limit(5).skip(3).toArray(); + test.equal(5, items2.length); - insert(function () { - finished(); - }); - }); - }); + // Check that we have the same elements + var numberEqual = 0; + var sliced = items.slice(3, 8); + + for (var i = 0; i < sliced.length; i++) { + if (sliced[i].x === items2[i].x) numberEqual = numberEqual + 1; + } + test.equal(5, numberEqual); + } + await insert(); + await finished(); } }); @@ -1148,24 +818,17 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('test_close_no_query_sent', (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('test_close_no_query_sent'); - const cursor = collection.find(); - cursor.close(err => { - expect(err).to.not.exist; - test.equal(true, cursor.closed); - done(); - }); - }); - }); + const cursor = collection.find(); + await cursor.close(); + + test.equal(true, cursor.closed); } }); @@ -1176,78 +839,55 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { var COUNT = 1000; const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('test_refill_via_get_more', (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('test_refill_via_get_more'); - function insert(callback) { - var docs = []; + async function insert() { + var docs = []; - for (var i = 0; i < COUNT; i++) { - docs.push({ a: i }); - } + for (var i = 0; i < COUNT; i++) { + docs.push({ a: i }); + } - collection.insertMany(docs, configuration.writeConcernMax(), callback); - } + await collection.insertMany(docs, configuration.writeConcernMax()); + } - function finished() { - collection.count((err, count) => { - expect(err).to.not.exist; - test.equal(COUNT, count); - }); + async function finished() { + let count = await collection.count(); + test.equal(COUNT, count); - var total = 0; - collection.find({}, {}).forEach( - item => { - total = total + item.a; - }, - err => { - expect(err).to.not.exist; - test.equal(499500, total); - - collection.count((err, count) => { - expect(err).to.not.exist; - test.equal(COUNT, count); - }); + var total = 0; + await collection.find({}, {}).forEach(item => { + total = total + item.a; + }); - collection.count((err, count) => { - expect(err).to.not.exist; - test.equal(COUNT, count); - - var total2 = 0; - collection.find().forEach( - item => { - total2 = total2 + item.a; - }, - err => { - expect(err).to.not.exist; - test.equal(499500, total2); - collection.count((err, count) => { - expect(err).to.not.exist; - test.equal(COUNT, count); - test.equal(total, total2); - done(); - }); - } - ); - }); - } - ); - } + test.equal(499500, total); - insert(function () { - finished(); - }); + count = await collection.count(); + test.equal(COUNT, count); + + count = await collection.count(); + test.equal(COUNT, count); + + var total2 = 0; + await collection.find().forEach(item => { + total2 = total2 + item.a; }); - }); + + test.equal(499500, total2); + count = await collection.count(); + + test.equal(COUNT, count); + test.equal(total, total2); + } + await insert(); + await finished(); } }); @@ -1258,78 +898,56 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('test_refill_via_get_more_alt_coll', (err, collection) => { - expect(err).to.not.exist; - var COUNT = 1000; + const db = client.db(configuration.db); + const collection = await db.createCollection('test_refill_via_get_more_alt_coll'); - function insert(callback) { - var docs = []; + var COUNT = 1000; - for (var i = 0; i < COUNT; i++) { - docs.push({ a: i }); - } + async function insert() { + var docs = []; - collection.insertMany(docs, configuration.writeConcernMax(), callback); - } + for (var i = 0; i < COUNT; i++) { + docs.push({ a: i }); + } - function finished() { - collection.count((err, count) => { - expect(err).to.not.exist; - test.equal(1000, count); - }); + await collection.insertMany(docs, configuration.writeConcernMax()); + } - var total = 0; - collection.find().forEach( - doc => { - total = total + doc.a; - }, - err => { - expect(err).to.not.exist; - test.equal(499500, total); - - collection.count((err, count) => { - expect(err).to.not.exist; - test.equal(1000, count); - }); + async function finished() { + let count = await collection.count(); + test.equal(1000, count); - collection.count((err, count) => { - expect(err).to.not.exist; - test.equal(1000, count); - - var total2 = 0; - collection.find().forEach( - doc => { - total2 = total2 + doc.a; - }, - err => { - expect(err).to.not.exist; - expect(total2).to.equal(499500); - - collection.count((err, count) => { - expect(err).to.not.exist; - expect(count).to.equal(1000); - expect(total2).to.equal(total); - done(); - }); - } - ); - }); - } - ); - } + var total = 0; + await collection.find().forEach(doc => { + total = total + doc.a; + }); - insert(function () { - finished(); - }); + test.equal(499500, total); + + count = await collection.count(); + test.equal(1000, count); + + count = await collection.count(); + test.equal(1000, count); + + var total2 = 0; + await collection.find().forEach(doc => { + total2 = total2 + doc.a; }); - }); + + expect(total2).to.equal(499500); + + count = await collection.count(); + + expect(count).to.equal(1000); + expect(total2).to.equal(total); + } + await insert(); + await finished(); } }); @@ -1340,32 +958,20 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('test_close_after_query_sent', (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('test_close_after_query_sent'); - collection.insert({ a: 1 }, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + await collection.insert({ a: 1 }, configuration.writeConcernMax()); - const cursor = collection.find({ a: 1 }); - cursor.next(err => { - expect(err).to.not.exist; + const cursor = collection.find({ a: 1 }); + await cursor.next(); - cursor.close(err => { - expect(err).to.not.exist; - test.equal(true, cursor.closed); - done(); - }); - }); - }); - }); - }); + await cursor.close(); + test.equal(true, cursor.closed); } }); @@ -1376,32 +982,19 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('test_count_with_fields', (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('test_count_with_fields'); - collection.insertOne({ x: 1, a: 2 }, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + await collection.insertOne({ x: 1, a: 2 }, configuration.writeConcernMax()); - collection - .find({}) - .project({ a: 1 }) - .toArray((err, items) => { - expect(err).to.not.exist; - test.equal(1, items.length); - test.equal(2, items[0].a); - expect(items[0].x).to.not.exist; - done(); - }); - }); - }); - }); + const items = await collection.find({}).project({ a: 1 }).toArray(); + test.equal(1, items.length); + test.equal(2, items[0].a); + expect(items[0].x).to.not.exist; } }); @@ -1412,29 +1005,20 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('test_count_with_fields_using_exclude', (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('test_count_with_fields_using_exclude'); - collection.insertOne({ x: 1, a: 2 }, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + await collection.insertOne({ x: 1, a: 2 }, configuration.writeConcernMax()); - collection.find({}, { projection: { x: 0 } }).toArray((err, items) => { - expect(err).to.not.exist; - test.equal(1, items.length); - test.equal(2, items[0].a); - expect(items[0].x).to.not.exist; - done(); - }); - }); - }); - }); + const items = await collection.find({}, { projection: { x: 0 } }).toArray(); + + test.equal(1, items.length); + test.equal(2, items[0].a); + expect(items[0].x).to.not.exist; } }); @@ -1445,7 +1029,7 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { var docs = []; for (var i = 0; i < 1000; i++) { @@ -1454,48 +1038,31 @@ describe('Cursor', function () { } const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('Should_correctly_execute_count_on_cursor_1', (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('Should_correctly_execute_count_on_cursor_1'); - // insert all docs - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + // insert all docs + await collection.insert(docs, configuration.writeConcernMax()); - let total = 0; - // Create a cursor for the content - const cursor = collection.find({}); - this.defer(() => cursor.close()); - - cursor.count(err => { - expect(err).to.not.exist; - // Ensure each returns all documents - cursor.forEach( - () => { - total++; - }, - err => { - expect(err).to.not.exist; - cursor.count((err, c) => { - expect(err).to.not.exist; - expect(c).to.equal(1000); - expect(total).to.equal(1000); - done(); - }); - } - ); - }); - }); - }); + let total = 0; + // Create a cursor for the content + const cursor = collection.find({}); + // this.defer(() => cursor.close()); + + await cursor.count(); + // Ensure each returns all documents + await cursor.forEach(() => { + total++; }); + const c = await cursor.count(); + expect(c).to.equal(1000); + expect(total).to.equal(1000); } }); - it('does not auto destroy streams', function (done) { + it('does not auto destroy streams', async function () { const docs = []; for (var i = 0; i < 10; i++) { @@ -1503,32 +1070,26 @@ describe('Cursor', function () { } const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('does_not_autodestroy_streams', (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('does_not_autodestroy_streams'); - collection.insertMany(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + await collection.insertMany(docs, configuration.writeConcernMax()); - const cursor = collection.find(); - const stream = cursor.stream(); - stream.on('close', () => { - expect.fail('extra close event must not be called'); - }); - stream.on('end', () => { - client.close(); - done(); - }); - stream.on('data', doc => { - expect(doc).to.exist; - }); - stream.resume(); - }); - }); + const cursor = collection.find(); + const stream = cursor.stream(); + stream.on('close', () => { + expect.fail('extra close event must not be called'); }); + stream.on('end', () => { + client.close(); + }); + stream.on('data', doc => { + expect(doc).to.exist; + }); + stream.resume(); + await once(stream, 'end'); }); it('should be able to stream documents', { @@ -1538,79 +1099,77 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { var docs = []; - for (var i = 0; i < 1000; i++) { - docs[i] = { a: i + 1 }; + for (var n = 0; n < 1000; n++) { + docs[n] = { a: n + 1 }; } var count = 0; const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('Should_be_able_to_stream_documents', (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('Should_be_able_to_stream_documents'); - // insert all docs - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + // insert all docs + await collection.insert(docs, configuration.writeConcernMax()); - var paused = 0, - closed = 0, - resumed = 0, - i = 0; + var paused = 0, + closed = 0, + resumed = 0, + i = 0, + err = null; - const cursor = collection.find(); - const stream = cursor.stream(); - - stream.on('data', function (doc) { - test.equal(true, !!doc); - test.equal(true, !!doc.a); - count = count + 1; + const cursor = collection.find(); + const stream = cursor.stream(); - if (paused > 0 && 0 === resumed) { - err = new Error('data emitted during pause'); - return testDone(); - } + stream.on('data', function (doc) { + test.equal(true, !!doc); + test.equal(true, !!doc.a); + count = count + 1; - if (++i === 3) { - stream.pause(); - paused++; + if (paused > 0 && 0 === resumed) { + err = new Error('data emitted during pause'); + testDone(); + return; + } - setTimeout(function () { - stream.resume(); - resumed++; - }, 20); - } - }); + if (++i === 3) { + stream.pause(); + paused++; - stream.once('error', function (er) { - err = er; - testDone(); - }); + setTimeout(function () { + stream.resume(); + resumed++; + }, 20); + } + }); - stream.once('end', function () { - closed++; - testDone(); - }); + stream.once('error', function (er) { + err = er; + testDone(); + }); - function testDone() { - expect(err).to.not.exist; - test.equal(i, docs.length); - test.equal(1, closed); - test.equal(1, paused); - test.equal(1, resumed); - test.strictEqual(cursor.closed, true); - done(); - } - }); - }); + stream.once('end', function () { + closed++; + testDone(); }); + + function testDone() { + expect(err).to.not.exist; + test.equal(i, docs.length); + test.equal(1, closed); + test.equal(1, paused); + test.equal(1, resumed); + test.strictEqual(cursor.closed, true); + } + + const promise = once(stream, 'end'); + await promise; + await client.close(); } }); @@ -1621,54 +1180,49 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { var i = 0, docs = [{ b: 2 }, { b: 3 }], doneCalled = 0; const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection( - 'immediately_destroying_a_stream_prevents_the_query_from_executing', - (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection( + 'immediately_destroying_a_stream_prevents_the_query_from_executing' + ); - // insert all docs - collection.insertMany(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + // insert all docs + await collection.insertMany(docs, configuration.writeConcernMax()); - const cursor = collection.find(); - const stream = cursor.stream(); + const cursor = collection.find(); + const stream = cursor.stream(); - stream.on('data', function () { - i++; - }); + stream.on('data', function () { + i++; + }); - cursor.once('close', testDone('close')); - stream.once('error', testDone('error')); + cursor.once('close', testDone('close')); + stream.once('error', testDone('error')); + const promise = once(cursor, 'close'); - stream.destroy(); + stream.destroy(); - function testDone() { - return err => { - ++doneCalled; + function testDone() { + return err => { + ++doneCalled; - if (doneCalled === 1) { - expect(err).to.not.exist; - test.strictEqual(0, i); - test.strictEqual(true, cursor.closed); - done(); - } - }; - } - }); + if (doneCalled === 1) { + expect(err).to.not.exist; + test.strictEqual(0, i); + test.strictEqual(true, cursor.closed); } - ); - }); + }; + } + + await cursor.close(); + await promise; } }); @@ -1802,49 +1356,43 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('cursor_stream_pipe', (err, collection) => { - expect(err).to.not.exist; - - var docs = []; - 'Aaden Aaron Adrian Aditya Bob Joe'.split(' ').forEach(function (name) { - docs.push({ name: name }); - }); + const db = client.db(configuration.db); + const collection = await db.createCollection('cursor_stream_pipe'); - // insert all docs - collection.insertMany(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + var docs = []; + 'Aaden Aaron Adrian Aditya Bob Joe'.split(' ').forEach(function (name) { + docs.push({ name: name }); + }); + + // insert all docs + await collection.insertMany(docs, configuration.writeConcernMax()); + + const filename = path.join(os.tmpdir(), '_nodemongodbnative_stream_out.txt'); + const out = fs.createWriteStream(filename); + const stream = collection.find().stream().map(JSON.stringify); + + stream.pipe(out); + // Wait for output stream to close + out.on('close', testDone); + + function testDone(err) { + // Object.prototype.toString = toString; + test.strictEqual(undefined, err); + var contents = fs.readFileSync(filename, 'utf8'); + test.ok(/Aaden/.test(contents)); + test.ok(/Aaron/.test(contents)); + test.ok(/Adrian/.test(contents)); + test.ok(/Aditya/.test(contents)); + test.ok(/Bob/.test(contents)); + test.ok(/Joe/.test(contents)); + fs.unlinkSync(filename); + } - const filename = path.join(os.tmpdir(), '_nodemongodbnative_stream_out.txt'); - const out = fs.createWriteStream(filename); - const stream = collection.find().stream().map(JSON.stringify); - - stream.pipe(out); - // Wait for output stream to close - out.on('close', testDone); - - function testDone(err) { - // Object.prototype.toString = toString; - test.strictEqual(undefined, err); - var contents = fs.readFileSync(filename, 'utf8'); - test.ok(/Aaden/.test(contents)); - test.ok(/Aaron/.test(contents)); - test.ok(/Adrian/.test(contents)); - test.ok(/Aditya/.test(contents)); - test.ok(/Bob/.test(contents)); - test.ok(/Joe/.test(contents)); - fs.unlinkSync(filename); - done(); - } - }); - }); - }); + await once(out, 'close'); } }); @@ -1884,33 +1432,24 @@ describe('Cursor', function () { } ); - it('shouldAwaitDataWithDocumentsAvailable', function (done) { + it('shouldAwaitDataWithDocumentsAvailable', async function () { // www.mongodb.com/docs/display/DOCS/Tailable+Cursors const configuration = this.configuration; const client = configuration.newClient({ maxPoolSize: 1 }); - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - const options = { capped: true, size: 8 }; - db.createCollection('should_await_data_no_docs', options, (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const options = { capped: true, size: 8 }; + const collection = await db.createCollection('should_await_data_no_docs', options); - // Create cursor with awaitData, and timeout after the period specified - const cursor = collection.find({}, { tailable: true, awaitData: true }); - this.defer(() => cursor.close()); + // Create cursor with awaitData, and timeout after the period specified + const cursor = collection.find({}, { tailable: true, awaitData: true }); + // this.defer(() => cursor.close()); - cursor.forEach( - () => {}, - err => { - expect(err).to.not.exist; - done(); - } - ); - }); - }); + await cursor.forEach(() => { }); + await cursor.close(); + await client.close(); }); context('awaiting data core tailable cursor test', () => { @@ -1936,7 +1475,7 @@ describe('Cursor', function () { try { await db.collection('cursor_tailable').drop(); // eslint-disable-next-line no-empty - } catch {} + } catch { } const collection = await db.createCollection('cursor_tailable', { capped: true, @@ -1978,34 +1517,22 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { // www.mongodb.com/docs/display/DOCS/Tailable+Cursors const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - const options = { capped: true, size: 8 }; - db.createCollection('should_await_data', options, (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const options = { capped: true, size: 8 }; + const collection = await db.createCollection('should_await_data', options); - collection.insert({ a: 1 }, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + await collection.insert({ a: 1 }, configuration.writeConcernMax()); - // Create cursor with awaitData, and timeout after the period specified - var cursor = collection.find({}, { tailable: true, awaitData: true }); - cursor.forEach( - () => cursor.kill(), - () => { - // kill cursor b/c cursor is tailable / awaitable - cursor.close(done); - } - ); - }); - }); - }); + // Create cursor with awaitData, and timeout after the period specified + var cursor = collection.find({}, { tailable: true, awaitData: true }); + await cursor.forEach(() => cursor.kill()); + await cursor.close(); } }); @@ -2016,7 +1543,7 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { var docs = []; docs[0] = { _keywords: [ @@ -2195,39 +1722,20 @@ describe('Cursor', function () { }; const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - // Insert all the docs - var collection = db.collection('shouldCorrectExecuteExplainHonoringLimit'); - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + // Insert all the docs + var collection = db.collection('shouldCorrectExecuteExplainHonoringLimit'); + await collection.insert(docs, configuration.writeConcernMax()); - collection.createIndex({ _keywords: 1 }, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + await collection.createIndex({ _keywords: 1 }, configuration.writeConcernMax()); - collection - .find({ _keywords: 'red' }) - .limit(10) - .toArray(function (err, result) { - expect(err).to.not.exist; - test.ok(result != null); - - collection - .find({ _keywords: 'red' }, {}) - .limit(10) - .explain(function (err, result) { - expect(err).to.not.exist; - test.ok(result != null); - - done(); - }); - }); - }); - }); - }); + let result = await collection.find({ _keywords: 'red' }).limit(10).toArray(); + test.ok(result != null); + + result = await collection.find({ _keywords: 'red' }, {}).limit(10).explain(); + test.ok(result != null); } }); @@ -2238,30 +1746,18 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { var doc = { name: 'camera', _keywords: ['compact', 'ii2gd', 'led', 'red', 'aet'] }; const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - var collection = db.collection('shouldNotExplainWhenFalse'); - collection.insert(doc, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; - - collection - .find({ _keywords: 'red' }) - .limit(10) - .toArray(function (err, result) { - expect(err).to.not.exist; + const db = client.db(configuration.db); + var collection = db.collection('shouldNotExplainWhenFalse'); + await collection.insert(doc, configuration.writeConcernMax()); - test.equal('camera', result[0].name); - done(); - }); - }); - }); + const result = await collection.find({ _keywords: 'red' }).limit(10).toArray(); + test.equal('camera', result[0].name); } }); @@ -2272,32 +1768,29 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); - - const db = client.db(configuration.db); - try { - db.collection('shouldFailToSetReadPreferenceOnCursor') - .find() - .withReadPreference('notsecondary'); - test.ok(false); - } catch (err) {} // eslint-disable-line + await client.connect(); - db.collection('shouldFailToSetReadPreferenceOnCursor') + const db = client.db(configuration.db); + try { + await db + .collection('shouldFailToSetReadPreferenceOnCursor') .find() - .withReadPreference('secondary'); + .withReadPreference('notsecondary'); + test.ok(false); + } catch (err) { } // eslint-disable-line - done(); - }); + await db + .collection('shouldFailToSetReadPreferenceOnCursor') + .find() + .withReadPreference('secondary'); } }); it('should allow setting the cursors readConcern through a builder', { metadata: { requires: { mongodb: '>=3.2' } }, - test: function (done) { + test: async function () { const client = this.configuration.newClient({ monitorCommands: true }); const events = []; client.on('commandStarted', event => { @@ -2309,14 +1802,12 @@ describe('Cursor', function () { const cursor = db.collection('foo').find().withReadConcern('local'); expect(cursor).property('readConcern').to.have.property('level').equal('local'); - cursor.toArray(err => { - expect(err).to.not.exist; + await cursor.toArray(); - expect(events).to.have.length(1); - const findCommand = events[0]; - expect(findCommand).nested.property('command.readConcern').to.eql({ level: 'local' }); - client.close(done); - }); + expect(events).to.have.length(1); + const findCommand = events[0]; + expect(findCommand).nested.property('command.readConcern').to.eql({ level: 'local' }); + await client.close(); } }); @@ -2327,53 +1818,40 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('shouldNotFailDueToStackOverflowEach', (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('shouldNotFailDueToStackOverflowEach'); - var docs = []; - var total = 0; - for (var i = 0; i < 30000; i++) docs.push({ a: i }); - var allDocs = []; - var left = 0; + var docs = []; + var total = 0; + for (var i = 0; i < 30000; i++) docs.push({ a: i }); + var allDocs = []; + var left = 0; - while (docs.length > 0) { - allDocs.push(docs.splice(0, 1000)); - } - // Get all batches we must insert - left = allDocs.length; - var totalI = 0; - - // Execute inserts - for (i = 0; i < left; i++) { - collection.insert(allDocs.shift(), configuration.writeConcernMax(), function (err, d) { - expect(err).to.not.exist; - - left = left - 1; - totalI = totalI + d.length; - - if (left === 0) { - collection.find({}).forEach( - () => { - total++; - }, - err => { - expect(err).to.not.exist; - expect(total).to.equal(30000); - done(); - } - ); - } - }); - } - }); - }); + while (docs.length > 0) { + allDocs.push(docs.splice(0, 1000)); + } + // Get all batches we must insert + left = allDocs.length; + var totalI = 0; + + // Execute inserts + for (i = 0; i < left; i++) { + const d = await collection.insert(allDocs.shift(), configuration.writeConcernMax()); + + left = left - 1; + totalI = totalI + d.length; + + if (left === 0) { + await collection.find({}).forEach(() => { + total++; + }); + expect(total).to.equal(30000); + } + } } }); @@ -2412,69 +1890,45 @@ describe('Cursor', function () { await client.close(); }); - it('should correctly skip and limit', function (done) { + it('should correctly skip and limit', async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; + await client.connect(); - const db = client.db(configuration.db); - var collection = db.collection('shouldCorrectlySkipAndLimit'); - var docs = []; - for (var i = 0; i < 100; i++) docs.push({ a: i, OrderNumber: i }); + const db = client.db(configuration.db); + var collection = db.collection('shouldCorrectlySkipAndLimit'); + var docs = []; + for (var i = 0; i < 100; i++) docs.push({ a: i, OrderNumber: i }); - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + await collection.insert(docs, configuration.writeConcernMax()); - collection - .find({}, { OrderNumber: 1 }) - .skip(10) - .limit(10) - .toArray((err, items) => { - expect(err).to.not.exist; - test.equal(10, items[0].OrderNumber); - - collection - .find({}, { OrderNumber: 1 }) - .skip(10) - .limit(10) - .count() - .then(count => { - test.equal(10, count); - client.close(done); - }); - }); - }); - }); + const items = await collection.find({}, { OrderNumber: 1 }).skip(10).limit(10).toArray(); + + test.equal(10, items[0].OrderNumber); + + const count = await collection.find({}, { OrderNumber: 1 }).skip(10).limit(10).count(); + test.equal(10, count); + + await client.close(); }); - it('shouldFailToTailANormalCollection', function (done) { + it('shouldFailToTailANormalCollection', async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - var collection = db.collection('shouldFailToTailANormalCollection'); - var docs = []; - for (var i = 0; i < 100; i++) docs.push({ a: i, OrderNumber: i }); + const db = client.db(configuration.db); + var collection = db.collection('shouldFailToTailANormalCollection'); + var docs = []; + for (var i = 0; i < 100; i++) docs.push({ a: i, OrderNumber: i }); - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + await collection.insert(docs, configuration.writeConcernMax()); - const cursor = collection.find({}, { tailable: true }); - cursor.forEach( - () => {}, - err => { - test.ok(err instanceof Error); - test.ok(typeof err.code === 'number'); + const cursor = collection.find({}, { tailable: true }); + const err = await cursor.forEach(() => { }).catch(e => e); + test.ok(err instanceof Error); + test.ok(typeof err.code === 'number'); - // Close cursor b/c we did not exhaust cursor - cursor.close(); - done(); - } - ); - }); - }); + // Close cursor b/c we did not exhaust cursor + cursor.close(); }); it('shouldCorrectlyUseFindAndCursorCount', { @@ -2484,43 +1938,32 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; // DOC_LINE var client = new MongoClient(new Server('localhost', 27017)); // DOC_START // Establish connection to db - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); - - const db = client.db(configuration.db); + await client.connect(); - // Create a lot of documents to insert - var docs = []; - for (var i = 0; i < 100; i++) { - docs.push({ a: i }); - } + const db = client.db(configuration.db); - // Create a collection - db.createCollection('test_close_function_on_cursor_2', (err, collection) => { - expect(err).to.not.exist; + // Create a lot of documents to insert + var docs = []; + for (var i = 0; i < 100; i++) { + docs.push({ a: i }); + } - // Insert documents into collection - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + // Create a collection + const collection = await db.createCollection('test_close_function_on_cursor_2'); - const cursor = collection.find({}); + // Insert documents into collection + await collection.insert(docs, configuration.writeConcernMax()); - cursor.count((err, count) => { - expect(err).to.not.exist; - test.equal(100, count); + const cursor = collection.find({}); - done(); - }); - }); - }); - }); + const count = await cursor.count(); + test.equal(100, count); // DOC_END } }); @@ -2535,57 +1978,41 @@ describe('Cursor', function () { } }, - test: function (done) { + test: async function () { const configuration = this.configuration; // DOC_LINE var client = new MongoClient(new Server('localhost', 27017)); // DOC_START // Establish connection to db - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - var col = db.collection('count_hint'); + const db = client.db(configuration.db); + var col = db.collection('count_hint'); - col.insert([{ i: 1 }, { i: 2 }], { writeConcern: { w: 1 } }, err => { - expect(err).to.not.exist; + await col.insert([{ i: 1 }, { i: 2 }], { writeConcern: { w: 1 } }); - col.createIndex({ i: 1 }, err => { - expect(err).to.not.exist; + await col.createIndex({ i: 1 }); - col.find({ i: 1 }, { hint: '_id_' }).count((err, count) => { - expect(err).to.not.exist; - test.equal(1, count); + let count = await col.find({ i: 1 }, { hint: '_id_' }).count(); + test.equal(1, count); - col.find({}, { hint: '_id_' }).count((err, count) => { - expect(err).to.not.exist; - test.equal(2, count); + count = await col.find({}, { hint: '_id_' }).count(); + test.equal(2, count); - col.find({ i: 1 }, { hint: 'BAD HINT' }).count(err => { - test.ok(err != null); + const err = await col + .find({ i: 1 }, { hint: 'BAD HINT' }) + .count() + .catch(e => e); + test.ok(err != null); - col.createIndex({ x: 1 }, { sparse: true }, err => { - expect(err).to.not.exist; + await col.createIndex({ x: 1 }, { sparse: true }); - col.find({ i: 1 }, { hint: 'x_1' }).count((err, count) => { - expect(err).to.not.exist; - test.equal(0, count); + count = await col.find({ i: 1 }, { hint: 'x_1' }).count(); + test.equal(0, count); - col.find({}, { hint: 'i_1' }).count((err, count) => { - expect(err).to.not.exist; - test.equal(2, count); + count = await col.find({}, { hint: 'i_1' }).count(); - done(); - }); - }); - }); - }); - }); - }); - }); - }); - }); + test.equal(2, count); // DOC_END } }); @@ -2597,44 +2024,30 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); + const db = client.db(configuration.db); - const db = client.db(configuration.db); + // Create a lot of documents to insert + var docs = []; + for (var i = 0; i < 100; i++) { + docs.push({ a: i }); + } - // Create a lot of documents to insert - var docs = []; - for (var i = 0; i < 100; i++) { - docs.push({ a: i }); - } + // Create a collection + const collection = await db.createCollection('terminate_each_returning_false'); - // Create a collection - db.createCollection('terminate_each_returning_false', (err, collection) => { - expect(err).to.not.exist; + // Insert documents into collection + await collection.insert(docs, configuration.writeConcernMax()); + var finished = false; - // Insert documents into collection - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; - var finished = false; - - collection.find({}).forEach( - doc => { - expect(doc).to.exist; - test.equal(finished, false); - finished = true; - - done(); - return false; - }, - err => { - expect(err).to.not.exist; - } - ); - }); - }); + await collection.find({}).forEach(doc => { + expect(doc).to.exist; + test.equal(finished, false); + finished = true; + + return false; }); } }); @@ -2646,31 +2059,23 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - var donkey = { - color: 'brown' - }; + const db = client.db(configuration.db); + var donkey = { + color: 'brown' + }; - db.collection('donkies').insertOne(donkey, function (err, result) { - expect(err).to.not.exist; + const result = await db.collection('donkies').insertOne(donkey); - var query = { _id: result.insertedId }; - var options = { maxTimeMS: 1000 }; + var query = { _id: result.insertedId }; + var options = { maxTimeMS: 1000 }; - db.collection('donkies').findOne(query, options, function (err, doc) { - expect(err).to.not.exist; - test.equal('brown', doc.color); + const doc = await db.collection('donkies').findOne(query, options); - done(); - }); - }); - }); + test.equal('brown', doc.color); } }); @@ -2681,53 +2086,38 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - const collectionName = 'should_correctly_handle_batchSize_2'; - db.collection(collectionName).insert([{ x: 1 }, { x: 2 }, { x: 3 }], err => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collectionName = 'should_correctly_handle_batchSize_2'; + await db.collection(collectionName).insert([{ x: 1 }, { x: 2 }, { x: 3 }]); - const cursor = db.collection(collectionName).find({}, { batchSize: 2 }); - this.defer(() => cursor.close()); + const cursor = db.collection(collectionName).find({}, { batchSize: 2 }); + // this.defer(() => cursor.close()); - cursor.next(err => { - expect(err).to.not.exist; + await cursor.next(); + + await cursor.next(); - cursor.next(err => { - expect(err).to.not.exist; + await cursor.next(); - cursor.next(err => { - expect(err).to.not.exist; - done(); - }); - }); - }); - }); - }); + await cursor.close(); } }); it('Should report database name and collection name', { metadata: { requires: { topology: ['single'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); - - const db = client.db(configuration.db); - const cursor = db.collection('myCollection').find({}); - test.equal('myCollection', cursor.namespace.collection); - test.equal('integration_tests', cursor.namespace.db); + await client.connect(); - done(); - }); + const db = client.db(configuration.db); + const cursor = db.collection('myCollection').find({}); + test.equal('myCollection', cursor.namespace.collection); + test.equal('integration_tests', cursor.namespace.db); } }); @@ -2738,7 +2128,7 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { var docs = []; for (var i = 0; i < 1000; i++) { @@ -2747,42 +2137,27 @@ describe('Cursor', function () { } const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection( - 'Should_correctly_execute_count_on_cursor_2', - function (err, collection) { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('Should_correctly_execute_count_on_cursor_2'); - // insert all docs - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; - - // Create a cursor for the content - var cursor = collection.find({}); - cursor.limit(100); - cursor.skip(10); - cursor.count({ maxTimeMS: 1000 }, err => { - expect(err).to.not.exist; - - // Create a cursor for the content - var cursor = collection.find({}); - cursor.limit(100); - cursor.skip(10); - cursor.maxTimeMS(100); - - cursor.count(err => { - expect(err).to.not.exist; - done(); - }); - }); - }); - } - ); - }); + // insert all docs + await collection.insert(docs, configuration.writeConcernMax()); + + // Create a cursor for the content + var cursor = collection.find({}); + cursor.limit(100); + cursor.skip(10); + await cursor.count({ maxTimeMS: 1000 }); + + // Create a cursor for the content + cursor = collection.find({}); + cursor.limit(100); + cursor.skip(10); + cursor.maxTimeMS(100); + + await cursor.count(); } }); @@ -2793,7 +2168,7 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { var docs = []; for (var i = 0; i < 1000; i++) { @@ -2802,31 +2177,17 @@ describe('Cursor', function () { } const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); - - const db = client.db(configuration.db); - db.createCollection( - 'Should_correctly_execute_count_on_cursor_3', - function (err, collection) { - expect(err).to.not.exist; + await client.connect(); - // insert all docs - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('Should_correctly_execute_count_on_cursor_3'); - // Create a cursor for the content - var cursor = collection.find({}, { maxTimeMS: 100 }); - cursor.toArray(err => { - expect(err).to.not.exist; + // insert all docs + await collection.insert(docs, configuration.writeConcernMax()); - done(); - }); - }); - } - ); - }); + // Create a cursor for the content + var cursor = collection.find({}, { maxTimeMS: 100 }); + await cursor.toArray(); } }); @@ -2837,7 +2198,7 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { var docs = []; for (var i = 0; i < 1000; i++) { @@ -2845,39 +2206,30 @@ describe('Cursor', function () { docs[i] = { a: i, createdAt: new Date(d) }; } - const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); - - const db = client.db(configuration.db); - var collection = db.collection('map_toArray'); + const configuration = this.configuration; + await client.connect(); - // insert all docs - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + var collection = db.collection('map_toArray'); - // Create a cursor for the content - var cursor = collection - .find({}) - .map(function () { - return { a: 1 }; - }) - .batchSize(5) - .limit(10); + // insert all docs + await collection.insert(docs, configuration.writeConcernMax()); - cursor.toArray(function (err, docs) { - expect(err).to.not.exist; - test.equal(10, docs.length); + // Create a cursor for the content + var cursor = collection + .find({}) + .map(function () { + return { a: 1 }; + }) + .batchSize(5) + .limit(10); - // Ensure all docs where mapped - docs.forEach(doc => { - expect(doc).property('a').to.equal(1); - }); + const docs2 = await cursor.toArray(); + test.equal(10, docs2.length); - done(); - }); - }); + // Ensure all docs where mapped + docs2.forEach(doc => { + expect(doc).property('a').to.equal(1); }); } }); @@ -2889,7 +2241,7 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { const docs = []; for (var i = 0; i < 1000; i++) { const d = new Date().getTime() + i * 1000; @@ -2897,34 +2249,26 @@ describe('Cursor', function () { } const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - const collection = db.collection('map_next'); + const db = client.db(configuration.db); + const collection = db.collection('map_next'); - // insert all docs - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + // insert all docs + await collection.insert(docs, configuration.writeConcernMax()); - // Create a cursor for the content - const cursor = collection - .find({}) - .map(function () { - return { a: 1 }; - }) - .batchSize(5) - .limit(10); - - this.defer(() => cursor.close()); - cursor.next((err, doc) => { - expect(err).to.not.exist; - test.equal(1, doc.a); - done(); - }); - }); - }); + // Create a cursor for the content + const cursor = collection + .find({}) + .map(function () { + return { a: 1 }; + }) + .batchSize(5) + .limit(10); + + const doc = await cursor.next(); + test.equal(1, doc.a); + await cursor.close(); } }); @@ -2935,7 +2279,7 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { var docs = []; for (var i = 0; i < 1000; i++) { @@ -2944,36 +2288,25 @@ describe('Cursor', function () { } const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - const collection = db.collection('map_each'); + const db = client.db(configuration.db); + const collection = db.collection('map_each'); - // insert all docs - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + // insert all docs + await collection.insert(docs, configuration.writeConcernMax()); - // Create a cursor for the content - var cursor = collection - .find({}) - .map(function () { - return { a: 1 }; - }) - .batchSize(5) - .limit(10); - - cursor.forEach( - doc => { - test.equal(1, doc.a); - }, - err => { - expect(err).to.not.exist; - done(); - } - ); - }); + // Create a cursor for the content + var cursor = collection + .find({}) + .map(function () { + return { a: 1 }; + }) + .batchSize(5) + .limit(10); + + await cursor.forEach(doc => { + test.equal(1, doc.a); }); } }); @@ -2985,7 +2318,7 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { var docs = []; for (var i = 0; i < 1000; i++) { @@ -2994,40 +2327,30 @@ describe('Cursor', function () { } const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - var collection = db.collection('map_forEach'); + const db = client.db(configuration.db); + var collection = db.collection('map_forEach'); - // insert all docs - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + // insert all docs + await collection.insert(docs, configuration.writeConcernMax()); - // Create a cursor for the content - var cursor = collection - .find({}) - .map(function () { - return { a: 2 }; - }) - .map(function (x) { - return { a: x.a * x.a }; - }) - .batchSize(5) - .limit(10); - - cursor.forEach( - doc => { - test.equal(4, doc.a); - }, - err => { - expect(err).to.not.exist; - done(); - } - ); - }); + // Create a cursor for the content + var cursor = collection + .find({}) + .map(function () { + return { a: 2 }; + }) + .map(function (x) { + return { a: x.a * x.a }; + }) + .batchSize(5) + .limit(10); + + await cursor.forEach(doc => { + test.equal(4, doc.a); }); + await cursor.close(); } }); @@ -3038,7 +2361,7 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { var docs = []; for (var i = 0; i < 1000; i++) { @@ -3047,37 +2370,27 @@ describe('Cursor', function () { } const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - var collection = db.collection('map_mapmapforEach'); + const db = client.db(configuration.db); + var collection = db.collection('map_mapmapforEach'); - // insert all docs - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + // insert all docs + await collection.insert(docs, configuration.writeConcernMax()); - // Create a cursor for the content - var cursor = collection - .find({}) - .map(function () { - return { a: 1 }; - }) - .batchSize(5) - .limit(10); - - cursor.forEach( - doc => { - expect(doc).property('a').to.equal(1); - }, - err => { - expect(err).to.not.exist; - done(); - } - ); - }); + // Create a cursor for the content + var cursor = collection + .find({}) + .map(function () { + return { a: 1 }; + }) + .batchSize(5) + .limit(10); + + await cursor.forEach(doc => { + expect(doc).property('a').to.equal(1); }); + await cursor.close(); } }); @@ -3086,38 +2399,25 @@ describe('Cursor', function () { // in this case we are setting that node needs to be higher than 0.10.X to run metadata: { requires: { topology: ['single', 'replicaset'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); - - const db = client.db(configuration.db); - var collection = db.collection('cursor_limit_skip_correctly'); + await client.connect(); - // Insert x number of docs - var ordered = collection.initializeUnorderedBulkOp(); + const db = client.db(configuration.db); + var collection = db.collection('cursor_limit_skip_correctly'); - for (var i = 0; i < 6000; i++) { - ordered.insert({ a: i }); - } + // Insert x number of docs + var ordered = collection.initializeUnorderedBulkOp(); - ordered.execute({ writeConcern: { w: 1 } }, err => { - expect(err).to.not.exist; + for (var i = 0; i < 6000; i++) { + ordered.insert({ a: i }); + } - // Let's attempt to skip and limit - collection - .find({}) - .limit(2016) - .skip(2016) - .toArray(function (err, docs) { - expect(err).to.not.exist; - test.equal(2016, docs.length); + await ordered.execute({ writeConcern: { w: 1 } }); - done(); - }); - }); - }); + // Let's attempt to skip and limit + const docs = await collection.find({}).limit(2016).skip(2016).toArray(); + test.equal(2016, docs.length); } }); @@ -3126,45 +2426,35 @@ describe('Cursor', function () { // in this case we are setting that node needs to be higher than 0.10.X to run metadata: { requires: { topology: ['single'], mongodb: '<7.0.0' } }, - test: function (done) { + test: async function () { const configuration = this.configuration; const client = configuration.newClient(); - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - var options = { capped: true, size: 8 }; - db.createCollection( - 'should_await_data_max_awaittime_ms', - options, - function (err, collection) { - expect(err).to.not.exist; - - collection.insert({ a: 1 }, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; - - // Create cursor with awaitData, and timeout after the period specified - var cursor = collection - .find({}) - .addCursorFlag('tailable', true) - .addCursorFlag('awaitData', true) - .maxAwaitTimeMS(500); - - const s = new Date(); - cursor.forEach( - () => { - setTimeout(() => cursor.close(), 300); - }, - () => { - test.ok(new Date().getTime() - s.getTime() >= 500); - done(); - } - ); - }); - } - ); - }); + const db = client.db(configuration.db); + var options = { capped: true, size: 8 }; + const collection = await db.createCollection('should_await_data_max_awaittime_ms', options); + + await collection.insert({ a: 1 }, configuration.writeConcernMax()); + + // Create cursor with awaitData, and timeout after the period specified + var cursor = collection + .find({}) + .addCursorFlag('tailable', true) + .addCursorFlag('awaitData', true) + .maxAwaitTimeMS(500); + + const s = new Date(); + const err = await cursor + .forEach(async () => { + await sleep(300); + await cursor.close(); + }) + .catch(e => e); + test.ok(err instanceof Error); + test.ok(new Date().getTime() - s.getTime() >= 500); + await cursor.close(); + await client.close(); } }); @@ -3173,37 +2463,32 @@ describe('Cursor', function () { // in this case we are setting that node needs to be higher than 0.10.X to run metadata: { requires: { topology: ['single', 'replicaset'] } }, - test: function (done) { + test: async function () { const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); - - const db = client.db(configuration.db); - var collection = db.collection('cursor_limit_skip_correctly'); + await client.connect(); - // Insert x number of docs - var ordered = collection.initializeUnorderedBulkOp(); + const db = client.db(configuration.db); + var collection = db.collection('cursor_limit_skip_correctly'); - for (var i = 0; i < 100; i++) { - ordered.insert({ a: i }); - } + // Insert x number of docs + var ordered = collection.initializeUnorderedBulkOp(); - ordered.execute({ writeConcern: { w: 1 } }, err => { - expect(err).to.not.exist; + for (var i = 0; i < 100; i++) { + ordered.insert({ a: i }); + } - // Let's attempt to skip and limit - var cursor = collection.find({}).batchSize(10); - const stream = cursor.stream(); - stream.on('data', function () { - stream.destroy(); - }); + await ordered.execute({ writeConcern: { w: 1 } }); - cursor.on('close', function () { - done(); - }); - }); + // Let's attempt to skip and limit + var cursor = collection.find({}).batchSize(10); + const stream = cursor.stream(); + stream.on('data', function () { + stream.destroy(); }); + + const onClose = once(cursor, 'close'); + await cursor.close(); + await onClose; } }); @@ -3214,7 +2499,7 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { var docs = []; for (var i = 0; i < 1; i++) { @@ -3223,39 +2508,23 @@ describe('Cursor', function () { } const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection( - 'shouldCorrectlyExecuteEnsureIndexWithNoCallback', - function (err, collection) { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection( + 'shouldCorrectlyExecuteEnsureIndexWithNoCallback' + ); - // ensure index of createdAt index - collection.createIndex({ createdAt: 1 }, err => { - expect(err).to.not.exist; + // ensure index of createdAt index + await collection.createIndex({ createdAt: 1 }); - // insert all docs - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + // insert all docs + await collection.insert(docs, configuration.writeConcernMax()); - // Find with sort - collection - .find() - .sort(['createdAt', 'asc']) - .toArray((err, items) => { - expect(err).to.not.exist; + // Find with sort + const items = await collection.find().sort(['createdAt', 'asc']).toArray(); - test.equal(1, items.length); - done(); - }); - }); - }); - } - ); - }); + test.equal(1, items.length); } }); @@ -3266,7 +2535,7 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { var docs = []; for (var i = 0; i < 50; i++) { @@ -3275,41 +2544,22 @@ describe('Cursor', function () { } const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('negative_batch_size_and_limit_set', (err, collection) => { - expect(err).to.not.exist; + const db = client.db(configuration.db); + const collection = await db.createCollection('negative_batch_size_and_limit_set'); - // insert all docs - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + // insert all docs + await collection.insert(docs, configuration.writeConcernMax()); - // Create a cursor for the content - var cursor = collection.find({}); - cursor - .limit(100) - .skip(0) - .count(function (err, c) { - expect(err).to.not.exist; - test.equal(50, c); - - var cursor = collection.find({}); - cursor - .limit(100) - .skip(0) - .toArray(err => { - expect(err).to.not.exist; - test.equal(50, c); - - done(); - }); - }); - }); - }); - }); + // Create a cursor for the content + var cursor = collection.find({}); + var c = await cursor.limit(100).skip(0).count(); + test.equal(50, c); + + cursor = collection.find({}); + c = (await cursor.limit(100).skip(0).toArray()).length; + test.equal(50, c); } }); @@ -3320,7 +2570,7 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { var docs = []; const configuration = this.configuration; @@ -3329,32 +2579,17 @@ describe('Cursor', function () { docs[i] = { a: i, createdAt: new Date(d) }; } - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); - - const db = client.db(configuration.db); - db.createCollection( - 'Should_correctly_execute_count_on_cursor_1_', - function (err, collection) { - expect(err).to.not.exist; - - // insert all docs - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; + await client.connect(); + const db = client.db(configuration.db); + const collection = await db.createCollection('Should_correctly_execute_count_on_cursor_1_'); - // Create a cursor for the content - var cursor = collection.find({}); - cursor.batchSize(-10).next(err => { - expect(err).to.not.exist; - test.ok(cursor.id.equals(BSON.Long.ZERO)); + // insert all docs + await collection.insert(docs, configuration.writeConcernMax()); - done(); - }); - }); - } - ); - }); + // Create a cursor for the content + var cursor = collection.find({}); + await cursor.batchSize(-10).next(); + test.ok(cursor.id.equals(BSON.Long.ZERO)); } }); @@ -3365,7 +2600,7 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { var started = []; const configuration = this.configuration; const client = configuration.newClient(configuration.writeConcernMax(), { @@ -3376,28 +2611,26 @@ describe('Cursor', function () { if (event.commandName === 'count') started.push(event); }); - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.collection('cursor_count_test', { readConcern: { level: 'local' } }) - .find({ project: '123' }) - .limit(5) - .skip(5) - .hint({ project: 1 }) - .count(err => { - expect(err).to.not.exist; - test.equal(1, started.length); - if (started[0].command.readConcern) - test.deepEqual({ level: 'local' }, started[0].command.readConcern); - test.deepEqual({ project: 1 }, started[0].command.hint); - test.equal(5, started[0].command.skip); - test.equal(5, started[0].command.limit); - - done(); - }); - }); + const db = client.db(configuration.db); + await db + .collection('cursor_count_test', { readConcern: { level: 'local' } }) + .find({ project: '123' }) + .limit(5) + .skip(5) + .hint({ project: 1 }) + .count(); + + test.equal(1, started.length); + if (started[0].command.readConcern) { + test.deepEqual({ level: 'local' }, started[0].command.readConcern); + } + test.deepEqual({ project: 1 }, started[0].command.hint); + test.equal(5, started[0].command.skip); + test.equal(5, started[0].command.limit); + + await client.close(); } }); @@ -3408,7 +2641,7 @@ describe('Cursor', function () { requires: { topology: ['single', 'replicaset', 'sharded'] } }, - test: function (done) { + test: async function () { var started = []; const configuration = this.configuration; @@ -3416,34 +2649,28 @@ describe('Cursor', function () { if (event.commandName === 'count') started.push(event); }); - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.collection('cursor_count_test1', { readConcern: { level: 'local' } }).count( - { - project: '123' - }, - { - readConcern: { level: 'local' }, - limit: 5, - skip: 5, - hint: { project: 1 } - }, - err => { - expect(err).to.not.exist; - test.equal(1, started.length); - if (started[0].command.readConcern) - test.deepEqual({ level: 'local' }, started[0].command.readConcern); - test.deepEqual({ project: 1 }, started[0].command.hint); - test.equal(5, started[0].command.skip); - test.equal(5, started[0].command.limit); - - done(); - } - ); - }); + const db = client.db(configuration.db); + await db.collection('cursor_count_test1', { readConcern: { level: 'local' } }).count( + { + project: '123' + }, + { + readConcern: { level: 'local' }, + limit: 5, + skip: 5, + hint: { project: 1 } + } + ); + + test.equal(1, started.length); + if (started[0].command.readConcern) { + test.deepEqual({ level: 'local' }, started[0].command.readConcern); + } + test.deepEqual({ project: 1 }, started[0].command.hint); + test.equal(5, started[0].command.skip); + test.equal(5, started[0].command.limit); } }); @@ -3467,7 +2694,7 @@ describe('Cursor', function () { const configuration = this.configuration; - let cleanup = () => {}; + let cleanup = () => { }; let caughtError = undefined; return ( @@ -3687,40 +2914,32 @@ describe('Cursor', function () { const cursor = collection.find(); this.defer(() => cursor.close()); - const promise = cursor.forEach(() => {}); + const promise = cursor.forEach(() => { }); expect(promise).to.exist.and.to.be.an.instanceof(Promise); return promise; }); }); - it('should return false when exhausted and hasNext called more than once', function (done) { + it('should return false when exhausted and hasNext called more than once', async function () { const configuration = this.configuration; const client = configuration.newClient({ w: 1 }, { maxPoolSize: 1 }); - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const db = client.db(configuration.db); - db.createCollection('cursor_hasNext_test').then(() => { - const cursor = db.collection('cursor_hasNext_test').find(); - this.defer(() => cursor.close()); - - cursor - .hasNext() - .then(val1 => { - expect(val1).to.equal(false); - return cursor.hasNext(); - }) - .then(val2 => { - expect(val2).to.equal(false); - done(); - }); - }); - }); + const db = client.db(configuration.db); + await db.createCollection('cursor_hasNext_test'); + const cursor = db.collection('cursor_hasNext_test').find(); + + const val1 = await cursor.hasNext(); + expect(val1).to.equal(false); + const val2 = await cursor.hasNext(); + expect(val2).to.equal(false); + + await cursor.close(); + await client.close(); }); - const testTransformStream = (config, _done) => { + const testTransformStream = async config => { const client = config.client; const configuration = config.configuration; const collectionName = config.collectionName; @@ -3728,46 +2947,49 @@ describe('Cursor', function () { const expectedSet = config.expectedSet; let cursor; - const done = err => cursor.close(err2 => client.close(err3 => _done(err || err2 || err3))); + const done = async err => { + await cursor.close(); + await client.close(); + if (err) { + throw err; + } + }; - client.connect((err, client) => { - expect(err).to.not.exist; + await client.connect(); - const db = client.db(configuration.db); - let collection; - const docs = [ - { _id: 0, a: { b: 1, c: 0 } }, - { _id: 1, a: { b: 1, c: 0 } }, - { _id: 2, a: { b: 1, c: 0 } } - ]; - const resultSet = new Set(); - Promise.resolve() - .then(() => db.createCollection(collectionName)) - .then(() => (collection = db.collection(collectionName))) - .then(() => collection.insertMany(docs)) - .then(() => { - cursor = collection.find(); - return cursor.stream().map(transformFunc ?? (doc => doc)); - }) - .then(stream => { - stream.on('data', function (doc) { - resultSet.add(doc); - }); + const db = client.db(configuration.db); + const docs = [ + { _id: 0, a: { b: 1, c: 0 } }, + { _id: 1, a: { b: 1, c: 0 } }, + { _id: 2, a: { b: 1, c: 0 } } + ]; + const resultSet = new Set(); + await db.createCollection(collectionName); + const collection = await db.collection(collectionName); + await collection.insertMany(docs); + cursor = await collection.find(); + const stream = await cursor.stream().map(transformFunc ?? (doc => doc)); - stream.once('end', function () { - expect(resultSet).to.deep.equal(expectedSet); - done(); - }); + stream.on('data', function (doc) { + resultSet.add(doc); + }); - stream.once('error', e => { - done(e); - }); - }) - .catch(e => done(e)); + stream.once('end', function () { + expect(resultSet).to.deep.equal(expectedSet); + done(); }); + + stream.once('error', e => { + done(e); + }); + + const promise = once(stream, 'end'); + await promise; + await cursor.close(); + await client.close(); }; - it('stream should apply the supplied transformation function to each document in the stream', function (done) { + it('stream should apply the supplied transformation function to each document in the stream', async function () { const configuration = this.configuration; const client = configuration.newClient({ w: 1 }, { maxPoolSize: 1 }); const expectedDocs = [ @@ -3783,10 +3005,10 @@ describe('Cursor', function () { expectedSet: new Set(expectedDocs) }; - testTransformStream(config, done); + await testTransformStream(config); }); - it('stream should return a stream of unmodified docs if no transform function applied', function (done) { + it('stream should return a stream of unmodified docs if no transform function applied', async function () { const configuration = this.configuration; const client = configuration.newClient({ w: 1 }, { maxPoolSize: 1 }); const expectedDocs = [ @@ -3802,7 +3024,7 @@ describe('Cursor', function () { expectedSet: new Set(expectedDocs) }; - testTransformStream(config, done); + await testTransformStream(config); }); it.skip('should apply parent read preference to count command', function (done) { @@ -3841,107 +3063,93 @@ describe('Cursor', function () { }); }); - it('should not consume first document on hasNext when streaming', function (done) { + it('should not consume first document on hasNext when streaming', async function () { const configuration = this.configuration; const client = configuration.newClient({ w: 1 }, { maxPoolSize: 1 }); - client.connect(err => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const collection = client.db().collection('documents'); - collection.drop(() => { - const docs = [{ a: 1 }, { a: 2 }, { a: 3 }]; - collection.insertMany(docs, err => { - expect(err).to.not.exist; + const collection = client.db(configuration.db).collection('documents'); + const err = await collection.drop().catch(e => e); + expect(err).to.exist; - const cursor = collection.find({}, { sort: { a: 1 } }); - cursor.hasNext((err, hasNext) => { - expect(err).to.not.exist; - expect(hasNext).to.be.true; - - const collected = []; - const stream = new Writable({ - objectMode: true, - write: (chunk, encoding, next) => { - collected.push(chunk); - next(undefined, chunk); - } - }); + const docs = [{ a: 1 }, { a: 2 }, { a: 3 }]; + await collection.insertMany(docs); - const cursorStream = cursor.stream(); + const cursor = collection.find({}, { sort: { a: 1 } }); + const hasNext = await cursor.hasNext(); + expect(hasNext).to.be.true; - cursorStream.on('end', () => { - expect(collected).to.have.length(3); - expect(collected).to.eql(docs); - done(); - }); + const collected = []; + const stream = new Writable({ + objectMode: true, + write: (chunk, encoding, next) => { + collected.push(chunk); + next(undefined, chunk); + } + }); - cursorStream.pipe(stream); - }); - }); - }); + const cursorStream = cursor.stream(); + + cursorStream.on('end', () => { + expect(collected).to.have.length(3); + expect(collected).to.eql(docs); }); + + const promise = once(cursorStream, 'end'); + cursorStream.pipe(stream); + await promise; + await client.close(); }); describe('transforms', function () { - it('should correctly apply map transform to cursor as readable stream', function (done) { + it('should correctly apply map transform to cursor as readable stream', async function () { const configuration = this.configuration; const client = configuration.newClient(); - client.connect(err => { - expect(err).to.not.exist; - this.defer(() => client.close()); + await client.connect(); - const docs = 'Aaden Aaron Adrian Aditya Bob Joe'.split(' ').map(x => ({ name: x })); - const coll = client.db(configuration.db).collection('cursor_stream_mapping'); - coll.insertMany(docs, err => { - expect(err).to.not.exist; - - const bag = []; - const stream = coll - .find() - .project({ _id: 0, name: 1 }) - .map(doc => ({ mapped: doc })) - .stream() - .on('data', doc => bag.push(doc)); - - stream.on('error', done).on('end', () => { - expect(bag.map(x => x.mapped)).to.eql(docs.map(x => ({ name: x.name }))); - done(); - }); - }); - }); + const docs = 'Aaden Aaron Adrian Aditya Bob Joe'.split(' ').map(x => ({ name: x })); + const coll = client.db(configuration.db).collection('cursor_stream_mapping'); + await coll.insertMany(docs); + const bag = []; + const stream = coll + .find() + .project({ _id: 0, name: 1 }) + .map(doc => ({ mapped: doc })) + .stream() + .on('data', doc => bag.push(doc)); + + stream.on('error', () => expect.fail()); + stream.on('end', () => { + expect(bag.map(x => x.mapped)).to.eql(docs.map(x => ({ name: x.name }))); + }); + await once(stream, 'end'); + await client.close(); }); - it('should correctly apply map transform when converting cursor to array', function (done) { + it('should correctly apply map transform when converting cursor to array', async function () { const configuration = this.configuration; const client = configuration.newClient(); - client.connect(err => { - expect(err).to.not.exist; - this.defer(() => client.close()); - - const docs = 'Aaden Aaron Adrian Aditya Bob Joe'.split(' ').map(x => ({ name: x })); - const coll = client.db(configuration.db).collection('cursor_toArray_mapping'); - coll.insertMany(docs, err => { - expect(err).to.not.exist; - - coll - .find() - .project({ _id: 0, name: 1 }) - .map(doc => ({ mapped: doc })) - .toArray((err, mappedDocs) => { - expect(err).to.not.exist; - expect(mappedDocs.map(x => x.mapped)).to.eql(docs.map(x => ({ name: x.name }))); - done(); - }); - }); - }); + await client.connect(); + // this.defer(() => client.close()); + + const docs = 'Aaden Aaron Adrian Aditya Bob Joe'.split(' ').map(x => ({ name: x })); + const coll = client.db(configuration.db).collection('cursor_toArray_mapping'); + await coll.insertMany(docs); + + const mappedDocs = await coll + .find() + .project({ _id: 0, name: 1 }) + .map(doc => ({ mapped: doc })) + .toArray(); + expect(mappedDocs.map(x => x.mapped)).to.eql(docs.map(x => ({ name: x.name }))); + await client.close(); }); }); context('sort', function () { const findSort = (input, output) => - function (done) { + async function () { const client = this.configuration.newClient({ monitorCommands: true }); const events = []; client.on('commandStarted', event => { @@ -3952,16 +3160,14 @@ describe('Cursor', function () { const db = client.db('test'); const collection = db.collection('test_sort_dos'); const cursor = collection.find({}, { sort: input }); - cursor.next(err => { - expect(err).to.not.exist; - expect(events[0].command.sort).to.be.instanceOf(Map); - expect(Array.from(events[0].command.sort)).to.deep.equal(Array.from(output)); - client.close(done); - }); + await cursor.next(); + expect(events[0].command.sort).to.be.instanceOf(Map); + expect(Array.from(events[0].command.sort)).to.deep.equal(Array.from(output)); + await client.close(); }; const cursorSort = (input, output) => - function (done) { + async function () { const client = this.configuration.newClient({ monitorCommands: true }); const events = []; client.on('commandStarted', event => { @@ -3972,12 +3178,10 @@ describe('Cursor', function () { const db = client.db('test'); const collection = db.collection('test_sort_dos'); const cursor = collection.find({}).sort(input); - cursor.next(err => { - expect(err).to.not.exist; - expect(events[0].command.sort).to.be.instanceOf(Map); - expect(Array.from(events[0].command.sort)).to.deep.equal(Array.from(output)); - client.close(done); - }); + await cursor.next(); + expect(events[0].command.sort).to.be.instanceOf(Map); + expect(Array.from(events[0].command.sort)).to.deep.equal(Array.from(output)); + await client.close(); }; it('should use find options object', findSort({ alpha: 1 }, new Map([['alpha', 1]]))); From 02890da56631e695a56081b62bbd8ff0ff6e5baa Mon Sep 17 00:00:00 2001 From: Pavel Safronov Date: Tue, 21 Oct 2025 11:23:51 -0700 Subject: [PATCH 2/5] js to ts migration --- ...c_cursors.test.js => misc_cursors.test.ts} | 659 +++++++++--------- 1 file changed, 329 insertions(+), 330 deletions(-) rename test/integration/crud/{misc_cursors.test.js => misc_cursors.test.ts} (85%) diff --git a/test/integration/crud/misc_cursors.test.js b/test/integration/crud/misc_cursors.test.ts similarity index 85% rename from test/integration/crud/misc_cursors.test.js rename to test/integration/crud/misc_cursors.test.ts index 3408fb2db5..b5df299bd5 100644 --- a/test/integration/crud/misc_cursors.test.js +++ b/test/integration/crud/misc_cursors.test.ts @@ -1,19 +1,19 @@ -'use strict'; -const { assert: test, filterForCommands, setupDatabase } = require('../shared'); -const { runLater, sleep } = require('../../tools/utils'); -const fs = require('fs'); -const os = require('os'); -const path = require('path'); -const { expect } = require('chai'); -const BSON = require('bson'); -const sinon = require('sinon'); -const { Writable } = require('stream'); -const { once, on } = require('events'); -const { setTimeout } = require('timers'); -const { ReadPreference } = require('../../../src/read_preference'); -const { ServerType } = require('../../../src/sdam/common'); -const { MongoClientClosedError } = require('../../../src/error'); -const { formatSort } = require('../../../src/sort'); +import * as BSON from 'bson'; +import { expect } from 'chai'; +import { on, once } from 'events'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { Writable } from 'stream'; +import { setTimeout } from 'timers'; + +import { MongoClientClosedError } from '../../../src/error'; +import { type MongoClient } from '../../../src/mongo_client'; +import { ReadPreference } from '../../../src/read_preference'; +import { ServerType } from '../../../src/sdam/common'; +import { formatSort } from '../../../src/sort'; +import { runLater, sleep } from '../../tools/utils'; +import { assert as test, filterForCommands, setupDatabase } from '../shared'; describe('Cursor', function () { before(function () { @@ -24,10 +24,7 @@ describe('Cursor', function () { ]); }); - /** - * @type {import('../../../src/mongo_client').MongoClient} - */ - let client; + let client: MongoClient; beforeEach(async function () { client = this.configuration.newClient({ maxPoolSize: 1, monitorCommands: true }); @@ -75,9 +72,9 @@ describe('Cursor', function () { const db = client.db(configuration.db); const collection = await db.createCollection('close_on_next'); - await collection.insert([{ a: 1 }, { a: 1 }, { a: 1 }], configuration.writeConcernMax()); + await collection.insertMany([{ a: 1 }, { a: 1 }, { a: 1 }], configuration.writeConcernMax()); - var cursor = collection.find({}); + const cursor = collection.find({}); // this.defer(() => cursor.close()); cursor.batchSize(2); @@ -100,7 +97,7 @@ describe('Cursor', function () { const db = client.db(configuration.db); const collection = await db.createCollection('trigger_get_more'); - await collection.insert([{ a: 1 }, { a: 1 }, { a: 1 }], configuration.writeConcernMax()); + await collection.insertMany([{ a: 1 }, { a: 1 }, { a: 1 }], configuration.writeConcernMax()); const cursor = collection.find({}).batchSize(2); @@ -123,7 +120,7 @@ describe('Cursor', function () { const db = client.db(configuration.db); const collection = await db.createCollection('test_explain'); - await collection.insert({ a: 1 }, configuration.writeConcernMax()); + await collection.insertMany([{ a: 1 }], configuration.writeConcernMax()); const explanation = await collection.find({ a: 1 }).explain(); @@ -147,8 +144,8 @@ describe('Cursor', function () { await collection.find().count(); async function insert() { - for (var i = 0; i < 10; i++) { - await collection.insert({ x: i }, configuration.writeConcernMax()); + for (let i = 0; i < 10; i++) { + await collection.insertMany([{ x: i }], configuration.writeConcernMax()); } } @@ -167,7 +164,7 @@ describe('Cursor', function () { test.equal(0, count); - var cursor = collection.find(); + const cursor = collection.find(); count = await cursor.count(); test.equal(10, count); @@ -220,8 +217,8 @@ describe('Cursor', function () { await collection.find().count(); async function insert() { - for (var i = 0; i < 10; i++) { - await collection.insert({ x: i }, configuration.writeConcernMax()); + for (let i = 0; i < 10; i++) { + await collection.insertOne({ x: i }, configuration.writeConcernMax()); } } @@ -239,7 +236,7 @@ describe('Cursor', function () { count = await db.collection('acollectionthatdoesn').count(); test.equal(0, count); - var cursor = collection.find(); + const cursor = collection.find(); count = await cursor.count(); test.equal(10, count); @@ -268,8 +265,8 @@ describe('Cursor', function () { const db = client.db(configuration.db); const collection = await db.createCollection('test_each'); async function insert() { - for (var i = 0; i < 10; i++) { - await collection.insert({ x: i }, configuration.writeConcernMax()); + for (let i = 0; i < 10; i++) { + await collection.insertOne({ x: i }, configuration.writeConcernMax()); } } @@ -302,8 +299,8 @@ describe('Cursor', function () { const collection = await db.createCollection('test_cursor_limit'); async function insert() { - for (var i = 0; i < 10; i++) { - await collection.insert({ x: i }, configuration.writeConcernMax()); + for (let i = 0; i < 10; i++) { + await collection.insertOne({ x: i }, configuration.writeConcernMax()); } } @@ -331,8 +328,8 @@ describe('Cursor', function () { const collection = await db.createCollection('test_cursor_negative_one_limit'); async function insert() { - for (var i = 0; i < 10; i++) { - await collection.insert({ x: i }, configuration.writeConcernMax()); + for (let i = 0; i < 10; i++) { + await collection.insertOne({ x: i }, configuration.writeConcernMax()); } } @@ -361,8 +358,8 @@ describe('Cursor', function () { const collection = await db.createCollection('test_cursor_any_negative_limit'); async function insert() { - for (var i = 0; i < 10; i++) { - await collection.insert({ x: i }, configuration.writeConcernMax()); + for (let i = 0; i < 10; i++) { + await collection.insertOne({ x: i }, configuration.writeConcernMax()); } } @@ -389,13 +386,13 @@ describe('Cursor', function () { const db = client.db(configuration.db); const collection = await db.createCollection('test_limit_exceptions_2'); - await collection.insert({ a: 1 }, configuration.writeConcernMax()); + await collection.insertOne({ a: 1 }, configuration.writeConcernMax()); const cursor = collection.find(); // this.defer(() => cursor.close()); try { - cursor.limit('not-an-integer'); + cursor.limit('not-an-integer' as any); } catch (err) { test.equal('Operation "limit" requires an integer', err.message); } @@ -418,7 +415,7 @@ describe('Cursor', function () { const db = client.db(configuration.db); const collection = await db.createCollection('test_limit_exceptions'); - await collection.insert({ a: 1 }, configuration.writeConcernMax()); + await collection.insertOne({ a: 1 }, configuration.writeConcernMax()); const cursor = collection.find(); // this.defer(() => cursor.close()); @@ -445,7 +442,7 @@ describe('Cursor', function () { const db = client.db(configuration.db); const collection = await db.createCollection('test_limit_exceptions_1'); - await collection.insert({ a: 1 }, configuration.writeConcernMax()); + await collection.insertOne({ a: 1 }, configuration.writeConcernMax()); const cursor = collection.find(); await cursor.close(); @@ -470,8 +467,8 @@ describe('Cursor', function () { const collection = await db.createCollection('test_skip'); const insert = async () => { - for (var i = 0; i < 10; i++) { - await collection.insert({ x: i }, configuration.writeConcernMax()); + for (let i = 0; i < 10; i++) { + await collection.insertOne({ x: i }, configuration.writeConcernMax()); } }; @@ -479,7 +476,7 @@ describe('Cursor', function () { const cursor = collection.find(); // this.defer(() => cursor.close()); - let count = await cursor.count(); + const count = await cursor.count(); test.equal(10, count); const cursor2 = collection.find(); @@ -492,10 +489,10 @@ describe('Cursor', function () { test.equal(8, items2.length); // Check that we have the same elements - var numberEqual = 0; - var sliced = items.slice(2, 10); + let numberEqual = 0; + const sliced = items.slice(2, 10); - for (var i = 0; i < sliced.length; i++) { + for (let i = 0; i < sliced.length; i++) { if (sliced[i].x === items2[i].x) numberEqual = numberEqual + 1; } @@ -519,10 +516,10 @@ describe('Cursor', function () { const db = client.db(configuration.db); const collection = await db.createCollection('test_skip_exceptions'); - await collection.insert({ a: 1 }, configuration.writeConcernMax()); + await collection.insertOne({ a: 1 }, configuration.writeConcernMax()); try { - collection.find().skip('not-an-integer'); + collection.find().skip('not-an-integer' as any); } catch (err) { test.equal('Operation "skip" requires an integer', err.message); } @@ -558,11 +555,11 @@ describe('Cursor', function () { const db = client.db(configuration.db); const collection = await db.createCollection('test_batchSize_exceptions'); - await collection.insert({ a: 1 }, configuration.writeConcernMax()); + await collection.insertOne({ a: 1 }, configuration.writeConcernMax()); let cursor = collection.find(); try { - cursor.batchSize('not-an-integer'); + cursor.batchSize('not-an-integer' as any); test.ok(false); } catch (err) { test.equal('Operation "batchSize" requires an integer', err.message); @@ -603,14 +600,14 @@ describe('Cursor', function () { const collection = await db.createCollection('test_multiple_batch_size'); //test with the last batch that is a multiple of batchSize - var records = 4; - var batchSize = 2; - var docs = []; - for (var i = 0; i < records; i++) { + const records = 4; + const batchSize = 2; + const docs = []; + for (let i = 0; i < records; i++) { docs.push({ a: i }); } - await collection.insert(docs, configuration.writeConcernMax()); + await collection.insertMany(docs, configuration.writeConcernMax()); const cursor = collection.find({}, { batchSize: batchSize }); @@ -655,17 +652,17 @@ describe('Cursor', function () { const db = client.db(configuration.db); const collection = await db.createCollection('test_limit_greater_than_batch_size'); - var limit = 4; - var records = 10; - var batchSize = 3; - var docs = []; - for (var i = 0; i < records; i++) { + const limit = 4; + const records = 10; + const batchSize = 3; + const docs = []; + for (let i = 0; i < records; i++) { docs.push({ a: i }); } - await collection.insert(docs, configuration.writeConcernMax()); + await collection.insertMany(docs, configuration.writeConcernMax()); - var cursor = collection.find({}, { batchSize: batchSize, limit: limit }); + const cursor = collection.find({}, { batchSize: batchSize, limit: limit }); //1st await cursor.next(); test.equal(2, cursor.bufferedCount()); @@ -702,17 +699,17 @@ describe('Cursor', function () { const db = client.db(configuration.db); const collection = await db.createCollection('test_limit_less_than_batch_size'); - var limit = 2; - var records = 10; - var batchSize = 4; - var docs = []; - for (var i = 0; i < records; i++) { + const limit = 2; + const records = 10; + const batchSize = 4; + const docs = []; + for (let i = 0; i < records; i++) { docs.push({ a: i }); } - await collection.insert(docs, configuration.writeConcernMax()); + await collection.insertMany(docs, configuration.writeConcernMax()); - var cursor = collection.find({}, { batchSize: batchSize, limit: limit }); + const cursor = collection.find({}, { batchSize: batchSize, limit: limit }); //1st await cursor.next(); test.equal(1, cursor.bufferedCount()); @@ -741,11 +738,11 @@ describe('Cursor', function () { await client.connect(); const db = client.db(configuration.db); - var collection = db.collection('shouldHandleSkipLimitChaining'); + const collection = db.collection('shouldHandleSkipLimitChaining'); async function insert() { - for (var i = 0; i < 10; i++) { - await collection.insert({ x: i }, configuration.writeConcernMax()); + for (let i = 0; i < 10; i++) { + await collection.insertOne({ x: i }, configuration.writeConcernMax()); } } @@ -757,10 +754,10 @@ describe('Cursor', function () { test.equal(5, items2.length); // Check that we have the same elements - var numberEqual = 0; - var sliced = items.slice(3, 8); + let numberEqual = 0; + const sliced = items.slice(3, 8); - for (var i = 0; i < sliced.length; i++) { + for (let i = 0; i < sliced.length; i++) { if (sliced[i].x === items2[i].x) numberEqual = numberEqual + 1; } test.equal(5, numberEqual); @@ -785,8 +782,8 @@ describe('Cursor', function () { const collection = await db.createCollection('test_limit_skip_chaining_inline'); async function insert() { - for (var i = 0; i < 10; i++) { - await collection.insert({ x: i }, configuration.writeConcernMax()); + for (let i = 0; i < 10; i++) { + await collection.insertOne({ x: i }, configuration.writeConcernMax()); } } @@ -798,10 +795,10 @@ describe('Cursor', function () { test.equal(5, items2.length); // Check that we have the same elements - var numberEqual = 0; - var sliced = items.slice(3, 8); + let numberEqual = 0; + const sliced = items.slice(3, 8); - for (var i = 0; i < sliced.length; i++) { + for (let i = 0; i < sliced.length; i++) { if (sliced[i].x === items2[i].x) numberEqual = numberEqual + 1; } test.equal(5, numberEqual); @@ -840,7 +837,7 @@ describe('Cursor', function () { }, test: async function () { - var COUNT = 1000; + const COUNT = 1000; const configuration = this.configuration; await client.connect(); @@ -849,9 +846,9 @@ describe('Cursor', function () { const collection = await db.createCollection('test_refill_via_get_more'); async function insert() { - var docs = []; + const docs = []; - for (var i = 0; i < COUNT; i++) { + for (let i = 0; i < COUNT; i++) { docs.push({ a: i }); } @@ -862,7 +859,7 @@ describe('Cursor', function () { let count = await collection.count(); test.equal(COUNT, count); - var total = 0; + let total = 0; await collection.find({}, {}).forEach(item => { total = total + item.a; }); @@ -875,7 +872,7 @@ describe('Cursor', function () { count = await collection.count(); test.equal(COUNT, count); - var total2 = 0; + let total2 = 0; await collection.find().forEach(item => { total2 = total2 + item.a; }); @@ -905,12 +902,12 @@ describe('Cursor', function () { const db = client.db(configuration.db); const collection = await db.createCollection('test_refill_via_get_more_alt_coll'); - var COUNT = 1000; + const COUNT = 1000; async function insert() { - var docs = []; + const docs = []; - for (var i = 0; i < COUNT; i++) { + for (let i = 0; i < COUNT; i++) { docs.push({ a: i }); } @@ -921,7 +918,7 @@ describe('Cursor', function () { let count = await collection.count(); test.equal(1000, count); - var total = 0; + let total = 0; await collection.find().forEach(doc => { total = total + doc.a; }); @@ -934,7 +931,7 @@ describe('Cursor', function () { count = await collection.count(); test.equal(1000, count); - var total2 = 0; + let total2 = 0; await collection.find().forEach(doc => { total2 = total2 + doc.a; }); @@ -965,7 +962,7 @@ describe('Cursor', function () { const db = client.db(configuration.db); const collection = await db.createCollection('test_close_after_query_sent'); - await collection.insert({ a: 1 }, configuration.writeConcernMax()); + await collection.insertOne({ a: 1 }, configuration.writeConcernMax()); const cursor = collection.find({ a: 1 }); await cursor.next(); @@ -1030,10 +1027,10 @@ describe('Cursor', function () { }, test: async function () { - var docs = []; + const docs = []; - for (var i = 0; i < 1000; i++) { - var d = new Date().getTime() + i * 1000; + for (let i = 0; i < 1000; i++) { + const d = new Date().getTime() + i * 1000; docs[i] = { a: i, createdAt: new Date(d) }; } @@ -1044,7 +1041,7 @@ describe('Cursor', function () { const collection = await db.createCollection('Should_correctly_execute_count_on_cursor_1'); // insert all docs - await collection.insert(docs, configuration.writeConcernMax()); + await collection.insertMany(docs, configuration.writeConcernMax()); let total = 0; // Create a cursor for the content @@ -1065,7 +1062,7 @@ describe('Cursor', function () { it('does not auto destroy streams', async function () { const docs = []; - for (var i = 0; i < 10; i++) { + for (let i = 0; i < 10; i++) { docs.push({ a: i + 1 }); } @@ -1100,13 +1097,13 @@ describe('Cursor', function () { }, test: async function () { - var docs = []; + const docs = []; - for (var n = 0; n < 1000; n++) { + for (let n = 0; n < 1000; n++) { docs[n] = { a: n + 1 }; } - var count = 0; + let count = 0; const configuration = this.configuration; await client.connect(); @@ -1115,9 +1112,9 @@ describe('Cursor', function () { const collection = await db.createCollection('Should_be_able_to_stream_documents'); // insert all docs - await collection.insert(docs, configuration.writeConcernMax()); + await collection.insertMany(docs, configuration.writeConcernMax()); - var paused = 0, + let paused = 0, closed = 0, resumed = 0, i = 0, @@ -1181,8 +1178,8 @@ describe('Cursor', function () { }, test: async function () { - var i = 0, - docs = [{ b: 2 }, { b: 3 }], + const docs = [{ b: 2 }, { b: 3 }]; + let i = 0, doneCalled = 0; const configuration = this.configuration; @@ -1269,7 +1266,7 @@ describe('Cursor', function () { const dataEvents = on(stream, 'data'); for (let i = 0; i < 5; i++) { - let { + const { value: [doc] } = await dataEvents.next(); expect(doc).property('b', i + 1); @@ -1288,66 +1285,66 @@ describe('Cursor', function () { }); // NOTE: skipped for use of topology manager - it.skip('cursor stream errors', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { requires: { topology: ['single'] } }, - - test: function (done) { - const configuration = this.configuration; - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); - - const db = client.db(configuration.db); - db.createCollection('cursor_stream_errors', (err, collection) => { - expect(err).to.not.exist; - - var docs = []; - for (var ii = 0; ii < 10; ++ii) docs.push({ b: ii + 1 }); - - // insert all docs - collection.insert(docs, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; - - var finished = 0, - i = 0; - - const cursor = collection.find({}, { batchSize: 5 }); - const stream = cursor.stream(); - - stream.on('data', function () { - if (++i === 4) { - // Force restart - configuration.manager.stop(9); - } - }); - - stream.once('close', testDone('close')); - stream.once('error', testDone('error')); - - function testDone() { - return function () { - ++finished; - - if (finished === 2) { - setTimeout(function () { - test.equal(5, i); - test.equal(true, cursor.closed); - client.close(); - - configuration.manager.start().then(function () { - done(); - }); - }, 150); - } - }; - } - }); - }); - }); - } - }); + // it.skip('cursor stream errors', { + // // Add a tag that our runner can trigger on + // // in this case we are setting that node needs to be higher than 0.10.X to run + // metadata: { requires: { topology: ['single'] } }, + + // test: function (done) { + // const configuration = this.configuration; + // client.connect((err, client) => { + // expect(err).to.not.exist; + // this.defer(() => client.close()); + + // const db = client.db(configuration.db); + // db.createCollection('cursor_stream_errors', (err, collection) => { + // expect(err).to.not.exist; + + // const docs = []; + // for (let ii = 0; ii < 10; ++ii) docs.push({ b: ii + 1 }); + + // // insert all docs + // collection.insert(docs, configuration.writeConcernMax(), err => { + // expect(err).to.not.exist; + + // let finished = 0, + // i = 0; + + // const cursor = collection.find({}, { batchSize: 5 }); + // const stream = cursor.stream(); + + // stream.on('data', function () { + // if (++i === 4) { + // // Force restart + // configuration.manager.stop(9); + // } + // }); + + // stream.once('close', testDone('close')); + // stream.once('error', testDone('error')); + + // function testDone() { + // return function () { + // ++finished; + + // if (finished === 2) { + // setTimeout(function () { + // test.equal(5, i); + // test.equal(true, cursor.closed); + // client.close(); + + // configuration.manager.start().then(function () { + // done(); + // }); + // }, 150); + // } + // }; + // } + // }); + // }); + // }); + // } + // }); it('cursor stream pipe', { // Add a tag that our runner can trigger on @@ -1363,7 +1360,7 @@ describe('Cursor', function () { const db = client.db(configuration.db); const collection = await db.createCollection('cursor_stream_pipe'); - var docs = []; + const docs = []; 'Aaden Aaron Adrian Aditya Bob Joe'.split(' ').forEach(function (name) { docs.push({ name: name }); }); @@ -1373,16 +1370,19 @@ describe('Cursor', function () { const filename = path.join(os.tmpdir(), '_nodemongodbnative_stream_out.txt'); const out = fs.createWriteStream(filename); - const stream = collection.find().stream().map(JSON.stringify); + const stream = collection + .find() + .stream() + .map(d => JSON.stringify(d)); stream.pipe(out); // Wait for output stream to close - out.on('close', testDone); + out.on('close', () => testDone(undefined)); function testDone(err) { // Object.prototype.toString = toString; test.strictEqual(undefined, err); - var contents = fs.readFileSync(filename, 'utf8'); + const contents = fs.readFileSync(filename, 'utf8'); test.ok(/Aaden/.test(contents)); test.ok(/Aaron/.test(contents)); test.ok(/Adrian/.test(contents)); @@ -1527,10 +1527,10 @@ describe('Cursor', function () { const options = { capped: true, size: 8 }; const collection = await db.createCollection('should_await_data', options); - await collection.insert({ a: 1 }, configuration.writeConcernMax()); + await collection.insertOne({ a: 1 }, configuration.writeConcernMax()); // Create cursor with awaitData, and timeout after the period specified - var cursor = collection.find({}, { tailable: true, awaitData: true }); + const cursor = collection.find({}, { tailable: true, awaitData: true }); await cursor.forEach(() => cursor.kill()); await cursor.close(); } @@ -1544,7 +1544,7 @@ describe('Cursor', function () { }, test: async function () { - var docs = []; + const docs = []; docs[0] = { _keywords: [ 'compact', @@ -1726,16 +1726,16 @@ describe('Cursor', function () { const db = client.db(configuration.db); // Insert all the docs - var collection = db.collection('shouldCorrectExecuteExplainHonoringLimit'); - await collection.insert(docs, configuration.writeConcernMax()); + const collection = db.collection('shouldCorrectExecuteExplainHonoringLimit'); + await collection.insertMany(docs, configuration.writeConcernMax()); - await collection.createIndex({ _keywords: 1 }, configuration.writeConcernMax()); + await collection.createIndex({ _keywords: 1 }); - let result = await collection.find({ _keywords: 'red' }).limit(10).toArray(); + const result = await collection.find({ _keywords: 'red' }).limit(10).toArray(); test.ok(result != null); - result = await collection.find({ _keywords: 'red' }, {}).limit(10).explain(); - test.ok(result != null); + const result2 = await collection.find({ _keywords: 'red' }, {}).limit(10).explain(); + test.ok(result2 != null); } }); @@ -1747,14 +1747,14 @@ describe('Cursor', function () { }, test: async function () { - var doc = { name: 'camera', _keywords: ['compact', 'ii2gd', 'led', 'red', 'aet'] }; + const doc = { name: 'camera', _keywords: ['compact', 'ii2gd', 'led', 'red', 'aet'] }; const configuration = this.configuration; await client.connect(); const db = client.db(configuration.db); - var collection = db.collection('shouldNotExplainWhenFalse'); - await collection.insert(doc, configuration.writeConcernMax()); + const collection = db.collection('shouldNotExplainWhenFalse'); + await collection.insertOne(doc, configuration.writeConcernMax()); const result = await collection.find({ _keywords: 'red' }).limit(10).toArray(); test.equal('camera', result[0].name); @@ -1777,7 +1777,7 @@ describe('Cursor', function () { await db .collection('shouldFailToSetReadPreferenceOnCursor') .find() - .withReadPreference('notsecondary'); + .withReadPreference('notsecondary' as any); test.ok(false); } catch (err) { } // eslint-disable-line @@ -1825,25 +1825,25 @@ describe('Cursor', function () { const db = client.db(configuration.db); const collection = await db.createCollection('shouldNotFailDueToStackOverflowEach'); - var docs = []; - var total = 0; - for (var i = 0; i < 30000; i++) docs.push({ a: i }); - var allDocs = []; - var left = 0; + const docs = []; + let total = 0; + for (let i = 0; i < 30000; i++) docs.push({ a: i }); + const allDocs = []; + let left = 0; while (docs.length > 0) { allDocs.push(docs.splice(0, 1000)); } // Get all batches we must insert left = allDocs.length; - var totalI = 0; + let totalI = 0; // Execute inserts - for (i = 0; i < left; i++) { - const d = await collection.insert(allDocs.shift(), configuration.writeConcernMax()); + for (let i = 0; i < left; i++) { + const d = await collection.insertMany(allDocs.shift(), configuration.writeConcernMax()); left = left - 1; - totalI = totalI + d.length; + totalI = totalI + d.insertedCount; if (left === 0) { await collection.find({}).forEach(() => { @@ -1860,25 +1860,25 @@ describe('Cursor', function () { const db = client.db(configuration.db); const collection = await db.createCollection('shouldNotFailDueToStackOverflowToArray'); - var docs = Array.from({ length: 30000 }, (_, i) => ({ a: i })); - var allDocs = []; - var left = 0; + const docs = Array.from({ length: 30000 }, (_, i) => ({ a: i })); + const allDocs = []; + let left = 0; while (docs.length > 0) { allDocs.push(docs.splice(0, 1000)); } // Get all batches we must insert left = allDocs.length; - var totalI = 0; - var timeout = 0; + let totalI = 0; + let timeout = 0; // Execute inserts for (let i = 0; i < left; i++) { await sleep(timeout); - const d = await collection.insert(allDocs.shift()); + const d = await collection.insertMany(allDocs.shift()); left = left - 1; - totalI = totalI + d.length; + totalI = totalI + d.insertedCount; if (left === 0) { const items = await collection.find({}).toArray(); @@ -1895,11 +1895,11 @@ describe('Cursor', function () { await client.connect(); const db = client.db(configuration.db); - var collection = db.collection('shouldCorrectlySkipAndLimit'); - var docs = []; - for (var i = 0; i < 100; i++) docs.push({ a: i, OrderNumber: i }); + const collection = db.collection('shouldCorrectlySkipAndLimit'); + const docs = []; + for (let i = 0; i < 100; i++) docs.push({ a: i, OrderNumber: i }); - await collection.insert(docs, configuration.writeConcernMax()); + await collection.insertMany(docs, configuration.writeConcernMax()); const items = await collection.find({}, { OrderNumber: 1 }).skip(10).limit(10).toArray(); @@ -1916,11 +1916,11 @@ describe('Cursor', function () { await client.connect(); const db = client.db(configuration.db); - var collection = db.collection('shouldFailToTailANormalCollection'); - var docs = []; - for (var i = 0; i < 100; i++) docs.push({ a: i, OrderNumber: i }); + const collection = db.collection('shouldFailToTailANormalCollection'); + const docs = []; + for (let i = 0; i < 100; i++) docs.push({ a: i, OrderNumber: i }); - await collection.insert(docs, configuration.writeConcernMax()); + await collection.insertMany(docs, configuration.writeConcernMax()); const cursor = collection.find({}, { tailable: true }); const err = await cursor.forEach(() => { }).catch(e => e); @@ -1949,8 +1949,8 @@ describe('Cursor', function () { const db = client.db(configuration.db); // Create a lot of documents to insert - var docs = []; - for (var i = 0; i < 100; i++) { + const docs = []; + for (let i = 0; i < 100; i++) { docs.push({ a: i }); } @@ -1958,7 +1958,7 @@ describe('Cursor', function () { const collection = await db.createCollection('test_close_function_on_cursor_2'); // Insert documents into collection - await collection.insert(docs, configuration.writeConcernMax()); + await collection.insertMany(docs, configuration.writeConcernMax()); const cursor = collection.find({}); @@ -1987,9 +1987,9 @@ describe('Cursor', function () { await client.connect(); const db = client.db(configuration.db); - var col = db.collection('count_hint'); + const col = db.collection('count_hint'); - await col.insert([{ i: 1 }, { i: 2 }], { writeConcern: { w: 1 } }); + await col.insertMany([{ i: 1 }, { i: 2 }], { writeConcern: { w: 1 } }); await col.createIndex({ i: 1 }); @@ -2030,8 +2030,8 @@ describe('Cursor', function () { const db = client.db(configuration.db); // Create a lot of documents to insert - var docs = []; - for (var i = 0; i < 100; i++) { + const docs = []; + for (let i = 0; i < 100; i++) { docs.push({ a: i }); } @@ -2039,8 +2039,8 @@ describe('Cursor', function () { const collection = await db.createCollection('terminate_each_returning_false'); // Insert documents into collection - await collection.insert(docs, configuration.writeConcernMax()); - var finished = false; + await collection.insertMany(docs, configuration.writeConcernMax()); + let finished = false; await collection.find({}).forEach(doc => { expect(doc).to.exist; @@ -2064,14 +2064,14 @@ describe('Cursor', function () { await client.connect(); const db = client.db(configuration.db); - var donkey = { + const donkey = { color: 'brown' }; const result = await db.collection('donkies').insertOne(donkey); - var query = { _id: result.insertedId }; - var options = { maxTimeMS: 1000 }; + const query = { _id: result.insertedId }; + const options = { maxTimeMS: 1000 }; const doc = await db.collection('donkies').findOne(query, options); @@ -2092,7 +2092,7 @@ describe('Cursor', function () { const db = client.db(configuration.db); const collectionName = 'should_correctly_handle_batchSize_2'; - await db.collection(collectionName).insert([{ x: 1 }, { x: 2 }, { x: 3 }]); + await db.collection(collectionName).insertMany([{ x: 1 }, { x: 2 }, { x: 3 }]); const cursor = db.collection(collectionName).find({}, { batchSize: 2 }); // this.defer(() => cursor.close()); @@ -2129,10 +2129,10 @@ describe('Cursor', function () { }, test: async function () { - var docs = []; + const docs = []; - for (var i = 0; i < 1000; i++) { - var d = new Date().getTime() + i * 1000; + for (let i = 0; i < 1000; i++) { + const d = new Date().getTime() + i * 1000; docs[i] = { a: i, createdAt: new Date(d) }; } @@ -2143,10 +2143,10 @@ describe('Cursor', function () { const collection = await db.createCollection('Should_correctly_execute_count_on_cursor_2'); // insert all docs - await collection.insert(docs, configuration.writeConcernMax()); + await collection.insertMany(docs, configuration.writeConcernMax()); // Create a cursor for the content - var cursor = collection.find({}); + let cursor = collection.find({}); cursor.limit(100); cursor.skip(10); await cursor.count({ maxTimeMS: 1000 }); @@ -2169,10 +2169,10 @@ describe('Cursor', function () { }, test: async function () { - var docs = []; + const docs = []; - for (var i = 0; i < 1000; i++) { - var d = new Date().getTime() + i * 1000; + for (let i = 0; i < 1000; i++) { + const d = new Date().getTime() + i * 1000; docs[i] = { a: i, createdAt: new Date(d) }; } @@ -2183,10 +2183,10 @@ describe('Cursor', function () { const collection = await db.createCollection('Should_correctly_execute_count_on_cursor_3'); // insert all docs - await collection.insert(docs, configuration.writeConcernMax()); + await collection.insertMany(docs, configuration.writeConcernMax()); // Create a cursor for the content - var cursor = collection.find({}, { maxTimeMS: 100 }); + const cursor = collection.find({}, { maxTimeMS: 100 }); await cursor.toArray(); } }); @@ -2199,10 +2199,10 @@ describe('Cursor', function () { }, test: async function () { - var docs = []; + const docs = []; - for (var i = 0; i < 1000; i++) { - var d = new Date().getTime() + i * 1000; + for (let i = 0; i < 1000; i++) { + const d = new Date().getTime() + i * 1000; docs[i] = { a: i, createdAt: new Date(d) }; } @@ -2210,13 +2210,13 @@ describe('Cursor', function () { await client.connect(); const db = client.db(configuration.db); - var collection = db.collection('map_toArray'); + const collection = db.collection('map_toArray'); // insert all docs - await collection.insert(docs, configuration.writeConcernMax()); + await collection.insertMany(docs, configuration.writeConcernMax()); // Create a cursor for the content - var cursor = collection + const cursor = collection .find({}) .map(function () { return { a: 1 }; @@ -2243,7 +2243,7 @@ describe('Cursor', function () { test: async function () { const docs = []; - for (var i = 0; i < 1000; i++) { + for (let i = 0; i < 1000; i++) { const d = new Date().getTime() + i * 1000; docs[i] = { a: i, createdAt: new Date(d) }; } @@ -2255,7 +2255,7 @@ describe('Cursor', function () { const collection = db.collection('map_next'); // insert all docs - await collection.insert(docs, configuration.writeConcernMax()); + await collection.insertMany(docs, configuration.writeConcernMax()); // Create a cursor for the content const cursor = collection @@ -2280,10 +2280,10 @@ describe('Cursor', function () { }, test: async function () { - var docs = []; + const docs = []; - for (var i = 0; i < 1000; i++) { - var d = new Date().getTime() + i * 1000; + for (let i = 0; i < 1000; i++) { + const d = new Date().getTime() + i * 1000; docs[i] = { a: i, createdAt: new Date(d) }; } @@ -2294,10 +2294,10 @@ describe('Cursor', function () { const collection = db.collection('map_each'); // insert all docs - await collection.insert(docs, configuration.writeConcernMax()); + await collection.insertMany(docs, configuration.writeConcernMax()); // Create a cursor for the content - var cursor = collection + const cursor = collection .find({}) .map(function () { return { a: 1 }; @@ -2319,10 +2319,10 @@ describe('Cursor', function () { }, test: async function () { - var docs = []; + const docs = []; - for (var i = 0; i < 1000; i++) { - var d = new Date().getTime() + i * 1000; + for (let i = 0; i < 1000; i++) { + const d = new Date().getTime() + i * 1000; docs[i] = { a: i, createdAt: new Date(d) }; } @@ -2330,13 +2330,13 @@ describe('Cursor', function () { await client.connect(); const db = client.db(configuration.db); - var collection = db.collection('map_forEach'); + const collection = db.collection('map_forEach'); // insert all docs - await collection.insert(docs, configuration.writeConcernMax()); + await collection.insertMany(docs, configuration.writeConcernMax()); // Create a cursor for the content - var cursor = collection + const cursor = collection .find({}) .map(function () { return { a: 2 }; @@ -2362,10 +2362,10 @@ describe('Cursor', function () { }, test: async function () { - var docs = []; + const docs = []; - for (var i = 0; i < 1000; i++) { - var d = new Date().getTime() + i * 1000; + for (let i = 0; i < 1000; i++) { + const d = new Date().getTime() + i * 1000; docs[i] = { a: i, createdAt: new Date(d) }; } @@ -2373,13 +2373,13 @@ describe('Cursor', function () { await client.connect(); const db = client.db(configuration.db); - var collection = db.collection('map_mapmapforEach'); + const collection = db.collection('map_mapmapforEach'); // insert all docs - await collection.insert(docs, configuration.writeConcernMax()); + await collection.insertMany(docs, configuration.writeConcernMax()); // Create a cursor for the content - var cursor = collection + const cursor = collection .find({}) .map(function () { return { a: 1 }; @@ -2404,12 +2404,12 @@ describe('Cursor', function () { await client.connect(); const db = client.db(configuration.db); - var collection = db.collection('cursor_limit_skip_correctly'); + const collection = db.collection('cursor_limit_skip_correctly'); // Insert x number of docs - var ordered = collection.initializeUnorderedBulkOp(); + const ordered = collection.initializeUnorderedBulkOp(); - for (var i = 0; i < 6000; i++) { + for (let i = 0; i < 6000; i++) { ordered.insert({ a: i }); } @@ -2432,13 +2432,13 @@ describe('Cursor', function () { await client.connect(); const db = client.db(configuration.db); - var options = { capped: true, size: 8 }; + const options = { capped: true, size: 8 }; const collection = await db.createCollection('should_await_data_max_awaittime_ms', options); - await collection.insert({ a: 1 }, configuration.writeConcernMax()); + await collection.insertOne({ a: 1 }, configuration.writeConcernMax()); // Create cursor with awaitData, and timeout after the period specified - var cursor = collection + const cursor = collection .find({}) .addCursorFlag('tailable', true) .addCursorFlag('awaitData', true) @@ -2468,19 +2468,19 @@ describe('Cursor', function () { await client.connect(); const db = client.db(configuration.db); - var collection = db.collection('cursor_limit_skip_correctly'); + const collection = db.collection('cursor_limit_skip_correctly'); // Insert x number of docs - var ordered = collection.initializeUnorderedBulkOp(); + const ordered = collection.initializeUnorderedBulkOp(); - for (var i = 0; i < 100; i++) { + for (let i = 0; i < 100; i++) { ordered.insert({ a: i }); } await ordered.execute({ writeConcern: { w: 1 } }); // Let's attempt to skip and limit - var cursor = collection.find({}).batchSize(10); + const cursor = collection.find({}).batchSize(10); const stream = cursor.stream(); stream.on('data', function () { stream.destroy(); @@ -2500,10 +2500,10 @@ describe('Cursor', function () { }, test: async function () { - var docs = []; + const docs = []; - for (var i = 0; i < 1; i++) { - var d = new Date().getTime() + i * 1000; + for (let i = 0; i < 1; i++) { + const d = new Date().getTime() + i * 1000; docs[i] = { createdAt: new Date(d) }; } @@ -2519,7 +2519,7 @@ describe('Cursor', function () { await collection.createIndex({ createdAt: 1 }); // insert all docs - await collection.insert(docs, configuration.writeConcernMax()); + await collection.insertMany(docs, configuration.writeConcernMax()); // Find with sort const items = await collection.find().sort(['createdAt', 'asc']).toArray(); @@ -2536,10 +2536,10 @@ describe('Cursor', function () { }, test: async function () { - var docs = []; + const docs = []; - for (var i = 0; i < 50; i++) { - var d = new Date().getTime() + i * 1000; + for (let i = 0; i < 50; i++) { + const d = new Date().getTime() + i * 1000; docs[i] = { a: i, createdAt: new Date(d) }; } @@ -2550,11 +2550,11 @@ describe('Cursor', function () { const collection = await db.createCollection('negative_batch_size_and_limit_set'); // insert all docs - await collection.insert(docs, configuration.writeConcernMax()); + await collection.insertMany(docs, configuration.writeConcernMax()); // Create a cursor for the content - var cursor = collection.find({}); - var c = await cursor.limit(100).skip(0).count(); + let cursor = collection.find({}); + let c = await cursor.limit(100).skip(0).count(); test.equal(50, c); cursor = collection.find({}); @@ -2571,11 +2571,11 @@ describe('Cursor', function () { }, test: async function () { - var docs = []; + const docs = []; const configuration = this.configuration; - for (var i = 0; i < 50; i++) { - var d = new Date().getTime() + i * 1000; + for (let i = 0; i < 50; i++) { + const d = new Date().getTime() + i * 1000; docs[i] = { a: i, createdAt: new Date(d) }; } @@ -2584,10 +2584,10 @@ describe('Cursor', function () { const collection = await db.createCollection('Should_correctly_execute_count_on_cursor_1_'); // insert all docs - await collection.insert(docs, configuration.writeConcernMax()); + await collection.insertMany(docs, configuration.writeConcernMax()); // Create a cursor for the content - var cursor = collection.find({}); + const cursor = collection.find({}); await cursor.batchSize(-10).next(); test.ok(cursor.id.equals(BSON.Long.ZERO)); } @@ -2601,7 +2601,7 @@ describe('Cursor', function () { }, test: async function () { - var started = []; + const started = []; const configuration = this.configuration; const client = configuration.newClient(configuration.writeConcernMax(), { maxPoolSize: 1, @@ -2642,7 +2642,7 @@ describe('Cursor', function () { }, test: async function () { - var started = []; + const started = []; const configuration = this.configuration; client.on('commandStarted', function (event) { @@ -2694,7 +2694,7 @@ describe('Cursor', function () { const configuration = this.configuration; - let cleanup = () => { }; + const cleanup = () => { }; let caughtError = undefined; return ( @@ -2706,7 +2706,7 @@ describe('Cursor', function () { const collection = db.collection('cursorkilltest1'); // Insert 1000 documents - return collection.insert(docs).then(() => { + return collection.insertMany(docs).then(() => { // Generate cursor for find operation const cursor = collection.find({}); this.defer(() => cursor.close()); @@ -2946,15 +2946,6 @@ describe('Cursor', function () { const transformFunc = config.transformFunc; const expectedSet = config.expectedSet; - let cursor; - const done = async err => { - await cursor.close(); - await client.close(); - if (err) { - throw err; - } - }; - await client.connect(); const db = client.db(configuration.db); @@ -2967,16 +2958,24 @@ describe('Cursor', function () { await db.createCollection(collectionName); const collection = await db.collection(collectionName); await collection.insertMany(docs); - cursor = await collection.find(); + const cursor = await collection.find(); const stream = await cursor.stream().map(transformFunc ?? (doc => doc)); + const done = async err => { + await cursor.close(); + await client.close(); + if (err) { + throw err; + } + }; + stream.on('data', function (doc) { resultSet.add(doc); }); stream.once('end', function () { expect(resultSet).to.deep.equal(expectedSet); - done(); + done(undefined); }); stream.once('error', e => { @@ -3027,41 +3026,41 @@ describe('Cursor', function () { await testTransformStream(config); }); - it.skip('should apply parent read preference to count command', function (done) { - // NOTE: this test is skipped because mongo orchestration does not test sharded clusters - // with secondaries. This behavior should be unit tested - - const configuration = this.configuration; - const client = configuration.newClient( - { w: 1, readPreference: ReadPreference.SECONDARY }, - { maxPoolSize: 1, connectWithNoPrimary: true } - ); - - client.connect((err, client) => { - expect(err).to.not.exist; - this.defer(() => client.close()); - - const db = client.db(configuration.db); - let collection, cursor, spy; - const close = e => cursor.close(() => client.close(() => done(e))); - - Promise.resolve() - .then(() => new Promise(resolve => setTimeout(() => resolve(), 500))) - .then(() => db.createCollection('test_count_readPreference')) - .then(() => (collection = db.collection('test_count_readPreference'))) - .then(() => collection.find()) - .then(_cursor => (cursor = _cursor)) - .then(() => (spy = sinon.spy(cursor.topology, 'command'))) - .then(() => cursor.count()) - .then(() => - expect(spy.firstCall.args[2]) - .to.have.nested.property('readPreference.mode') - .that.equals('secondary') - ) - .then(() => close()) - .catch(e => close(e)); - }); - }); + // it.skip('should apply parent read preference to count command', function (done) { + // // NOTE: this test is skipped because mongo orchestration does not test sharded clusters + // // with secondaries. This behavior should be unit tested + + // const configuration = this.configuration; + // const client = configuration.newClient( + // { w: 1, readPreference: ReadPreference.SECONDARY }, + // { maxPoolSize: 1, connectWithNoPrimary: true } + // ); + + // client.connect((err, client) => { + // expect(err).to.not.exist; + // this.defer(() => client.close()); + + // const db = client.db(configuration.db); + // let collection, cursor, spy; + // const close = e => cursor.close(() => client.close(() => done(e))); + + // Promise.resolve() + // .then(() => new Promise(resolve => setTimeout(() => resolve(), 500))) + // .then(() => db.createCollection('test_count_readPreference')) + // .then(() => (collection = db.collection('test_count_readPreference'))) + // .then(() => collection.find()) + // .then(_cursor => (cursor = _cursor)) + // .then(() => (spy = sinon.spy(cursor.topology, 'command'))) + // .then(() => cursor.count()) + // .then(() => + // expect(spy.firstCall.args[2]) + // .to.have.nested.property('readPreference.mode') + // .that.equals('secondary') + // ) + // .then(() => close()) + // .catch(e => close(e)); + // }); + // }); it('should not consume first document on hasNext when streaming', async function () { const configuration = this.configuration; From 495362e24dfdd77be225fa7aeb5df98ab3b48725 Mon Sep 17 00:00:00 2001 From: Pavel Safronov Date: Tue, 21 Oct 2025 11:27:04 -0700 Subject: [PATCH 3/5] linter fixes --- test/integration/crud/misc_cursors.test.ts | 28 ++++++++++++++++------ 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/test/integration/crud/misc_cursors.test.ts b/test/integration/crud/misc_cursors.test.ts index b5df299bd5..f54466c0bd 100644 --- a/test/integration/crud/misc_cursors.test.ts +++ b/test/integration/crud/misc_cursors.test.ts @@ -168,7 +168,9 @@ describe('Cursor', function () { count = await cursor.count(); test.equal(10, count); - await cursor.forEach(() => { }); + await cursor.forEach(() => { + // do nothing + }); const count2 = await cursor.count(); expect(count2).to.equal(10); @@ -240,7 +242,9 @@ describe('Cursor', function () { count = await cursor.count(); test.equal(10, count); - await cursor.forEach(() => { }); + await cursor.forEach(() => { + // do nothing + }); const count2 = await cursor.count(); expect(count2).to.equal(10); @@ -1447,7 +1451,9 @@ describe('Cursor', function () { const cursor = collection.find({}, { tailable: true, awaitData: true }); // this.defer(() => cursor.close()); - await cursor.forEach(() => { }); + await cursor.forEach(() => { + // do nothing + }); await cursor.close(); await client.close(); }); @@ -1475,7 +1481,7 @@ describe('Cursor', function () { try { await db.collection('cursor_tailable').drop(); // eslint-disable-next-line no-empty - } catch { } + } catch {} const collection = await db.createCollection('cursor_tailable', { capped: true, @@ -1923,7 +1929,11 @@ describe('Cursor', function () { await collection.insertMany(docs, configuration.writeConcernMax()); const cursor = collection.find({}, { tailable: true }); - const err = await cursor.forEach(() => { }).catch(e => e); + const err = await cursor + .forEach(() => { + // do nothing + }) + .catch(e => e); test.ok(err instanceof Error); test.ok(typeof err.code === 'number'); @@ -2694,7 +2704,9 @@ describe('Cursor', function () { const configuration = this.configuration; - const cleanup = () => { }; + const cleanup = () => { + // do nothing + }; let caughtError = undefined; return ( @@ -2914,7 +2926,9 @@ describe('Cursor', function () { const cursor = collection.find(); this.defer(() => cursor.close()); - const promise = cursor.forEach(() => { }); + const promise = cursor.forEach(() => { + // do nothing + }); expect(promise).to.exist.and.to.be.an.instanceof(Promise); return promise; }); From 99d3aac393f55561739ccee75439a5adfb3a46d3 Mon Sep 17 00:00:00 2001 From: Pavel Safronov Date: Wed, 22 Oct 2025 09:01:22 -0700 Subject: [PATCH 4/5] pr feedback --- test/integration/crud/misc_cursors.test.ts | 1526 +------------------- 1 file changed, 76 insertions(+), 1450 deletions(-) diff --git a/test/integration/crud/misc_cursors.test.ts b/test/integration/crud/misc_cursors.test.ts index f54466c0bd..14af724fc4 100644 --- a/test/integration/crud/misc_cursors.test.ts +++ b/test/integration/crud/misc_cursors.test.ts @@ -1,11 +1,5 @@ -import * as BSON from 'bson'; import { expect } from 'chai'; import { on, once } from 'events'; -import * as fs from 'fs'; -import * as os from 'os'; -import * as path from 'path'; -import { Writable } from 'stream'; -import { setTimeout } from 'timers'; import { MongoClientClosedError } from '../../../src/error'; import { type MongoClient } from '../../../src/mongo_client'; @@ -58,54 +52,6 @@ describe('Cursor', function () { expect(forEachResult).to.be.undefined; }); - it('cursor should close after first next operation', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = await db.createCollection('close_on_next'); - - await collection.insertMany([{ a: 1 }, { a: 1 }, { a: 1 }], configuration.writeConcernMax()); - - const cursor = collection.find({}); - // this.defer(() => cursor.close()); - - cursor.batchSize(2); - await cursor.next(); - await cursor.close(); - } - }); - - it('cursor should trigger getMore', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = await db.createCollection('trigger_get_more'); - - await collection.insertMany([{ a: 1 }, { a: 1 }, { a: 1 }], configuration.writeConcernMax()); - - const cursor = collection.find({}).batchSize(2); - - await cursor.toArray(); - await cursor.close(); - } - }); - it('shouldCorrectlyExecuteCursorExplain', { // Add a tag that our runner can trigger on // in this case we are setting that node needs to be higher than 0.10.X to run @@ -144,9 +90,7 @@ describe('Cursor', function () { await collection.find().count(); async function insert() { - for (let i = 0; i < 10; i++) { - await collection.insertMany([{ x: i }], configuration.writeConcernMax()); - } + await collection.insertMany(Array.from({ length: 10 }, (_, i) => ({ x: i }))); } async function finished() { @@ -202,59 +146,6 @@ describe('Cursor', function () { } }); - it('shouldCorrectlyExecuteCursorCountWithDottedCollectionName', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = await db.createCollection('test_count.ext'); - - await collection.find().count(); - - async function insert() { - for (let i = 0; i < 10; i++) { - await collection.insertOne({ x: i }, configuration.writeConcernMax()); - } - } - - async function finished() { - let count = await collection.find().count(); - test.equal(10, count); - test.ok(count.constructor === Number); - - count = await collection.find({}, { limit: 5 }).count(); - test.equal(5, count); - - count = await collection.find({}, { skip: 5 }).count(); - test.equal(5, count); - - count = await db.collection('acollectionthatdoesn').count(); - test.equal(0, count); - - const cursor = collection.find(); - count = await cursor.count(); - test.equal(10, count); - - await cursor.forEach(() => { - // do nothing - }); - - const count2 = await cursor.count(); - expect(count2).to.equal(10); - expect(count2).to.equal(count); - } - await insert(); - await finished(); - } - }); - it('shouldThrowErrorOnEachWhenMissingCallback', { // Add a tag that our runner can trigger on // in this case we are setting that node needs to be higher than 0.10.X to run @@ -269,9 +160,7 @@ describe('Cursor', function () { const db = client.db(configuration.db); const collection = await db.createCollection('test_each'); async function insert() { - for (let i = 0; i < 10; i++) { - await collection.insertOne({ x: i }, configuration.writeConcernMax()); - } + await collection.insertMany(Array.from({ length: 10 }, (_, i) => ({ x: i }))); } function finished() { @@ -303,9 +192,7 @@ describe('Cursor', function () { const collection = await db.createCollection('test_cursor_limit'); async function insert() { - for (let i = 0; i < 10; i++) { - await collection.insertOne({ x: i }, configuration.writeConcernMax()); - } + await collection.insertMany(Array.from({ length: 10 }, (_, i) => ({ x: i }))); } async function finished() { @@ -332,9 +219,7 @@ describe('Cursor', function () { const collection = await db.createCollection('test_cursor_negative_one_limit'); async function insert() { - for (let i = 0; i < 10; i++) { - await collection.insertOne({ x: i }, configuration.writeConcernMax()); - } + await collection.insertMany(Array.from({ length: 10 }, (_, i) => ({ x: i }))); } async function finished() { @@ -362,9 +247,7 @@ describe('Cursor', function () { const collection = await db.createCollection('test_cursor_any_negative_limit'); async function insert() { - for (let i = 0; i < 10; i++) { - await collection.insertOne({ x: i }, configuration.writeConcernMax()); - } + await collection.insertMany(Array.from({ length: 10 }, (_, i) => ({ x: i }))); } async function finished() { @@ -393,15 +276,15 @@ describe('Cursor', function () { await collection.insertOne({ a: 1 }, configuration.writeConcernMax()); const cursor = collection.find(); - // this.defer(() => cursor.close()); try { cursor.limit('not-an-integer' as any); + test.ok(false); } catch (err) { test.equal('Operation "limit" requires an integer', err.message); } - await cursor.clone(); + await cursor.close(); } }); @@ -422,37 +305,13 @@ describe('Cursor', function () { await collection.insertOne({ a: 1 }, configuration.writeConcernMax()); const cursor = collection.find(); - // this.defer(() => cursor.close()); await cursor.next(); expect(() => { cursor.limit(1); }).to.throw(/Cursor is already initialized/); - } - }); - - // NOTE: who cares what you set when the cursor is closed? - it.skip('shouldCorrectlyReturnErrorsOnIllegalLimitValuesIsClosedWithinClose', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const configuration = this.configuration; - await client.connect(); - const db = client.db(configuration.db); - const collection = await db.createCollection('test_limit_exceptions_1'); - - await collection.insertOne({ a: 1 }, configuration.writeConcernMax()); - - const cursor = collection.find(); await cursor.close(); - expect(() => { - cursor.limit(1); - }).to.throw(/not extensible/); } }); @@ -524,25 +383,10 @@ describe('Cursor', function () { try { collection.find().skip('not-an-integer' as any); + test.ok(false); } catch (err) { test.equal('Operation "skip" requires an integer', err.message); } - - const cursor = collection.find(); - await cursor.next(); - - // NOTE: who cares what you set when closed, if not initialized - // expect(() => { - // cursor.skip(1); - // }).to.throw(/not extensible/); - - const cursor2 = collection.find(); - await cursor2.close(); - - // NOTE: who cares what you set when closed, if not initialized - // expect(() => { - // cursor2.skip(1); - // }).to.throw(/not extensible/); } }); @@ -561,31 +405,13 @@ describe('Cursor', function () { const collection = await db.createCollection('test_batchSize_exceptions'); await collection.insertOne({ a: 1 }, configuration.writeConcernMax()); - let cursor = collection.find(); + const cursor = collection.find(); try { cursor.batchSize('not-an-integer' as any); test.ok(false); } catch (err) { test.equal('Operation "batchSize" requires an integer', err.message); } - - cursor = collection.find(); - await cursor.next(); - - await cursor.next(); - - // NOTE: who cares what you set when closed, if not initialized - // expect(() => { - // cursor.batchSize(1); - // }).to.throw(/not extensible/); - - const cursor2 = collection.find(); - await cursor2.close(); - - // NOTE: who cares what you set when closed, if not initialized - // expect(() => { - // cursor2.batchSize(1); - // }).to.throw(/not extensible/); } }); @@ -745,9 +571,7 @@ describe('Cursor', function () { const collection = db.collection('shouldHandleSkipLimitChaining'); async function insert() { - for (let i = 0; i < 10; i++) { - await collection.insertOne({ x: i }, configuration.writeConcernMax()); - } + await collection.insertMany(Array.from({ length: 10 }, (_, i) => ({ x: i }))); } async function finished() { @@ -786,9 +610,7 @@ describe('Cursor', function () { const collection = await db.createCollection('test_limit_skip_chaining_inline'); async function insert() { - for (let i = 0; i < 10; i++) { - await collection.insertOne({ x: i }, configuration.writeConcernMax()); - } + await collection.insertMany(Array.from({ length: 10 }, (_, i) => ({ x: i }))); } async function finished() { @@ -833,125 +655,6 @@ describe('Cursor', function () { } }); - it('shouldCorrectlyRefillViaGetMoreCommand', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const COUNT = 1000; - - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = await db.createCollection('test_refill_via_get_more'); - - async function insert() { - const docs = []; - - for (let i = 0; i < COUNT; i++) { - docs.push({ a: i }); - } - - await collection.insertMany(docs, configuration.writeConcernMax()); - } - - async function finished() { - let count = await collection.count(); - test.equal(COUNT, count); - - let total = 0; - await collection.find({}, {}).forEach(item => { - total = total + item.a; - }); - - test.equal(499500, total); - - count = await collection.count(); - test.equal(COUNT, count); - - count = await collection.count(); - test.equal(COUNT, count); - - let total2 = 0; - await collection.find().forEach(item => { - total2 = total2 + item.a; - }); - - test.equal(499500, total2); - count = await collection.count(); - - test.equal(COUNT, count); - test.equal(total, total2); - } - await insert(); - await finished(); - } - }); - - it('shouldCorrectlyRefillViaGetMoreAlternativeCollection', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = await db.createCollection('test_refill_via_get_more_alt_coll'); - - const COUNT = 1000; - - async function insert() { - const docs = []; - - for (let i = 0; i < COUNT; i++) { - docs.push({ a: i }); - } - - await collection.insertMany(docs, configuration.writeConcernMax()); - } - - async function finished() { - let count = await collection.count(); - test.equal(1000, count); - - let total = 0; - await collection.find().forEach(doc => { - total = total + doc.a; - }); - - test.equal(499500, total); - - count = await collection.count(); - test.equal(1000, count); - - count = await collection.count(); - test.equal(1000, count); - - let total2 = 0; - await collection.find().forEach(doc => { - total2 = total2 + doc.a; - }); - - expect(total2).to.equal(499500); - - count = await collection.count(); - - expect(count).to.equal(1000); - expect(total2).to.equal(total); - } - await insert(); - await finished(); - } - }); - it('shouldCloseCursorAfterQueryHasBeenSent', { // Add a tag that our runner can trigger on // in this case we are setting that node needs to be higher than 0.10.X to run @@ -1023,46 +726,6 @@ describe('Cursor', function () { } }); - it('Should correctly execute count on cursor', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const docs = []; - - for (let i = 0; i < 1000; i++) { - const d = new Date().getTime() + i * 1000; - docs[i] = { a: i, createdAt: new Date(d) }; - } - - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = await db.createCollection('Should_correctly_execute_count_on_cursor_1'); - - // insert all docs - await collection.insertMany(docs, configuration.writeConcernMax()); - - let total = 0; - // Create a cursor for the content - const cursor = collection.find({}); - // this.defer(() => cursor.close()); - - await cursor.count(); - // Ensure each returns all documents - await cursor.forEach(() => { - total++; - }); - const c = await cursor.count(); - expect(c).to.equal(1000); - expect(total).to.equal(1000); - } - }); - it('does not auto destroy streams', async function () { const docs = []; @@ -1093,88 +756,7 @@ describe('Cursor', function () { await once(stream, 'end'); }); - it('should be able to stream documents', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const docs = []; - - for (let n = 0; n < 1000; n++) { - docs[n] = { a: n + 1 }; - } - - let count = 0; - - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = await db.createCollection('Should_be_able_to_stream_documents'); - - // insert all docs - await collection.insertMany(docs, configuration.writeConcernMax()); - - let paused = 0, - closed = 0, - resumed = 0, - i = 0, - err = null; - - const cursor = collection.find(); - const stream = cursor.stream(); - - stream.on('data', function (doc) { - test.equal(true, !!doc); - test.equal(true, !!doc.a); - count = count + 1; - - if (paused > 0 && 0 === resumed) { - err = new Error('data emitted during pause'); - testDone(); - return; - } - - if (++i === 3) { - stream.pause(); - paused++; - - setTimeout(function () { - stream.resume(); - resumed++; - }, 20); - } - }); - - stream.once('error', function (er) { - err = er; - testDone(); - }); - - stream.once('end', function () { - closed++; - testDone(); - }); - - function testDone() { - expect(err).to.not.exist; - test.equal(i, docs.length); - test.equal(1, closed); - test.equal(1, paused); - test.equal(1, resumed); - test.strictEqual(cursor.closed, true); - } - - const promise = once(stream, 'end'); - await promise; - await client.close(); - } - }); - - it('immediately destroying a stream prevents the query from executing', { + it('immediately destroying a stream prevents the query from executing', { // Add a tag that our runner can trigger on // in this case we are setting that node needs to be higher than 0.10.X to run metadata: { @@ -1204,12 +786,6 @@ describe('Cursor', function () { i++; }); - cursor.once('close', testDone('close')); - stream.once('error', testDone('error')); - const promise = once(cursor, 'close'); - - stream.destroy(); - function testDone() { return err => { ++doneCalled; @@ -1222,6 +798,12 @@ describe('Cursor', function () { }; } + cursor.once('close', testDone('close')); + stream.once('error', testDone('error')); + const promise = once(cursor, 'close'); + + stream.destroy(); + await cursor.close(); await promise; } @@ -1288,6 +870,40 @@ describe('Cursor', function () { ]); }); + it('Should not emit any events after close event emitted due to cursor killed', { + // Add a tag that our runner can trigger on + // in this case we are setting that node needs to be higher than 0.10.X to run + metadata: { requires: { topology: ['single', 'replicaset'] } }, + + test: async function () { + const configuration = this.configuration; + await client.connect(); + + const db = client.db(configuration.db); + const collection = db.collection('cursor_limit_skip_correctly'); + + // Insert x number of docs + const ordered = collection.initializeUnorderedBulkOp(); + + for (let i = 0; i < 100; i++) { + ordered.insert({ a: i }); + } + + await ordered.execute({ writeConcern: { w: 1 } }); + + // Let's attempt to skip and limit + const cursor = collection.find({}).batchSize(10); + const stream = cursor.stream(); + stream.on('data', function () { + stream.destroy(); + }); + + const onClose = once(cursor, 'close'); + await cursor.close(); + await onClose; + } + }); + // NOTE: skipped for use of topology manager // it.skip('cursor stream errors', { // // Add a tag that our runner can trigger on @@ -1350,56 +966,6 @@ describe('Cursor', function () { // } // }); - it('cursor stream pipe', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = await db.createCollection('cursor_stream_pipe'); - - const docs = []; - 'Aaden Aaron Adrian Aditya Bob Joe'.split(' ').forEach(function (name) { - docs.push({ name: name }); - }); - - // insert all docs - await collection.insertMany(docs, configuration.writeConcernMax()); - - const filename = path.join(os.tmpdir(), '_nodemongodbnative_stream_out.txt'); - const out = fs.createWriteStream(filename); - const stream = collection - .find() - .stream() - .map(d => JSON.stringify(d)); - - stream.pipe(out); - // Wait for output stream to close - out.on('close', () => testDone(undefined)); - - function testDone(err) { - // Object.prototype.toString = toString; - test.strictEqual(undefined, err); - const contents = fs.readFileSync(filename, 'utf8'); - test.ok(/Aaden/.test(contents)); - test.ok(/Aaron/.test(contents)); - test.ok(/Adrian/.test(contents)); - test.ok(/Aditya/.test(contents)); - test.ok(/Bob/.test(contents)); - test.ok(/Joe/.test(contents)); - fs.unlinkSync(filename); - } - - await once(out, 'close'); - } - }); - it( 'closes cursors when client is closed even if it has not been exhausted', { requires: { topology: '!replicaset' } }, @@ -1449,7 +1015,6 @@ describe('Cursor', function () { // Create cursor with awaitData, and timeout after the period specified const cursor = collection.find({}, { tailable: true, awaitData: true }); - // this.defer(() => cursor.close()); await cursor.forEach(() => { // do nothing @@ -1478,10 +1043,7 @@ describe('Cursor', function () { async test() { const db = client.db('cursor_tailable'); - try { - await db.collection('cursor_tailable').drop(); - // eslint-disable-next-line no-empty - } catch {} + await db.collection('cursor_tailable').drop(); const collection = await db.createCollection('cursor_tailable', { capped: true, @@ -1515,258 +1077,6 @@ describe('Cursor', function () { ); }); - // NOTE: should we continue to let users explicitly `kill` a cursor? - it.skip('Should correctly retry tailable cursor connection', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - // www.mongodb.com/docs/display/DOCS/Tailable+Cursors - - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const options = { capped: true, size: 8 }; - const collection = await db.createCollection('should_await_data', options); - - await collection.insertOne({ a: 1 }, configuration.writeConcernMax()); - - // Create cursor with awaitData, and timeout after the period specified - const cursor = collection.find({}, { tailable: true, awaitData: true }); - await cursor.forEach(() => cursor.kill()); - await cursor.close(); - } - }); - - it('shouldCorrectExecuteExplainHonoringLimit', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const docs = []; - docs[0] = { - _keywords: [ - 'compact', - 'ii2gd', - 'led', - '24-48v', - 'presse-etoupe', - 'bexbgl1d24483', - 'flash', - '48v', - 'eexd', - 'feu', - 'presse', - 'compris', - 'rouge', - 'etoupe', - 'iic', - 'ii2gdeexdiict5', - 'red', - 'aet' - ] - }; - docs[1] = { - _keywords: [ - 'reducteur', - '06212', - 'd20/16', - 'manch', - 'd20', - 'manchon', - 'ard', - 'sable', - 'irl', - 'red' - ] - }; - docs[2] = { - _keywords: [ - 'reducteur', - '06214', - 'manch', - 'd25/20', - 'd25', - 'manchon', - 'ard', - 'sable', - 'irl', - 'red' - ] - }; - docs[3] = { - _keywords: [ - 'bar', - 'rac', - 'boite', - '6790178', - '50-240/4-35', - '240', - 'branch', - 'coulee', - 'ddc', - 'red', - 'ip2x' - ] - }; - docs[4] = { - _keywords: [ - 'bar', - 'ip2x', - 'boite', - '6790158', - 'ddi', - '240', - 'branch', - 'injectee', - '50-240/4-35?', - 'red' - ] - }; - docs[5] = { - _keywords: [ - 'bar', - 'ip2x', - 'boite', - '6790179', - 'coulee', - '240', - 'branch', - 'sdc', - '50-240/4-35?', - 'red', - 'rac' - ] - }; - docs[6] = { - _keywords: [ - 'bar', - 'ip2x', - 'boite', - '6790159', - '240', - 'branch', - 'injectee', - '50-240/4-35?', - 'sdi', - 'red' - ] - }; - docs[7] = { - _keywords: [ - '6000', - 'r-6000', - 'resin', - 'high', - '739680', - 'red', - 'performance', - 'brd', - 'with', - 'ribbon', - 'flanges' - ] - }; - docs[8] = { _keywords: ['804320', 'for', 'paint', 'roads', 'brd', 'red'] }; - docs[9] = { _keywords: ['38mm', 'padlock', 'safety', '813594', 'brd', 'red'] }; - docs[10] = { _keywords: ['114551', 'r6900', 'for', 'red', 'bmp71', 'brd', 'ribbon'] }; - docs[11] = { - _keywords: ['catena', 'diameter', '621482', 'rings', 'brd', 'legend', 'red', '2mm'] - }; - docs[12] = { - _keywords: ['catena', 'diameter', '621491', 'rings', '5mm', 'brd', 'legend', 'red'] - }; - docs[13] = { - _keywords: ['catena', 'diameter', '621499', 'rings', '3mm', 'brd', 'legend', 'red'] - }; - docs[14] = { - _keywords: ['catena', 'diameter', '621508', 'rings', '5mm', 'brd', 'legend', 'red'] - }; - docs[15] = { - _keywords: [ - 'insert', - 'for', - 'cable', - '3mm', - 'carrier', - '621540', - 'blank', - 'brd', - 'ademark', - 'red' - ] - }; - docs[16] = { - _keywords: [ - 'insert', - 'for', - 'cable', - '621544', - '3mm', - 'carrier', - 'brd', - 'ademark', - 'legend', - 'red' - ] - }; - docs[17] = { - _keywords: ['catena', 'diameter', '6mm', '621518', 'rings', 'brd', 'legend', 'red'] - }; - docs[18] = { - _keywords: ['catena', 'diameter', '621455', '8mm', 'rings', 'brd', 'legend', 'red'] - }; - docs[19] = { - _keywords: ['catena', 'diameter', '621464', 'rings', '5mm', 'brd', 'legend', 'red'] - }; - - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - // Insert all the docs - const collection = db.collection('shouldCorrectExecuteExplainHonoringLimit'); - await collection.insertMany(docs, configuration.writeConcernMax()); - - await collection.createIndex({ _keywords: 1 }); - - const result = await collection.find({ _keywords: 'red' }).limit(10).toArray(); - test.ok(result != null); - - const result2 = await collection.find({ _keywords: 'red' }, {}).limit(10).explain(); - test.ok(result2 != null); - } - }); - - it('shouldNotExplainWhenFalse', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const doc = { name: 'camera', _keywords: ['compact', 'ii2gd', 'led', 'red', 'aet'] }; - - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = db.collection('shouldNotExplainWhenFalse'); - await collection.insertOne(doc, configuration.writeConcernMax()); - - const result = await collection.find({ _keywords: 'red' }).limit(10).toArray(); - test.equal('camera', result[0].name); - } - }); - it('shouldFailToSetReadPreferenceOnCursor', { // Add a tag that our runner can trigger on // in this case we are setting that node needs to be higher than 0.10.X to run @@ -1817,50 +1127,6 @@ describe('Cursor', function () { } }); - it('shouldNotFailDueToStackOverflowEach', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = await db.createCollection('shouldNotFailDueToStackOverflowEach'); - - const docs = []; - let total = 0; - for (let i = 0; i < 30000; i++) docs.push({ a: i }); - const allDocs = []; - let left = 0; - - while (docs.length > 0) { - allDocs.push(docs.splice(0, 1000)); - } - // Get all batches we must insert - left = allDocs.length; - let totalI = 0; - - // Execute inserts - for (let i = 0; i < left; i++) { - const d = await collection.insertMany(allDocs.shift(), configuration.writeConcernMax()); - - left = left - 1; - totalI = totalI + d.insertedCount; - - if (left === 0) { - await collection.find({}).forEach(() => { - total++; - }); - expect(total).to.equal(30000); - } - } - } - }); - it('should not fail due to stack overflow toArray', async function () { const configuration = this.configuration; const db = client.db(configuration.db); @@ -1896,27 +1162,6 @@ describe('Cursor', function () { await client.close(); }); - it('should correctly skip and limit', async function () { - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = db.collection('shouldCorrectlySkipAndLimit'); - const docs = []; - for (let i = 0; i < 100; i++) docs.push({ a: i, OrderNumber: i }); - - await collection.insertMany(docs, configuration.writeConcernMax()); - - const items = await collection.find({}, { OrderNumber: 1 }).skip(10).limit(10).toArray(); - - test.equal(10, items[0].OrderNumber); - - const count = await collection.find({}, { OrderNumber: 1 }).skip(10).limit(10).count(); - test.equal(10, count); - - await client.close(); - }); - it('shouldFailToTailANormalCollection', async function () { const configuration = this.configuration; await client.connect(); @@ -1938,44 +1183,7 @@ describe('Cursor', function () { test.ok(typeof err.code === 'number'); // Close cursor b/c we did not exhaust cursor - cursor.close(); - }); - - it('shouldCorrectlyUseFindAndCursorCount', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const configuration = this.configuration; - - // DOC_LINE var client = new MongoClient(new Server('localhost', 27017)); - // DOC_START - // Establish connection to db - await client.connect(); - - const db = client.db(configuration.db); - - // Create a lot of documents to insert - const docs = []; - for (let i = 0; i < 100; i++) { - docs.push({ a: i }); - } - - // Create a collection - const collection = await db.createCollection('test_close_function_on_cursor_2'); - - // Insert documents into collection - await collection.insertMany(docs, configuration.writeConcernMax()); - - const cursor = collection.find({}); - - const count = await cursor.count(); - test.equal(100, count); - // DOC_END - } + await cursor.close(); }); it('should correctly apply hint to count command for cursor', { @@ -2062,227 +1270,21 @@ describe('Cursor', function () { } }); - it('Should correctly handle maxTimeMS as part of findOne options', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const donkey = { - color: 'brown' - }; - - const result = await db.collection('donkies').insertOne(donkey); - - const query = { _id: result.insertedId }; - const options = { maxTimeMS: 1000 }; - - const doc = await db.collection('donkies').findOne(query, options); - - test.equal('brown', doc.color); - } - }); - - it('Should correctly handle batchSize of 2', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collectionName = 'should_correctly_handle_batchSize_2'; - await db.collection(collectionName).insertMany([{ x: 1 }, { x: 2 }, { x: 3 }]); - - const cursor = db.collection(collectionName).find({}, { batchSize: 2 }); - // this.defer(() => cursor.close()); - - await cursor.next(); - - await cursor.next(); - - await cursor.next(); - - await cursor.close(); - } - }); - - it('Should report database name and collection name', { - metadata: { requires: { topology: ['single'] } }, - - test: async function () { - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const cursor = db.collection('myCollection').find({}); - test.equal('myCollection', cursor.namespace.collection); - test.equal('integration_tests', cursor.namespace.db); - } - }); - - it('Should correctly execute count on cursor with maxTimeMS', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const docs = []; - - for (let i = 0; i < 1000; i++) { - const d = new Date().getTime() + i * 1000; - docs[i] = { a: i, createdAt: new Date(d) }; - } - - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = await db.createCollection('Should_correctly_execute_count_on_cursor_2'); - - // insert all docs - await collection.insertMany(docs, configuration.writeConcernMax()); - - // Create a cursor for the content - let cursor = collection.find({}); - cursor.limit(100); - cursor.skip(10); - await cursor.count({ maxTimeMS: 1000 }); - - // Create a cursor for the content - cursor = collection.find({}); - cursor.limit(100); - cursor.skip(10); - cursor.maxTimeMS(100); - - await cursor.count(); - } - }); - - it('Should correctly execute count on cursor with maxTimeMS set using legacy method', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const docs = []; - - for (let i = 0; i < 1000; i++) { - const d = new Date().getTime() + i * 1000; - docs[i] = { a: i, createdAt: new Date(d) }; - } - - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = await db.createCollection('Should_correctly_execute_count_on_cursor_3'); - - // insert all docs - await collection.insertMany(docs, configuration.writeConcernMax()); - - // Create a cursor for the content - const cursor = collection.find({}, { maxTimeMS: 100 }); - await cursor.toArray(); - } - }); - - it('Should correctly apply map to toArray', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const docs = []; - - for (let i = 0; i < 1000; i++) { - const d = new Date().getTime() + i * 1000; - docs[i] = { a: i, createdAt: new Date(d) }; - } - - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = db.collection('map_toArray'); - - // insert all docs - await collection.insertMany(docs, configuration.writeConcernMax()); - - // Create a cursor for the content - const cursor = collection - .find({}) - .map(function () { - return { a: 1 }; - }) - .batchSize(5) - .limit(10); - - const docs2 = await cursor.toArray(); - test.equal(10, docs2.length); - - // Ensure all docs where mapped - docs2.forEach(doc => { - expect(doc).property('a').to.equal(1); - }); - } - }); - - it('Should correctly apply map to next', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, + it('Should report database name and collection name', { + metadata: { requires: { topology: ['single'] } }, test: async function () { - const docs = []; - for (let i = 0; i < 1000; i++) { - const d = new Date().getTime() + i * 1000; - docs[i] = { a: i, createdAt: new Date(d) }; - } - const configuration = this.configuration; await client.connect(); const db = client.db(configuration.db); - const collection = db.collection('map_next'); - - // insert all docs - await collection.insertMany(docs, configuration.writeConcernMax()); - - // Create a cursor for the content - const cursor = collection - .find({}) - .map(function () { - return { a: 1 }; - }) - .batchSize(5) - .limit(10); - - const doc = await cursor.next(); - test.equal(1, doc.a); - await cursor.close(); + const cursor = db.collection('myCollection').find({}); + test.equal('myCollection', cursor.namespace.collection); + test.equal('integration_tests', cursor.namespace.db); } }); - it('Should correctly apply map to each', { + it('Should correctly apply map to toArray', { // Add a tag that our runner can trigger on // in this case we are setting that node needs to be higher than 0.10.X to run metadata: { @@ -2301,7 +1303,7 @@ describe('Cursor', function () { await client.connect(); const db = client.db(configuration.db); - const collection = db.collection('map_each'); + const collection = db.collection('map_toArray'); // insert all docs await collection.insertMany(docs, configuration.writeConcernMax()); @@ -2315,13 +1317,17 @@ describe('Cursor', function () { .batchSize(5) .limit(10); - await cursor.forEach(doc => { - test.equal(1, doc.a); + const docs2 = await cursor.toArray(); + test.equal(10, docs2.length); + + // Ensure all docs where mapped + docs2.forEach(doc => { + expect(doc).property('a').to.equal(1); }); } }); - it('Should correctly apply map to forEach', { + it('Should correctly apply map to next', { // Add a tag that our runner can trigger on // in this case we are setting that node needs to be higher than 0.10.X to run metadata: { @@ -2330,7 +1336,6 @@ describe('Cursor', function () { test: async function () { const docs = []; - for (let i = 0; i < 1000; i++) { const d = new Date().getTime() + i * 1000; docs[i] = { a: i, createdAt: new Date(d) }; @@ -2340,7 +1345,7 @@ describe('Cursor', function () { await client.connect(); const db = client.db(configuration.db); - const collection = db.collection('map_forEach'); + const collection = db.collection('map_next'); // insert all docs await collection.insertMany(docs, configuration.writeConcernMax()); @@ -2349,22 +1354,18 @@ describe('Cursor', function () { const cursor = collection .find({}) .map(function () { - return { a: 2 }; - }) - .map(function (x) { - return { a: x.a * x.a }; + return { a: 1 }; }) .batchSize(5) .limit(10); - await cursor.forEach(doc => { - test.equal(4, doc.a); - }); + const doc = await cursor.next(); + test.equal(1, doc.a); await cursor.close(); } }); - it('Should correctly apply multiple uses of map and apply forEach', { + it('Should correctly apply map to each', { // Add a tag that our runner can trigger on // in this case we are setting that node needs to be higher than 0.10.X to run metadata: { @@ -2383,7 +1384,7 @@ describe('Cursor', function () { await client.connect(); const db = client.db(configuration.db); - const collection = db.collection('map_mapmapforEach'); + const collection = db.collection('map_each'); // insert all docs await collection.insertMany(docs, configuration.writeConcernMax()); @@ -2398,36 +1399,8 @@ describe('Cursor', function () { .limit(10); await cursor.forEach(doc => { - expect(doc).property('a').to.equal(1); + test.equal(1, doc.a); }); - await cursor.close(); - } - }); - - it('Should correctly apply skip and limit to large set of documents', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { requires: { topology: ['single', 'replicaset'] } }, - - test: async function () { - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = db.collection('cursor_limit_skip_correctly'); - - // Insert x number of docs - const ordered = collection.initializeUnorderedBulkOp(); - - for (let i = 0; i < 6000; i++) { - ordered.insert({ a: i }); - } - - await ordered.execute({ writeConcern: { w: 1 } }); - - // Let's attempt to skip and limit - const docs = await collection.find({}).limit(2016).skip(2016).toArray(); - test.equal(2016, docs.length); } }); @@ -2468,141 +1441,6 @@ describe('Cursor', function () { } }); - it('Should not emit any events after close event emitted due to cursor killed', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { requires: { topology: ['single', 'replicaset'] } }, - - test: async function () { - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = db.collection('cursor_limit_skip_correctly'); - - // Insert x number of docs - const ordered = collection.initializeUnorderedBulkOp(); - - for (let i = 0; i < 100; i++) { - ordered.insert({ a: i }); - } - - await ordered.execute({ writeConcern: { w: 1 } }); - - // Let's attempt to skip and limit - const cursor = collection.find({}).batchSize(10); - const stream = cursor.stream(); - stream.on('data', function () { - stream.destroy(); - }); - - const onClose = once(cursor, 'close'); - await cursor.close(); - await onClose; - } - }); - - it('shouldCorrectlyExecuteEnsureIndexWithNoCallback', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const docs = []; - - for (let i = 0; i < 1; i++) { - const d = new Date().getTime() + i * 1000; - docs[i] = { createdAt: new Date(d) }; - } - - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = await db.createCollection( - 'shouldCorrectlyExecuteEnsureIndexWithNoCallback' - ); - - // ensure index of createdAt index - await collection.createIndex({ createdAt: 1 }); - - // insert all docs - await collection.insertMany(docs, configuration.writeConcernMax()); - - // Find with sort - const items = await collection.find().sort(['createdAt', 'asc']).toArray(); - - test.equal(1, items.length); - } - }); - - it('Should correctly execute count on cursor with limit and skip', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const docs = []; - - for (let i = 0; i < 50; i++) { - const d = new Date().getTime() + i * 1000; - docs[i] = { a: i, createdAt: new Date(d) }; - } - - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = await db.createCollection('negative_batch_size_and_limit_set'); - - // insert all docs - await collection.insertMany(docs, configuration.writeConcernMax()); - - // Create a cursor for the content - let cursor = collection.find({}); - let c = await cursor.limit(100).skip(0).count(); - test.equal(50, c); - - cursor = collection.find({}); - c = (await cursor.limit(100).skip(0).toArray()).length; - test.equal(50, c); - } - }); - - it('Should correctly handle negative batchSize and set the limit', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const docs = []; - const configuration = this.configuration; - - for (let i = 0; i < 50; i++) { - const d = new Date().getTime() + i * 1000; - docs[i] = { a: i, createdAt: new Date(d) }; - } - - await client.connect(); - const db = client.db(configuration.db); - const collection = await db.createCollection('Should_correctly_execute_count_on_cursor_1_'); - - // insert all docs - await collection.insertMany(docs, configuration.writeConcernMax()); - - // Create a cursor for the content - const cursor = collection.find({}); - await cursor.batchSize(-10).next(); - test.ok(cursor.id.equals(BSON.Long.ZERO)); - } - }); - it('Correctly decorate the cursor count command with skip, limit, hint, readConcern', { // Add a tag that our runner can trigger on // in this case we are setting that node needs to be higher than 0.10.X to run @@ -2644,7 +1482,7 @@ describe('Cursor', function () { } }); - it.skip('Correctly decorate the collection count command with skip, limit, hint, readConcern', { + it('Correctly decorate the collection count command with skip, limit, hint, readConcern', { // Add a tag that our runner can trigger on // in this case we are setting that node needs to be higher than 0.10.X to run metadata: { @@ -2684,92 +1522,6 @@ describe('Cursor', function () { } }); - // NOTE: should we allow users to explicitly `kill` a cursor anymore? - it.skip('Should properly kill a cursor', { - metadata: { - requires: { - topology: ['single', 'replicaset', 'sharded'], - mongodb: '>=3.2.0' - } - }, - - 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 cleanup = () => { - // do nothing - }; - let caughtError = undefined; - - return ( - client - .connect() - .then(client => { - this.defer(() => client.close()); - const db = client.db(configuration.db); - const collection = db.collection('cursorkilltest1'); - - // Insert 1000 documents - return collection.insertMany(docs).then(() => { - // Generate cursor for find operation - const cursor = collection.find({}); - this.defer(() => cursor.close()); - - // Iterate cursor past first element - return cursor - .next() - .then(() => cursor.next()) - .then(() => { - // Confirm that cursorId is non-zero - const longId = cursor.id; - expect(longId).to.be.an('object'); - expect(Object.getPrototypeOf(longId)).to.haveOwnProperty('_bsontype', 'Long'); - const id = longId.toNumber(); - - expect(id).to.not.equal(0); - - // Kill cursor - return new Promise((resolve, reject) => - cursor.kill((err, r) => (err ? reject(err) : resolve(r))) - ).then(response => { - // sharded clusters will return a long, single return integers - if ( - response && - response.cursorsKilled && - Array.isArray(response.cursorsKilled) - ) { - response.cursorsKilled = response.cursorsKilled.map(id => - typeof id === 'number' ? BSON.Long.fromNumber(id) : id - ); - } - - expect(response.ok).to.equal(1); - expect(response.cursorsKilled[0].equals(longId)).to.be.ok; - }); - }); - }); - }) - - // 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; - } - }) - ); - } - }); - it('should return implicit session to pool when client-side cursor exhausts results on initial query', async function () { const configuration = this.configuration; const client = configuration.newClient(); @@ -2953,93 +1705,6 @@ describe('Cursor', function () { await client.close(); }); - const testTransformStream = async config => { - const client = config.client; - const configuration = config.configuration; - const collectionName = config.collectionName; - const transformFunc = config.transformFunc; - const expectedSet = config.expectedSet; - - await client.connect(); - - const db = client.db(configuration.db); - const docs = [ - { _id: 0, a: { b: 1, c: 0 } }, - { _id: 1, a: { b: 1, c: 0 } }, - { _id: 2, a: { b: 1, c: 0 } } - ]; - const resultSet = new Set(); - await db.createCollection(collectionName); - const collection = await db.collection(collectionName); - await collection.insertMany(docs); - const cursor = await collection.find(); - const stream = await cursor.stream().map(transformFunc ?? (doc => doc)); - - const done = async err => { - await cursor.close(); - await client.close(); - if (err) { - throw err; - } - }; - - stream.on('data', function (doc) { - resultSet.add(doc); - }); - - stream.once('end', function () { - expect(resultSet).to.deep.equal(expectedSet); - done(undefined); - }); - - stream.once('error', e => { - done(e); - }); - - const promise = once(stream, 'end'); - await promise; - await cursor.close(); - await client.close(); - }; - - it('stream should apply the supplied transformation function to each document in the stream', async function () { - const configuration = this.configuration; - const client = configuration.newClient({ w: 1 }, { maxPoolSize: 1 }); - const expectedDocs = [ - { _id: 0, b: 1, c: 0 }, - { _id: 1, b: 1, c: 0 }, - { _id: 2, b: 1, c: 0 } - ]; - const config = { - client: client, - configuration: configuration, - collectionName: 'stream-test-transform', - transformFunc: doc => ({ _id: doc._id, b: doc.a.b, c: doc.a.c }), - expectedSet: new Set(expectedDocs) - }; - - await testTransformStream(config); - }); - - it('stream should return a stream of unmodified docs if no transform function applied', async function () { - const configuration = this.configuration; - const client = configuration.newClient({ w: 1 }, { maxPoolSize: 1 }); - const expectedDocs = [ - { _id: 0, a: { b: 1, c: 0 } }, - { _id: 1, a: { b: 1, c: 0 } }, - { _id: 2, a: { b: 1, c: 0 } } - ]; - const config = { - client: client, - configuration: configuration, - collectionName: 'transformStream-test-notransform', - transformFunc: null, - expectedSet: new Set(expectedDocs) - }; - - await testTransformStream(config); - }); - // it.skip('should apply parent read preference to count command', function (done) { // // NOTE: this test is skipped because mongo orchestration does not test sharded clusters // // with secondaries. This behavior should be unit tested @@ -3076,45 +1741,6 @@ describe('Cursor', function () { // }); // }); - it('should not consume first document on hasNext when streaming', async function () { - const configuration = this.configuration; - const client = configuration.newClient({ w: 1 }, { maxPoolSize: 1 }); - - await client.connect(); - - const collection = client.db(configuration.db).collection('documents'); - const err = await collection.drop().catch(e => e); - expect(err).to.exist; - - const docs = [{ a: 1 }, { a: 2 }, { a: 3 }]; - await collection.insertMany(docs); - - const cursor = collection.find({}, { sort: { a: 1 } }); - const hasNext = await cursor.hasNext(); - expect(hasNext).to.be.true; - - const collected = []; - const stream = new Writable({ - objectMode: true, - write: (chunk, encoding, next) => { - collected.push(chunk); - next(undefined, chunk); - } - }); - - const cursorStream = cursor.stream(); - - cursorStream.on('end', () => { - expect(collected).to.have.length(3); - expect(collected).to.eql(docs); - }); - - const promise = once(cursorStream, 'end'); - cursorStream.pipe(stream); - await promise; - await client.close(); - }); - describe('transforms', function () { it('should correctly apply map transform to cursor as readable stream', async function () { const configuration = this.configuration; From aa78855b354803e16eadd848bb56d6703871448c Mon Sep 17 00:00:00 2001 From: Pavel Safronov Date: Wed, 22 Oct 2025 14:04:44 -0700 Subject: [PATCH 5/5] pr feedback --- test/integration/crud/misc_cursors.test.ts | 156 +---------------- .../node-specific/cursor_stream.test.ts | 157 +++++++++++++++++- 2 files changed, 157 insertions(+), 156 deletions(-) diff --git a/test/integration/crud/misc_cursors.test.ts b/test/integration/crud/misc_cursors.test.ts index 14af724fc4..0044eca7d7 100644 --- a/test/integration/crud/misc_cursors.test.ts +++ b/test/integration/crud/misc_cursors.test.ts @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { on, once } from 'events'; +import { once } from 'events'; import { MongoClientClosedError } from '../../../src/error'; import { type MongoClient } from '../../../src/mongo_client'; @@ -726,89 +726,6 @@ describe('Cursor', function () { } }); - it('does not auto destroy streams', async function () { - const docs = []; - - for (let i = 0; i < 10; i++) { - docs.push({ a: i + 1 }); - } - - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = await db.createCollection('does_not_autodestroy_streams'); - - await collection.insertMany(docs, configuration.writeConcernMax()); - - const cursor = collection.find(); - const stream = cursor.stream(); - stream.on('close', () => { - expect.fail('extra close event must not be called'); - }); - stream.on('end', () => { - client.close(); - }); - stream.on('data', doc => { - expect(doc).to.exist; - }); - stream.resume(); - await once(stream, 'end'); - }); - - it('immediately destroying a stream prevents the query from executing', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { - requires: { topology: ['single', 'replicaset', 'sharded'] } - }, - - test: async function () { - const docs = [{ b: 2 }, { b: 3 }]; - let i = 0, - doneCalled = 0; - - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = await db.createCollection( - 'immediately_destroying_a_stream_prevents_the_query_from_executing' - ); - - // insert all docs - await collection.insertMany(docs, configuration.writeConcernMax()); - - const cursor = collection.find(); - const stream = cursor.stream(); - - stream.on('data', function () { - i++; - }); - - function testDone() { - return err => { - ++doneCalled; - - if (doneCalled === 1) { - expect(err).to.not.exist; - test.strictEqual(0, i); - test.strictEqual(true, cursor.closed); - } - }; - } - - cursor.once('close', testDone('close')); - stream.once('error', testDone('error')); - const promise = once(cursor, 'close'); - - stream.destroy(); - - await cursor.close(); - await promise; - } - }); - it('removes session when cloning an find cursor', async function () { const collection = await client.db().collection('test'); @@ -833,77 +750,6 @@ describe('Cursor', function () { expect(clonedCursor).to.have.property('session').to.be.null; }); - it('destroying a stream stops it', async function () { - const db = client.db(); - await db.dropCollection('destroying_a_stream_stops_it'); - const collection = await db.createCollection('destroying_a_stream_stops_it'); - - const docs = Array.from({ length: 10 }, (_, i) => ({ b: i + 1 })); - - await collection.insertMany(docs); - - const cursor = collection.find(); - const stream = cursor.stream(); - - expect(cursor).property('closed', false); - - const willClose = once(cursor, 'close'); - - const dataEvents = on(stream, 'data'); - - for (let i = 0; i < 5; i++) { - const { - value: [doc] - } = await dataEvents.next(); - expect(doc).property('b', i + 1); - } - - // After 5 successful data events, destroy stream - stream.destroy(); - - // We should get a close event on the stream and a close event on the cursor - // We should **not** get an 'error' or an 'end' event, - // the following will throw if either stream or cursor emitted an 'error' event - await Promise.race([ - willClose, - sleep(100).then(() => Promise.reject(new Error('close event never emitted'))) - ]); - }); - - it('Should not emit any events after close event emitted due to cursor killed', { - // Add a tag that our runner can trigger on - // in this case we are setting that node needs to be higher than 0.10.X to run - metadata: { requires: { topology: ['single', 'replicaset'] } }, - - test: async function () { - const configuration = this.configuration; - await client.connect(); - - const db = client.db(configuration.db); - const collection = db.collection('cursor_limit_skip_correctly'); - - // Insert x number of docs - const ordered = collection.initializeUnorderedBulkOp(); - - for (let i = 0; i < 100; i++) { - ordered.insert({ a: i }); - } - - await ordered.execute({ writeConcern: { w: 1 } }); - - // Let's attempt to skip and limit - const cursor = collection.find({}).batchSize(10); - const stream = cursor.stream(); - stream.on('data', function () { - stream.destroy(); - }); - - const onClose = once(cursor, 'close'); - await cursor.close(); - await onClose; - } - }); - // NOTE: skipped for use of topology manager // it.skip('cursor stream errors', { // // Add a tag that our runner can trigger on diff --git a/test/integration/node-specific/cursor_stream.test.ts b/test/integration/node-specific/cursor_stream.test.ts index 7c5c050f96..53c2f56dba 100644 --- a/test/integration/node-specific/cursor_stream.test.ts +++ b/test/integration/node-specific/cursor_stream.test.ts @@ -1,8 +1,10 @@ -import { once } from 'node:events'; +import { strictEqual } from 'node:assert'; +import { on, once } from 'node:events'; import { expect } from 'chai'; import { Binary, type Collection, type Db, type MongoClient, MongoServerError } from '../../../src'; +import { sleep } from '../../tools/utils'; describe('Cursor Streams', function () { let client: MongoClient; @@ -78,4 +80,157 @@ describe('Cursor Streams', function () { expect(error).to.be.instanceof(MongoServerError); expect(error.message).to.include('unknown operator'); }); + + it('does not auto destroy streams', async function () { + const docs = []; + + for (let i = 0; i < 10; i++) { + docs.push({ a: i + 1 }); + } + + const configuration = this.configuration; + await client.connect(); + + const db = client.db(configuration.db); + const collection = await db.createCollection('does_not_autodestroy_streams'); + + await collection.insertMany(docs, configuration.writeConcernMax()); + + const cursor = collection.find(); + const stream = cursor.stream(); + stream.on('close', () => { + expect.fail('extra close event must not be called'); + }); + stream.on('data', doc => { + expect(doc).to.exist; + }); + stream.resume(); + await once(stream, 'end'); + + await cursor.close(); + }); + + it('immediately destroying a stream prevents the query from executing', { + // Add a tag that our runner can trigger on + // in this case we are setting that node needs to be higher than 0.10.X to run + metadata: { + requires: { topology: ['single', 'replicaset', 'sharded'] } + }, + + test: async function () { + const docs = [{ b: 2 }, { b: 3 }]; + let i = 0, + doneCalled = 0; + + const configuration = this.configuration; + await client.connect(); + + const db = client.db(configuration.db); + const collection = await db.createCollection( + 'immediately_destroying_a_stream_prevents_the_query_from_executing' + ); + + // insert all docs + await collection.insertMany(docs, configuration.writeConcernMax()); + + const cursor = collection.find(); + const stream = cursor.stream(); + + stream.on('data', function () { + i++; + }); + + function testDone() { + return err => { + ++doneCalled; + + if (doneCalled === 1) { + expect(err).to.not.exist; + strictEqual(0, i); + strictEqual(true, cursor.closed); + } + }; + } + + cursor.once('close', testDone('close')); + stream.once('error', testDone('error')); + const promise = once(cursor, 'close'); + + stream.destroy(); + + await cursor.close(); + await promise; + } + }); + + it('destroying a stream stops it', async function () { + const db = client.db(); + await db.dropCollection('destroying_a_stream_stops_it'); + const collection = await db.createCollection('destroying_a_stream_stops_it'); + + const docs = Array.from({ length: 10 }, (_, i) => ({ b: i + 1 })); + + await collection.insertMany(docs); + + const cursor = collection.find(); + const stream = cursor.stream(); + + expect(cursor).property('closed', false); + + const willClose = once(cursor, 'close'); + + const dataEvents = on(stream, 'data'); + + for (let i = 0; i < 5; i++) { + const { + value: [doc] + } = await dataEvents.next(); + expect(doc).property('b', i + 1); + } + + // After 5 successful data events, destroy stream + stream.destroy(); + + // We should get a close event on the stream and a close event on the cursor + // We should **not** get an 'error' or an 'end' event, + // the following will throw if either stream or cursor emitted an 'error' event + await Promise.race([ + willClose, + sleep(100).then(() => Promise.reject(new Error('close event never emitted'))) + ]); + }); + + it('Should not emit any events after close event emitted due to cursor killed', { + // Add a tag that our runner can trigger on + // in this case we are setting that node needs to be higher than 0.10.X to run + metadata: { requires: { topology: ['single', 'replicaset'] } }, + + test: async function () { + const configuration = this.configuration; + await client.connect(); + + const db = client.db(configuration.db); + const collection = db.collection('cursor_limit_skip_correctly'); + + // Insert x number of docs + const ordered = collection.initializeUnorderedBulkOp(); + + for (let i = 0; i < 100; i++) { + ordered.insert({ a: i }); + } + + await ordered.execute({ writeConcern: { w: 1 } }); + + // Let's attempt to skip and limit + const cursor = collection.find({}).batchSize(10); + const stream = cursor.stream(); + stream.on('data', function () { + stream.destroy(); + }); + + const onClose = once(cursor, 'close'); + await cursor.close(); + await onClose; + } + }); });