net,tls: add abort signal support to connect · nodejs/node@669b81c
1+'use strict';
2+const common = require('../common');
3+const net = require('net');
4+const assert = require('assert');
5+const server = net.createServer();
6+const { getEventListeners, once } = require('events');
7+8+const liveConnections = new Set();
9+10+server.listen(0, common.mustCall(async () => {
11+const port = server.address().port;
12+const host = 'localhost';
13+const socketOptions = (signal) => ({ port, host, signal });
14+server.on('connection', (connection) => {
15+liveConnections.add(connection);
16+connection.on('close', () => {
17+liveConnections.delete(connection);
18+});
19+});
20+21+const assertAbort = async (socket, testName) => {
22+try {
23+await once(socket, 'close');
24+assert.fail(`close ${testName} should have thrown`);
25+} catch (err) {
26+assert.strictEqual(err.name, 'AbortError');
27+}
28+};
29+30+async function postAbort() {
31+const ac = new AbortController();
32+const { signal } = ac;
33+const socket = net.connect(socketOptions(signal));
34+assert.strictEqual(getEventListeners(signal, 'abort').length, 1);
35+ac.abort();
36+await assertAbort(socket, 'postAbort');
37+}
38+39+async function preAbort() {
40+const ac = new AbortController();
41+const { signal } = ac;
42+ac.abort();
43+const socket = net.connect(socketOptions(signal));
44+assert.strictEqual(getEventListeners(signal, 'abort').length, 0);
45+await assertAbort(socket, 'preAbort');
46+}
47+48+async function tickAbort() {
49+const ac = new AbortController();
50+const { signal } = ac;
51+setImmediate(() => ac.abort());
52+const socket = net.connect(socketOptions(signal));
53+assert.strictEqual(getEventListeners(signal, 'abort').length, 1);
54+await assertAbort(socket, 'tickAbort');
55+}
56+57+async function testConstructor() {
58+const ac = new AbortController();
59+const { signal } = ac;
60+ac.abort();
61+const socket = new net.Socket(socketOptions(signal));
62+assert.strictEqual(getEventListeners(signal, 'abort').length, 0);
63+await assertAbort(socket, 'testConstructor');
64+}
65+66+async function testConstructorPost() {
67+const ac = new AbortController();
68+const { signal } = ac;
69+const socket = new net.Socket(socketOptions(signal));
70+assert.strictEqual(getEventListeners(signal, 'abort').length, 1);
71+ac.abort();
72+await assertAbort(socket, 'testConstructorPost');
73+}
74+75+async function testConstructorPostTick() {
76+const ac = new AbortController();
77+const { signal } = ac;
78+const socket = new net.Socket(socketOptions(signal));
79+assert.strictEqual(getEventListeners(signal, 'abort').length, 1);
80+setImmediate(() => ac.abort());
81+await assertAbort(socket, 'testConstructorPostTick');
82+}
83+84+await postAbort();
85+await preAbort();
86+await tickAbort();
87+await testConstructor();
88+await testConstructorPost();
89+await testConstructorPostTick();
90+91+// Killing the net.socket without connecting hangs the server.
92+for (const connection of liveConnections) {
93+connection.destroy();
94+}
95+server.close(common.mustCall());
96+}));