Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3da56ac

Browse filesBrowse files
refackaddaleax
authored andcommitted
test: harden test-dgram-bind-shared-ports
* add `mustCall` and `mustNotCall` to all callbacks * added `known_issue` for port binding PR-URL: #13100 Refs: #13055 Refs: #12999 Refs: #13526 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent f686f73 commit 3da56ac
Copy full SHA for 3da56ac

File tree

Expand file treeCollapse file tree

2 files changed

+125
-31
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

2 files changed

+125
-31
lines changed
Open diff view settings
Collapse file
+56Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
'use strict';
2+
const common = require('../common');
3+
4+
// This test should fail because at present `cluster` does not know how to share
5+
// a socket when `worker1` binds with `port: 0`, and others try to bind to the
6+
// assigned port number from `worker1`
7+
//
8+
// *Note*: since this is a `known_issue` we try to swallow all errors except
9+
// the one we are interested in
10+
11+
const assert = require('assert');
12+
const cluster = require('cluster');
13+
const dgram = require('dgram');
14+
const BYE = 'bye';
15+
16+
if (cluster.isMaster) {
17+
const worker1 = cluster.fork();
18+
19+
// verify that Windows doesn't support this scenario
20+
worker1.on('error', (err) => {
21+
if (err.code === 'ENOTSUP') throw err;
22+
});
23+
24+
worker1.on('message', (msg) => {
25+
if (typeof msg !== 'object') process.exit(0);
26+
if (msg.message !== 'success') process.exit(0);
27+
if (typeof msg.port1 !== 'number') process.exit(0);
28+
29+
const worker2 = cluster.fork({ PRT1: msg.port1 });
30+
worker2.on('message', () => process.exit(0));
31+
worker2.on('exit', (code, signal) => {
32+
// this is the droid we are looking for
33+
assert.strictEqual(code, 0);
34+
assert.strictEqual(signal, null);
35+
});
36+
37+
// cleanup anyway
38+
process.on('exit', () => {
39+
worker1.send(BYE);
40+
worker2.send(BYE);
41+
});
42+
});
43+
// end master code
44+
} else {
45+
// worker code
46+
process.on('message', (msg) => msg === BYE && process.exit(0));
47+
48+
// first worker will bind to '0', second will try the assigned port and fail
49+
const PRT1 = process.env.PRT1 || 0;
50+
const socket1 = dgram.createSocket('udp4', () => {});
51+
socket1.on('error', PRT1 === 0 ? () => {} : assert.fail);
52+
socket1.bind(
53+
{ address: common.localhostIPv4, port: PRT1, exclusive: false },
54+
() => process.send({ message: 'success', port1: socket1.address().port })
55+
);
56+
}
Collapse file

‎test/sequential/test-dgram-bind-shared-ports.js‎

Copy file name to clipboardExpand all lines: test/sequential/test-dgram-bind-shared-ports.js
+69-31Lines changed: 69 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,55 +21,93 @@
2121

2222
'use strict';
2323
const common = require('../common');
24+
25+
// This test asserts the semantics of dgram::socket.bind({ exclusive })
26+
// when called from a cluster.Worker
27+
2428
const assert = require('assert');
2529
const cluster = require('cluster');
2630
const dgram = require('dgram');
31+
const BYE = 'bye';
32+
const WORKER2_NAME = 'wrker2';
2733

2834
if (cluster.isMaster) {
2935
const worker1 = cluster.fork();
3036

3137
if (common.isWindows) {
32-
const checkErrType = (er) => {
33-
assert.strictEqual(er.code, 'ENOTSUP');
38+
worker1.on('error', common.mustCall((err) => {
39+
console.log(err);
40+
assert.strictEqual(err.code, 'ENOTSUP');
3441
worker1.kill();
35-
};
36-
37-
worker1.on('error', common.mustCall(checkErrType, 1));
42+
}));
3843
return;
3944
}
4045

41-
worker1.on('message', (msg) => {
46+
worker1.on('message', common.mustCall((msg) => {
47+
console.log(msg);
4248
assert.strictEqual(msg, 'success');
43-
const worker2 = cluster.fork();
4449

45-
worker2.on('message', (msg) => {
46-
assert.strictEqual(msg, 'socket2:EADDRINUSE');
47-
worker1.kill();
48-
worker2.kill();
49-
});
50-
});
50+
const worker2 = cluster.fork({ WORKER2_NAME });
51+
worker2.on('message', common.mustCall((msg) => {
52+
console.log(msg);
53+
assert.strictEqual(msg, 'socket3:EADDRINUSE');
54+
55+
// finish test
56+
worker1.send(BYE);
57+
worker2.send(BYE);
58+
}));
59+
worker2.on('exit', common.mustCall((code, signal) => {
60+
assert.strictEqual(signal, null);
61+
assert.strictEqual(code, 0);
62+
}));
63+
}));
64+
worker1.on('exit', common.mustCall((code, signal) => {
65+
assert.strictEqual(signal, null);
66+
assert.strictEqual(code, 0);
67+
}));
68+
// end master code
5169
} else {
52-
const socket1 = dgram.createSocket('udp4', common.noop);
53-
const socket2 = dgram.createSocket('udp4', common.noop);
70+
// worker code
71+
process.on('message', common.mustCallAtLeast((msg) => {
72+
if (msg === BYE) process.exit(0);
73+
}), 1);
5474

55-
socket1.on('error', (err) => {
56-
// no errors expected
57-
process.send(`socket1:${err.code}`);
58-
});
75+
const isSecondWorker = process.env.WORKER2_NAME === WORKER2_NAME;
76+
const socket1 = dgram.createSocket('udp4', common.mustNotCall());
77+
const socket2 = dgram.createSocket('udp4', common.mustNotCall());
78+
const socket3 = dgram.createSocket('udp4', common.mustNotCall());
5979

60-
socket2.on('error', (err) => {
61-
// an error is expected on the second worker
62-
process.send(`socket2:${err.code}`);
63-
});
80+
socket1.on('error', (err) => assert.fail(err));
81+
socket2.on('error', (err) => assert.fail(err));
6482

65-
socket1.bind({
66-
address: 'localhost',
67-
port: common.PORT,
68-
exclusive: false
69-
}, () => {
70-
socket2.bind({ port: common.PORT + 1, exclusive: true }, () => {
71-
// the first worker should succeed
83+
// First worker should bind, second should err
84+
const socket3OnBind =
85+
isSecondWorker ?
86+
common.mustNotCall() :
87+
common.mustCall(() => {
88+
const port3 = socket3.address().port;
89+
assert.strictEqual(typeof port3, 'number');
7290
process.send('success');
7391
});
74-
});
92+
// an error is expected only in the second worker
93+
const socket3OnError =
94+
!isSecondWorker ?
95+
common.mustNotCall() :
96+
common.mustCall((err) => {
97+
process.send(`socket3:${err.code}`);
98+
});
99+
const address = common.localhostIPv4;
100+
const opt1 = { address, port: 0, exclusive: false };
101+
const opt2 = { address, port: common.PORT, exclusive: false };
102+
const opt3 = { address, port: common.PORT + 1, exclusive: true };
103+
socket1.bind(opt1, common.mustCall(() => {
104+
const port1 = socket1.address().port;
105+
assert.strictEqual(typeof port1, 'number');
106+
socket2.bind(opt2, common.mustCall(() => {
107+
const port2 = socket2.address().port;
108+
assert.strictEqual(typeof port2, 'number');
109+
socket3.on('error', socket3OnError);
110+
socket3.bind(opt3, socket3OnBind);
111+
}));
112+
}));
75113
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.