Skip to content

Commit 386c366

Browse files
committed
test: some cleanup re: #12890
1 parent 256a11e commit 386c366

File tree

7 files changed

+117
-100
lines changed

7 files changed

+117
-100
lines changed

lib/cursor/ChangeStream.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ class ChangeStream extends EventEmitter {
5454

5555
['close', 'change', 'end', 'error'].forEach(ev => {
5656
this.driverChangeStream.on(ev, data => {
57+
// Sometimes Node driver still polls after close, so
58+
// avoid any uncaught exceptions due to closed change streams
59+
// See tests for gh-7022
60+
if (ev === 'error' && this.closed) {
61+
return;
62+
}
5763
if (data != null && data.fullDocument != null && this.options && this.options.hydrate) {
5864
data.fullDocument = this.options.model.hydrate(data.fullDocument);
5965
}
@@ -71,6 +77,12 @@ class ChangeStream extends EventEmitter {
7177

7278
['close', 'change', 'end', 'error'].forEach(ev => {
7379
this.driverChangeStream.on(ev, data => {
80+
// Sometimes Node driver still polls after close, so
81+
// avoid any uncaught exceptions due to closed change streams
82+
// See tests for gh-7022
83+
if (ev === 'error' && this.closed) {
84+
return;
85+
}
7486
this.emit(ev, data);
7587
});
7688
});

test/collection.capped.test.js

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,12 @@ const Schema = mongoose.Schema;
1919
describe('collections: capped:', function() {
2020
let db;
2121

22-
const connectionsToClose = [];
23-
24-
before(function() {
25-
db = start();
26-
});
27-
28-
after(async function() {
22+
afterEach(async function() {
23+
if (db == null) {
24+
return;
25+
}
2926
await db.close();
30-
await Promise.all(connectionsToClose.map((v) => v.close()));
27+
db = null;
3128
});
3229

3330
it('schemas should have option size', function() {
@@ -41,6 +38,8 @@ describe('collections: capped:', function() {
4138
it('creation', async function() {
4239
this.timeout(15000);
4340

41+
db = start();
42+
4443
await db.dropCollection('Test').catch(() => {});
4544

4645
const capped = new Schema({ key: String });
@@ -55,7 +54,6 @@ describe('collections: capped:', function() {
5554

5655
it('skips when setting autoCreate to false (gh-8566)', async function() {
5756
const db = start();
58-
connectionsToClose.push(db);
5957
this.timeout(30000);
6058
await db.dropDatabase();
6159

test/collection.test.js

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,18 @@ const assert = require('assert');
88
const mongoose = start.mongoose;
99

1010
describe('collections:', function() {
11-
const connectionsToClose = [];
11+
let db = null;
1212

13-
after(async function() {
14-
await Promise.all(connectionsToClose.map((v) => v.close()));
13+
this.afterEach(async function() {
14+
if (db == null) {
15+
return;
16+
}
17+
await db.close();
18+
db = null;
1519
});
1620

1721
it('should buffer commands until connection is established', function(done) {
18-
const db = mongoose.createConnection();
19-
connectionsToClose.push(db);
22+
db = mongoose.createConnection();
2023
const collection = db.collection('test-buffering-collection');
2124
let connected = false;
2225
let insertedId = undefined;
@@ -49,8 +52,7 @@ describe('collections:', function() {
4952
});
5053

5154
it('returns a promise if buffering and no callback (gh-7676)', function(done) {
52-
const db = mongoose.createConnection();
53-
connectionsToClose.push(db);
55+
db = mongoose.createConnection();
5456
const collection = db.collection('gh7676');
5557

5658
const promise = collection.insertOne({ foo: 'bar' }, {})
@@ -152,8 +154,7 @@ describe('collections:', function() {
152154
});
153155

154156
it('buffers for sync methods (gh-10610)', function(done) {
155-
const db = mongoose.createConnection();
156-
connectionsToClose.push(db);
157+
mongoose.createConnection();
157158
const collection = db.collection('gh10610');
158159

159160
collection.find({}, {}, function(err, res) {

test/connection.test.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -773,29 +773,29 @@ describe('connections:', function() {
773773
db2.close();
774774
});
775775

776-
it('cache connections to the same db', function(done) {
776+
it('cache connections to the same db', function() {
777777
const db = start();
778778
const db2 = db.useDb(start.databases[1], { useCache: true });
779779
const db3 = db.useDb(start.databases[1], { useCache: true });
780780

781781
assert.strictEqual(db2, db3);
782-
db.close(done);
782+
return db.close();
783783
});
784784
});
785785

786786
describe('shouldAuthenticate()', function() {
787787
describe('when using standard authentication', function() {
788788
describe('when username and password are undefined', function() {
789-
it('should return false', function(done) {
789+
it('should return false', function() {
790790
const db = mongoose.createConnection(start.uri, {});
791791

792792
assert.equal(db.shouldAuthenticate(), false);
793793

794-
db.close(done);
794+
return db.close();
795795
});
796796
});
797797
describe('when username and password are empty strings', function() {
798-
it('should return false', function(done) {
798+
it('should return false', function() {
799799
const db = mongoose.createConnection(start.uri, {
800800
user: '',
801801
pass: ''
@@ -804,7 +804,7 @@ describe('connections:', function() {
804804

805805
assert.equal(db.shouldAuthenticate(), false);
806806

807-
db.close(done);
807+
return db.close();
808808
});
809809
});
810810
describe('when both username and password are defined', function() {
@@ -823,14 +823,14 @@ describe('connections:', function() {
823823
});
824824
describe('when using MONGODB-X509 authentication', function() {
825825
describe('when username and password are undefined', function() {
826-
it('should return false', function(done) {
826+
it('should return false', function() {
827827
const db = mongoose.createConnection(start.uri, {});
828828
db.on('error', function() {
829829
});
830830

831831
assert.equal(db.shouldAuthenticate(), false);
832832

833-
db.close(done);
833+
return db.close();
834834
});
835835
});
836836
describe('when only username is defined', function() {

test/model.test.js

Lines changed: 1 addition & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,10 @@ const EmbeddedDocument = mongoose.Types.Subdocument;
2020
const MongooseError = mongoose.Error;
2121

2222
describe('Model', function() {
23-
2423
let db;
2524
let Comments;
2625
let BlogPost;
2726

28-
const connectionsToClose = [];
29-
3027
beforeEach(() => db.deleteModel(/.*/));
3128

3229
beforeEach(function() {
@@ -84,7 +81,6 @@ describe('Model', function() {
8481

8582
after(async function() {
8683
await db.close();
87-
await Promise.all(connectionsToClose.map(async(v) => /* v instanceof Promise ? (await v).close() : */ v.close()));
8884
});
8985

9086
afterEach(() => util.clearTestData(db));
@@ -3722,9 +3718,6 @@ describe('Model', function() {
37223718
});
37233719

37243720
it('with positional notation on path not existing in schema (gh-1048)', function(done) {
3725-
const db = start();
3726-
connectionsToClose.push(db);
3727-
37283721
const M = db.model('Test', Schema({ name: 'string' }));
37293722
db.on('open', function() {
37303723
const o = {
@@ -4336,7 +4329,6 @@ describe('Model', function() {
43364329
it('save max bson size error with buffering (gh-3906)', async function() {
43374330
this.timeout(10000);
43384331
const db = start({ noErrorListener: true });
4339-
connectionsToClose.push(db);
43404332
const Test = db.model('Test', { name: Object });
43414333

43424334
const test = new Test({
@@ -4355,7 +4347,6 @@ describe('Model', function() {
43554347
it('reports max bson size error in save (gh-3906)', async function() {
43564348
this.timeout(10000);
43574349
const db = await start({ noErrorListener: true });
4358-
connectionsToClose.push(db);
43594350
const Test = db.model('Test', { name: Object });
43604351

43614352
const test = new Test({
@@ -5339,63 +5330,6 @@ describe('Model', function() {
53395330
assert.equal(changeData.operationType, 'insert');
53405331
assert.equal(changeData.fullDocument.name, 'Child');
53415332
});
5342-
5343-
it('watch() before connecting (gh-5964)', async function() {
5344-
const db = start();
5345-
connectionsToClose.push(db);
5346-
5347-
const MyModel = db.model('Test5964', new Schema({ name: String }));
5348-
5349-
// Synchronous, before connection happens
5350-
const changeStream = MyModel.watch();
5351-
const changed = new global.Promise(resolve => {
5352-
changeStream.once('change', data => resolve(data));
5353-
});
5354-
5355-
await db;
5356-
await MyModel.create({ name: 'Ned Stark' });
5357-
5358-
const changeData = await changed;
5359-
assert.equal(changeData.operationType, 'insert');
5360-
assert.equal(changeData.fullDocument.name, 'Ned Stark');
5361-
});
5362-
5363-
it('watch() close() prevents buffered watch op from running (gh-7022)', async function() {
5364-
const db = start();
5365-
connectionsToClose.push(db);
5366-
const MyModel = db.model('Test', new Schema({}));
5367-
const changeStream = MyModel.watch();
5368-
const ready = new global.Promise(resolve => {
5369-
changeStream.once('data', () => {
5370-
resolve(true);
5371-
});
5372-
setTimeout(resolve, 500, false);
5373-
});
5374-
5375-
changeStream.close();
5376-
await db;
5377-
const readyCalled = await ready;
5378-
assert.strictEqual(readyCalled, false);
5379-
});
5380-
5381-
it('watch() close() closes the stream (gh-7022)', async function() {
5382-
const db = await start();
5383-
connectionsToClose.push(db);
5384-
const MyModel = db.model('Test', new Schema({ name: String }));
5385-
5386-
await MyModel.init();
5387-
5388-
const changeStream = MyModel.watch();
5389-
const closed = new global.Promise(resolve => {
5390-
changeStream.once('close', () => resolve(true));
5391-
});
5392-
5393-
await MyModel.create({ name: 'Hodor' });
5394-
5395-
changeStream.close();
5396-
const closedData = await closed;
5397-
assert.strictEqual(closedData, true);
5398-
});
53995333
});
54005334

54015335
describe('sessions (gh-6362)', function() {
@@ -5429,9 +5363,7 @@ describe('Model', function() {
54295363
});
54305364

54315365
it('startSession() before connecting', async function() {
5432-
54335366
const db = start();
5434-
connectionsToClose.push(db);
54355367

54365368
const MyModel = db.model('Test', new Schema({ name: String }));
54375369

@@ -5446,6 +5378,7 @@ describe('Model', function() {
54465378

54475379
session.endSession();
54485380

5381+
await db.close();
54495382
});
54505383

54515384
it('sets session when pulling a document from db', async function() {

test/model.watch.test.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
'use strict';
2+
3+
const assert = require('assert');
4+
const start = require('./common');
5+
6+
const mongoose = start.mongoose;
7+
const Schema = mongoose.Schema;
8+
9+
describe('model: watch: ', function() {
10+
describe('with buffering', function() {
11+
let db;
12+
13+
before(function() {
14+
if (!process.env.REPLICA_SET) {
15+
this.skip();
16+
}
17+
});
18+
19+
beforeEach(function() {
20+
db = start();
21+
});
22+
23+
afterEach(() => db.close());
24+
25+
it('watch() before connecting (gh-5964)', async function() {
26+
const MyModel = db.model('Test5964', new Schema({ name: String }));
27+
28+
// Synchronous, before connection happens
29+
const changeStream = MyModel.watch();
30+
const changed = new global.Promise(resolve => {
31+
changeStream.once('change', data => resolve(data));
32+
});
33+
34+
await db.asPromise();
35+
await MyModel.create({ name: 'Ned Stark' });
36+
37+
const changeData = await changed;
38+
assert.equal(changeData.operationType, 'insert');
39+
assert.equal(changeData.fullDocument.name, 'Ned Stark');
40+
});
41+
42+
it('watch() close() prevents buffered watch op from running (gh-7022)', async function() {
43+
const MyModel = db.model('Test', new Schema({}));
44+
const changeStream = MyModel.watch();
45+
const ready = new global.Promise(resolve => {
46+
changeStream.once('data', () => {
47+
resolve(true);
48+
});
49+
setTimeout(resolve, 500, false);
50+
});
51+
52+
const close = changeStream.close();
53+
await db.asPromise();
54+
const readyCalled = await ready;
55+
assert.strictEqual(readyCalled, false);
56+
57+
await close;
58+
});
59+
60+
it('watch() close() closes the stream (gh-7022)', async function() {
61+
const MyModel = db.model('Test', new Schema({ name: String }));
62+
63+
await db.asPromise();
64+
await MyModel.init();
65+
66+
const changeStream = MyModel.watch();
67+
const closed = new global.Promise(resolve => {
68+
changeStream.once('close', () => resolve(true));
69+
});
70+
71+
await MyModel.create({ name: 'Hodor' });
72+
73+
await changeStream.close();
74+
75+
const closedData = await closed;
76+
assert.strictEqual(closedData, true);
77+
});
78+
});
79+
});

0 commit comments

Comments
 (0)