Skip to content

Commit 7b830f4

Browse files
joyeecheungjasnell
authored andcommitted
test: add more and refactor test cases to net.connect
PR-URL: #11847 Reviewed-By: James M Snell <[email protected]>
1 parent db39273 commit 7b830f4

6 files changed

+498
-180
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
// Copyright Joyent, Inc. and other Node contributors.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a
4+
// copy of this software and associated documentation files (the
5+
// "Software"), to deal in the Software without restriction, including
6+
// without limitation the rights to use, copy, modify, merge, publish,
7+
// distribute, sublicense, and/or sell copies of the Software, and to permit
8+
// persons to whom the Software is furnished to do so, subject to the
9+
// following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included
12+
// in all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
22+
'use strict';
23+
const common = require('../common');
24+
const assert = require('assert');
25+
const net = require('net');
26+
27+
function testClients(getSocketOpt, getConnectOpt, getConnectCb) {
28+
const cloneOptions = (index) =>
29+
Object.assign({}, getSocketOpt(index), getConnectOpt(index));
30+
return [
31+
net.connect(cloneOptions(0), getConnectCb(0)),
32+
net.connect(cloneOptions(1))
33+
.on('connect', getConnectCb(1)),
34+
net.createConnection(cloneOptions(2), getConnectCb(2)),
35+
net.createConnection(cloneOptions(3))
36+
.on('connect', getConnectCb(3)),
37+
new net.Socket(getSocketOpt(4)).connect(getConnectOpt(4), getConnectCb(4)),
38+
new net.Socket(getSocketOpt(5)).connect(getConnectOpt(5))
39+
.on('connect', getConnectCb(5))
40+
];
41+
}
42+
43+
const CLIENT_VARIANTS = 6; // Same length as array above
44+
const forAllClients = (cb) => common.mustCall(cb, CLIENT_VARIANTS);
45+
46+
// Test allowHalfOpen
47+
{
48+
let clientReceivedFIN = 0;
49+
let serverConnections = 0;
50+
let clientSentFIN = 0;
51+
let serverReceivedFIN = 0;
52+
const server = net.createServer({
53+
allowHalfOpen: true
54+
})
55+
.on('connection', forAllClients(function serverOnConnection(socket) {
56+
const serverConnection = ++serverConnections;
57+
let clientId;
58+
console.error(`${serverConnections} 'connection' emitted on server`);
59+
socket.resume();
60+
// 'end' on each socket must not be emitted twice
61+
socket.on('data', common.mustCall(function(data) {
62+
clientId = data.toString();
63+
console.error(`${serverConnection} server connection is started ` +
64+
`by client No. ${clientId}`);
65+
}));
66+
socket.on('end', common.mustCall(function() {
67+
serverReceivedFIN++;
68+
console.error(`Server recieved FIN sent by No. ${clientId}`);
69+
if (serverReceivedFIN === CLIENT_VARIANTS) {
70+
setTimeout(() => {
71+
server.close();
72+
console.error(`No. ${clientId} connection is closing server: ` +
73+
`${serverReceivedFIN} FIN received by server, ` +
74+
`${clientReceivedFIN} FIN received by client, ` +
75+
`${clientSentFIN} FIN sent by client, ` +
76+
`${serverConnections} FIN sent by server`);
77+
}, 50);
78+
}
79+
}, 1));
80+
socket.end();
81+
console.error(`Server has sent ${serverConnections} FIN`);
82+
}))
83+
.on('close', common.mustCall(function serverOnClose() {
84+
console.error('Server has been closed: ' +
85+
`${serverReceivedFIN} FIN received by server, ` +
86+
`${clientReceivedFIN} FIN received by client, ` +
87+
`${clientSentFIN} FIN sent by client, ` +
88+
`${serverConnections} FIN sent by server`);
89+
}))
90+
.listen(0, 'localhost', common.mustCall(function serverOnListen() {
91+
const host = 'localhost';
92+
const port = server.address().port;
93+
94+
console.error(`Server starts at ${host}:${port}`);
95+
const getSocketOpt = () => ({ allowHalfOpen: true });
96+
const getConnectOpt = () => ({ host, port });
97+
const getConnectCb = (index) => common.mustCall(function clientOnConnect() {
98+
const client = this;
99+
console.error(`'connect' emitted on Client ${index}`);
100+
client.resume();
101+
client.on('end', common.mustCall(function clientOnEnd() {
102+
setTimeout(function() {
103+
// when allowHalfOpen is true, client must still be writable
104+
// after the server closes the connections, but not readable
105+
console.error(`No. ${index} client received FIN`);
106+
assert(!client.readable);
107+
assert(client.writable);
108+
assert(client.write(index + ''));
109+
client.end();
110+
clientSentFIN++;
111+
console.error(`No. ${index} client sent FIN, ` +
112+
`${clientSentFIN} have been sent`);
113+
}, 50);
114+
}));
115+
client.on('close', common.mustCall(function clientOnClose() {
116+
clientReceivedFIN++;
117+
console.error(`No. ${index} connection has been closed by both ` +
118+
`sides, ${clientReceivedFIN} clients have closed`);
119+
}));
120+
});
121+
122+
testClients(getSocketOpt, getConnectOpt, getConnectCb);
123+
}));
124+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
'use strict';
2+
const common = require('../common');
3+
const assert = require('assert');
4+
const net = require('net');
5+
const Pipe = process.binding('pipe_wrap').Pipe;
6+
7+
if (common.isWindows) {
8+
common.skip('Does not support wrapping sockets with fd on Windows');
9+
return;
10+
}
11+
12+
common.refreshTmpDir();
13+
14+
function testClients(getSocketOpt, getConnectOpt, getConnectCb) {
15+
const cloneOptions = (index) =>
16+
Object.assign({}, getSocketOpt(index), getConnectOpt(index));
17+
return [
18+
net.connect(cloneOptions(0), getConnectCb(0)),
19+
net.connect(cloneOptions(1))
20+
.on('connect', getConnectCb(1)),
21+
net.createConnection(cloneOptions(2), getConnectCb(2)),
22+
net.createConnection(cloneOptions(3))
23+
.on('connect', getConnectCb(3)),
24+
new net.Socket(getSocketOpt(4)).connect(getConnectOpt(4), getConnectCb(4)),
25+
new net.Socket(getSocketOpt(5)).connect(getConnectOpt(5))
26+
.on('connect', getConnectCb(5))
27+
];
28+
}
29+
30+
const CLIENT_VARIANTS = 6; // Same length as array above
31+
const forAllClients = (cb) => common.mustCall(cb, CLIENT_VARIANTS);
32+
33+
// Test Pipe fd is wrapped correctly
34+
{
35+
const prefix = `${common.PIPE}-net-connect-options-fd`;
36+
const serverPath = `${prefix}-server`;
37+
let counter = 0;
38+
let socketCounter = 0;
39+
const handleMap = new Map();
40+
const server = net.createServer()
41+
.on('connection', forAllClients(function serverOnConnection(socket) {
42+
let clientFd;
43+
socket.on('data', common.mustCall(function(data) {
44+
clientFd = data.toString();
45+
console.error(`[Pipe]Received data from fd ${clientFd}`);
46+
socket.end();
47+
}));
48+
socket.on('end', common.mustCall(function() {
49+
counter++;
50+
console.error(`[Pipe]Received end from fd ${clientFd}, total ${counter}`);
51+
if (counter === CLIENT_VARIANTS) {
52+
setTimeout(() => {
53+
console.error(`[Pipe]Server closed by fd ${clientFd}`);
54+
server.close();
55+
}, 10);
56+
}
57+
}, 1));
58+
}))
59+
.on('close', function() {
60+
setTimeout(() => {
61+
for (const pair of handleMap) {
62+
console.error(`[Pipe]Clean up handle with fd ${pair[1].fd}`);
63+
pair[1].close(); // clean up handles
64+
}
65+
}, 10);
66+
})
67+
.on('error', function(err) {
68+
console.error(err);
69+
assert.fail(null, null, '[Pipe server]' + err);
70+
})
71+
.listen({path: serverPath}, common.mustCall(function serverOnListen() {
72+
const getSocketOpt = (index) => {
73+
const handle = new Pipe();
74+
const err = handle.bind(`${prefix}-client-${socketCounter++}`);
75+
assert(err >= 0, '' + err);
76+
assert.notStrictEqual(handle.fd, -1);
77+
handleMap.set(index, handle);
78+
console.error(`[Pipe]Bound handle with Pipe ${handle.fd}`);
79+
return { fd: handle.fd, readable: true, writable: true };
80+
};
81+
const getConnectOpt = () => ({
82+
path: serverPath
83+
});
84+
const getConnectCb = (index) => common.mustCall(function clientOnConnect() {
85+
const client = this;
86+
// Test if it's wrapping an existing fd
87+
assert(handleMap.has(index));
88+
const oldHandle = handleMap.get(index);
89+
assert.strictEqual(oldHandle.fd, this._handle.fd);
90+
client.write(oldHandle.fd + '');
91+
console.error(`[Pipe]Sending data through fd ${oldHandle.fd}`);
92+
client.on('error', function(err) {
93+
console.error(err);
94+
assert.fail(null, null, '[Pipe Client]' + err);
95+
});
96+
});
97+
98+
testClients(getSocketOpt, getConnectOpt, getConnectCb);
99+
}));
100+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
'use strict';
2+
const common = require('../common');
3+
const net = require('net');
4+
5+
// This file tests the option handling of net.connect,
6+
// net.createConnect, and new Socket().connect
7+
8+
common.refreshTmpDir();
9+
10+
const CLIENT_VARIANTS = 12;
11+
12+
// Test connect(path)
13+
{
14+
const prefix = `${common.PIPE}-net-connect-options-path`;
15+
const serverPath = `${prefix}-server`;
16+
let counter = 0;
17+
const server = net.createServer()
18+
.on('connection', common.mustCall(function(socket) {
19+
socket.end('ok');
20+
}, CLIENT_VARIANTS))
21+
.listen(serverPath, common.mustCall(function() {
22+
const getConnectCb = () => common.mustCall(function() {
23+
const client = this;
24+
client.end();
25+
client.on('close', common.mustCall(function() {
26+
counter++;
27+
if (counter === CLIENT_VARIANTS) {
28+
server.close();
29+
}
30+
}));
31+
});
32+
33+
// CLIENT_VARIANTS depends on the following code
34+
net.connect(serverPath, getConnectCb());
35+
net.connect(serverPath)
36+
.on('connect', getConnectCb());
37+
net.createConnection(serverPath, getConnectCb());
38+
net.createConnection(serverPath)
39+
.on('connect', getConnectCb());
40+
new net.Socket().connect(serverPath, getConnectCb());
41+
new net.Socket().connect(serverPath)
42+
.on('connect', getConnectCb());
43+
net.connect({path: serverPath}, getConnectCb());
44+
net.connect({path: serverPath})
45+
.on('connect', getConnectCb());
46+
net.createConnection({path: serverPath}, getConnectCb());
47+
net.createConnection({path: serverPath})
48+
.on('connect', getConnectCb());
49+
new net.Socket().connect({path: serverPath}, getConnectCb());
50+
new net.Socket().connect({path: serverPath})
51+
.on('connect', getConnectCb());
52+
}));
53+
}

0 commit comments

Comments
 (0)