/
collectHandles.test.js
150 lines (115 loc) · 4.54 KB
/
collectHandles.test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import * as crypto from 'crypto';
import {promises as dns} from 'dns';
import http from 'http';
import {PerformanceObserver} from 'perf_hooks';
import {TLSSocket} from 'tls';
import zlib from 'zlib';
import collectHandles from '../collectHandles';
describe('collectHandles', () => {
it('should collect Timeout', async () => {
const handleCollector = collectHandles();
const interval = setInterval(() => {}, 100);
const openHandles = await handleCollector();
expect(openHandles).toContainEqual(
expect.objectContaining({message: 'Timeout'}),
);
clearInterval(interval);
});
it('should not collect the PerformanceObserver open handle', async () => {
const handleCollector = collectHandles();
const obs = new PerformanceObserver((list, observer) => {});
obs.observe({entryTypes: ['mark']});
const openHandles = await handleCollector();
expect(openHandles).not.toContainEqual(
expect.objectContaining({message: 'PerformanceObserver'}),
);
});
it('should not collect the DNSCHANNEL open handle', async () => {
const handleCollector = collectHandles();
const resolver = new dns.Resolver();
resolver.getServers();
const openHandles = await handleCollector();
expect(openHandles).not.toContainEqual(
expect.objectContaining({message: 'DNSCHANNEL'}),
);
});
it('should not collect the ZLIB open handle', async () => {
const handleCollector = collectHandles();
const decompressed = zlib.inflateRawSync(
Buffer.from('cb2a2d2e5128492d2ec9cc4b0700', 'hex'),
);
const openHandles = await handleCollector();
expect(openHandles).not.toContainEqual(
expect.objectContaining({message: 'ZLIB'}),
);
});
it('should not collect the SIGNREQUEST open handle', async () => {
const handleCollector = collectHandles();
const key =
'-----BEGIN PRIVATE KEY-----\r\nMC4CAQAwBQYDK2VwBCIEIHKj+sVa9WcD' +
'/q2DJUJaf43Kptc8xYuUQA4bOFj9vC8T\r\n-----END PRIVATE KEY-----';
const data = Buffer.from('a');
crypto.sign(null, data, key);
const openHandles = await handleCollector();
expect(openHandles).not.toContainEqual(
expect.objectContaining({message: 'SIGNREQUEST'}),
);
});
it('should collect handles opened in test functions with `done` callbacks', done => {
const handleCollector = collectHandles();
const server = http.createServer((_, response) => response.end('ok'));
server.listen(0, () => {
// Collect results while server is still open.
handleCollector()
.then(openHandles => {
server.close(() => {
expect(openHandles).toContainEqual(
expect.objectContaining({message: 'TCPSERVERWRAP'}),
);
done();
});
})
.catch(done);
});
});
it('should not collect handles that have been queued to close', async () => {
const handleCollector = collectHandles();
const server = http.createServer((_, response) => response.end('ok'));
// Start and stop server.
await new Promise(resolve => server.listen(0, resolve));
await new Promise(resolve => server.close(resolve));
const openHandles = await handleCollector();
expect(openHandles).toHaveLength(0);
});
it('should collect handles indirectly triggered by user code', async () => {
const handleCollector = collectHandles();
// Calling `server.listen` with just a port (e.g. `server.listen(0)`)
// creates a `TCPSERVERWRAP` async resource. However, including a `host`
// option instead creates a `GETADDRINFOREQWRAP` resource that only
// lasts for the lifetime of the `listen()` call, but which *indirectly*
// creates a long-lived `TCPSERVERWRAP` resource. We want to make sure we
// capture that long-lived resource.
const server = new http.Server();
await new Promise(resolve =>
server.listen({host: 'localhost', port: 0}, resolve),
);
const openHandles = await handleCollector();
await new Promise(resolve => server.close(resolve));
expect(openHandles).toContainEqual(
expect.objectContaining({message: 'TCPSERVERWRAP'}),
);
});
it('should not collect the `TLSWRAP` open handle', async () => {
const handleCollector = collectHandles();
const socket = new TLSSocket();
const openHandles = await handleCollector();
expect(openHandles).toHaveLength(0);
});
});