Skip to content

Commit 1c8e20f

Browse files
most of tree reformatting done
1 parent 9ed1528 commit 1c8e20f

File tree

5 files changed

+217
-51
lines changed

5 files changed

+217
-51
lines changed

logs.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
"ActiveResources":["FSReqPromise","GetAddrInfoReqWrap","TCPSocketWrap","Timeout"],
2+
"newResources":[{"type":"tcp","is_active":false,"is_referenced":true,"address":"0x0000000135e04560","localEndpoint":null,"remoteEndpoint":null,"sendBufferSize":0,"recvBufferSize":0,"writeQueueSize":0,"readable":false,"writable":false}],
3+
"exitCode":0,

test/integration/node-specific/client_close.test.ts

Lines changed: 142 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,40 @@
11
import { expect } from 'chai';
2+
import * as fs from 'fs';
23

34
import { type TestConfiguration } from '../../tools/runner/config';
45
import { runScriptAndGetProcessInfo } from './resource_tracking_script_builder';
6+
import { sleep } from '../../tools/utils';
57

6-
describe.skip('client.close() Integration', () => {
7-
let config: TestConfiguration;
8+
describe.skip('MongoClient.close() Integration', () => {
9+
// note: these tests are set-up in accordance of the resource ownership tree
810

11+
let config: TestConfiguration;
912
beforeEach(function () {
1013
config = this.configuration;
1114
});
1215

13-
describe('MongoClient', () => {
14-
describe('when client is being instantiated and reads a long docker file', () => {
15-
// our docker env detection uses fs.access which will not be aborted until after it runs
16-
// fs.access does not support abort signals
16+
describe('Node.js resource: TLS File read', () => {
17+
describe('when client is connecting and reads an infinite TLS file', () => {
18+
it('the file read is interrupted by client.close()', async function () {
19+
await runScriptAndGetProcessInfo(
20+
'tls-file-read',
21+
config,
22+
async function run({ MongoClient, uri, log, chai }) {
23+
const devZeroFilePath = '/dev/zero';
24+
const client = new MongoClient(uri, { tlsCertificateKeyFile: devZeroFilePath });
25+
client.connect();
26+
log({ ActiveResources: process.getActiveResourcesInfo() });
27+
chai.expect(process.getActiveResourcesInfo()).to.include('FSReqPromise');
28+
await client.close();
29+
chai.expect(process.getActiveResourcesInfo()).to.not.include('FSReqPromise');
30+
}
31+
);
32+
});
33+
});
34+
});
35+
36+
describe('Node.js resource: .dockerenv file access', () => {
37+
describe('when client is connecting and reads an infinite .dockerenv file', () => {
1738
it('the file read is not interrupted by client.close()', async () => {
1839
await runScriptAndGetProcessInfo(
1940
'docker-read',
@@ -29,35 +50,129 @@ describe.skip('client.close() Integration', () => {
2950
);
3051
});
3152
});
53+
});
3254

33-
describe('when client is connecting and reads an infinite TLS file', () => {
34-
it('the file read is interrupted by client.close()', async function () {
35-
await runScriptAndGetProcessInfo(
36-
'tls-file-read',
37-
config,
38-
async function run({ MongoClient, uri }) {
39-
const devZeroFilePath = '/dev/zero';
40-
const client = new MongoClient(uri, { tlsCertificateKeyFile: devZeroFilePath });
41-
client.connect();
42-
log({ ActiveResources: process.getActiveResourcesInfo() });
43-
chai.expect(process.getActiveResourcesInfo()).to.include('FSReqPromise');
44-
await client.close();
45-
setTimeout(
46-
() => chai.expect(process.getActiveResourcesInfo()).to.not.include('FSReqPromise'),
47-
1000
48-
);
49-
}
50-
);
55+
describe('MongoClientAuthProviders', () => {
56+
describe('Node.js resource: Token file read', () => {
57+
describe('when MongoClientAuthProviders is instantiated and token file read hangs', () => {
58+
it('the file read is interrupted by client.close()', async () => {});
5159
});
5260
});
5361
});
5462

55-
describe('MongoClientAuthProviders', () => {
56-
describe('when MongoClientAuthProviders is instantiated and token file read hangs', () => {
57-
it('the file read is interrupted by client.close()', async () => {});
63+
describe('Topology', () => {
64+
describe('Node.js resource: Server Selection Timer', () => {
65+
66+
});
67+
68+
describe('Server', () => {
69+
describe('Monitor', () => {
70+
describe('MonitorInterval', () => {
71+
describe('Node.js resource: Timer', () => {
72+
73+
});
74+
});
75+
76+
describe('Connection Monitoring', () => {
77+
// connection monitoring is by default turned on - with the exception of load-balanced mode
78+
describe('Node.js resource: Socket', () => {
79+
it('no sockets remain after client.close()', async () => {
80+
// TODO: skip for LB mode
81+
});
82+
});
83+
describe('Server resource: connection thread', () => {
84+
85+
});
86+
});
87+
88+
describe('RTT Pinger', () => {
89+
describe('Node.js resource: Timer', () => {
90+
91+
});
92+
describe('Connection', () => {
93+
describe('Node.js resource: Socket', () => {
94+
95+
});
96+
describe('Server resource: connection thread', () => {
97+
98+
});
99+
});
100+
});
101+
});
102+
103+
describe('ConnectionPool', () => {
104+
describe('Node.js resource: minPoolSize timer', () => {
105+
106+
});
107+
108+
describe('Node.js resource: checkOut Timer', () => { // waitQueueTimeoutMS
109+
110+
});
111+
112+
describe('Connection', () => {
113+
describe('Node.js resource: Socket', () => {
114+
115+
});
116+
describe('Node.js resource: Socket', () => {
117+
118+
});
119+
});
120+
});
121+
});
122+
123+
describe('SrvPoller', () => {
124+
describe('Node.js resource: Timer', () => {
125+
126+
});
127+
});
128+
});
129+
130+
describe('ClientSession (Implicit)', () => {
131+
describe('Server resource: LSID/ServerSession', () => {
132+
});
133+
134+
describe('Server resource: Transactions', () => {
135+
});
136+
});
137+
138+
describe('ClientSession (Explicit)', () => {
139+
describe('Server resource: LSID/ServerSession', () => {
140+
});
141+
142+
describe('Server resource: Transactions', () => {
143+
});
144+
});
145+
146+
describe('AutoEncrypter', () => {
147+
describe('KMS Request', () => {
148+
describe('Node.js resource: TLS file read', () => {
149+
150+
});
151+
describe('Node.js resource: Socket', () => {
152+
153+
});
154+
});
155+
});
156+
157+
describe('ClientEncryption', () => {
158+
describe('KMS Request', () => {
159+
describe('Node.js resource: TLS file read', () => {
160+
161+
});
162+
describe('Node.js resource: Socket', () => {
163+
164+
});
165+
});
166+
});
167+
168+
describe('Server resource: Cursor', () => {
169+
describe('after cursors are created', () => {
170+
it('all active server-side cursors are closed by client.close()', async () => {});
58171
});
59172
});
173+
});
60174

175+
describe.skip('OLD', () => {
61176
describe('Topology', () => {
62177
describe('after a Topology is created through client.connect()', () => {
63178
it('server selection timers are cleaned up by client.close()', async () => {
@@ -146,23 +261,6 @@ describe.skip('client.close() Integration', () => {
146261
});
147262

148263
describe('Connection', () => {
149-
describe('when connection monitoring is turned on', () => {
150-
// connection monitoring is by default turned on - with the exception of load-balanced mode
151-
it('no sockets remain after client.close()', async () => {
152-
// TODO: skip for LB mode
153-
await runScriptAndGetProcessInfo(
154-
'connection-monitoring',
155-
config,
156-
async function run({ MongoClient, uri }) {
157-
const client = new MongoClient(uri);
158-
await client.connect();
159-
await client.close();
160-
}
161-
);
162-
});
163-
164-
it('no server-side connection threads remain after client.close()', async () => {});
165-
});
166264

167265
describe('when rtt monitoring is turned on', () => {
168266
it('no sockets remain after client.close()', async () => {});
@@ -182,10 +280,4 @@ describe.skip('client.close() Integration', () => {
182280
it('no server-side connection threads remain after client.close()', async () => {});
183281
});
184282
});
185-
186-
describe('Cursor', () => {
187-
describe('after cursors are created', () => {
188-
it('all active server-side cursors are closed by client.close()', async () => {});
189-
});
190-
});
191283
});

test/integration/node-specific/resource_tracking_script_builder.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ export type HeapResourceTestFunction = (options: {
2121
export type ProcessResourceTestFunction = (options: {
2222
MongoClient: typeof MongoClient;
2323
uri: string;
24+
log: (out: any) => void;
25+
chai: { expect: Function };
2426
}) => Promise<void>;
2527

2628
const HEAP_RESOURCE_SCRIPT_PATH = path.resolve(

test/tools/fixtures/process_resource_script.in.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ async function main() {
4040
process.on('beforeExit', () => {
4141
log({ beforeExitHappened: true });
4242
});
43-
run({ MongoClient, uri });
43+
await run({ MongoClient, uri });
4444
log({ newResources: getNewResourceArray() });
4545
}
4646

tls-file-read.cjs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
'use strict';
2+
3+
/* eslint-disable no-undef */
4+
/* eslint-disable no-unused-vars */
5+
const driverPath = "/Users/aditi.khare/Desktop/node-mongodb-native/lib";
6+
const func = (async function run({ MongoClient, uri }) {
7+
const devZeroFilePath = '/dev/zero';
8+
const client = new MongoClient(uri, { tlsCertificateKeyFile: devZeroFilePath });
9+
client.connect();
10+
log({ ActiveResources: process.getActiveResourcesInfo() });
11+
(0, chai_1.expect)(process.getActiveResourcesInfo()).to.include('FSReqPromise');
12+
await client.close();
13+
setTimeout(() => chai.expect(process.getActiveResourcesInfo()).to.not.include('FSReqPromise'), 1000);
14+
});
15+
const name = "tls-file-read";
16+
const uri = "mongodb://bob:pwd123@localhost:31000/integration_tests?replicaSet=rs&authSource=admin";
17+
18+
const { MongoClient } = require(driverPath);
19+
const process = require('node:process');
20+
const v8 = require('node:v8');
21+
const util = require('node:util');
22+
const timers = require('node:timers');
23+
const fs = require('node:fs');
24+
const chai = require('chai');
25+
const { setTimeout } = require('timers');
26+
27+
let originalReport;
28+
const logFile = 'logs.txt';
29+
30+
const run = func;
31+
32+
// Returns an array containing new the resources created after script start
33+
function getNewResourceArray() {
34+
let currReport = process.report.getReport().libuv;
35+
const originalReportAddresses = originalReport.map(resource => resource.address);
36+
currReport = currReport.filter(resource => !originalReportAddresses.includes(resource.address));
37+
return currReport;
38+
}
39+
40+
function log(message) {
41+
// remove outer parentheses for easier parsing
42+
const messageToLog = JSON.stringify(message).slice(1, -1) + ', \n';
43+
fs.writeFileSync(logFile, messageToLog, { flag: 'a' });
44+
}
45+
46+
async function main() {
47+
originalReport = process.report.getReport().libuv;
48+
process.on('beforeExit', () => {
49+
log({ beforeExitHappened: true });
50+
});
51+
run({ MongoClient, uri });
52+
log({ newResources: getNewResourceArray() });
53+
}
54+
55+
main()
56+
.then(() => {
57+
log({ exitCode: 0 });
58+
})
59+
.catch(() => {
60+
log({ exitCode: 1 });
61+
});
62+
63+
setTimeout(() => {
64+
// this means something was in the event loop such that it hung for more than 10 seconds
65+
// so we kill the process
66+
log({ exitCode: 99 });
67+
process.exit(99);
68+
// using `unref` will ensure this setTimeout call is not a resource / does not keep the event loop running
69+
}, 10000).unref();

0 commit comments

Comments
 (0)