Skip to content

Commit

Permalink
test: add more test cases of server.listen option
Browse files Browse the repository at this point in the history
* Test listening with different handle and fd
* Test listening without callback

PR-URL: #11778
  • Loading branch information
joyeecheung committed Apr 11, 2017
1 parent 9f73df5 commit 58a342b
Show file tree
Hide file tree
Showing 3 changed files with 287 additions and 0 deletions.
152 changes: 152 additions & 0 deletions test/parallel/test-net-server-listen-handle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
'use strict';

const common = require('../common');
const assert = require('assert');
const net = require('net');
const fs = require('fs');
const uv = process.binding('uv');
const TCP = process.binding('tcp_wrap').TCP;
const Pipe = process.binding('pipe_wrap').Pipe;

common.refreshTmpDir();

function closeServer() {
return common.mustCall(function() {
this.close();
});
}

// server.listen(pipe) creates a new pipe wrap,
// so server.close() doesn't actually unlink this existing pipe.
// It needs to be unlinked separately via handle.close()
function closePipeServer(handle) {
return common.mustCall(function() {
this.close();
handle.close();
});
}

let counter = 0;

// Avoid conflict with listen-path
function randomPipePath() {
return common.PIPE + '-listen-handle-' + (counter++);
}

function randomHandle(type) {
let handle, errno, handleName;
if (type === 'tcp') {
handle = new TCP();
errno = handle.bind('0.0.0.0', 0);
handleName = 'arbitrary tcp port';
} else {
const path = randomPipePath();
handle = new Pipe();
errno = handle.bind(path);
handleName = `pipe ${path}`;
}

if (errno < 0) { // uv.errname requires err < 0
assert(errno >= 0, `unable to bind ${handleName}: ${uv.errname(errno)}`);
}
if (!common.isWindows) { // fd doesn't work on windows
// err >= 0 but fd = -1, should not happen
assert.notStrictEqual(handle.fd, -1,
`Bound ${handleName} has fd -1 and errno ${errno}`);
}
return handle;
}

// Not a public API, used by child_process
{
// Test listen(tcp)
net.createServer()
.listen(randomHandle('tcp'))
.on('listening', closeServer());
// Test listen(tcp, cb)
net.createServer()
.listen(randomHandle('tcp'), closeServer());
}

function randomPipes(number) {
const arr = [];
for (let i = 0; i < number; ++i) {
arr.push(randomHandle('pipe'));
}
return arr;
}

// Not a public API, used by child_process
if (!common.isWindows) { // Windows doesn't support {fd: <n>}
const handles = randomPipes(2); // generate pipes in advance
// Test listen(pipe)
net.createServer()
.listen(handles[0])
.on('listening', closePipeServer(handles[0]));
// Test listen(pipe, cb)
net.createServer()
.listen(handles[1], closePipeServer(handles[1]));
}

{
// Test listen({handle: tcp}, cb)
net.createServer()
.listen({handle: randomHandle('tcp')}, closeServer());
// Test listen({handle: tcp})
net.createServer()
.listen({handle: randomHandle('tcp')})
.on('listening', closeServer());
// Test listen({_handle: tcp}, cb)
net.createServer()
.listen({_handle: randomHandle('tcp')}, closeServer());
// Test listen({_handle: tcp})
net.createServer()
.listen({_handle: randomHandle('tcp')})
.on('listening', closeServer());
}

if (!common.isWindows) { // Windows doesn't support {fd: <n>}
// Test listen({fd: tcp.fd}, cb)
net.createServer()
.listen({fd: randomHandle('tcp').fd}, closeServer());
// Test listen({fd: tcp.fd})
net.createServer()
.listen({fd: randomHandle('tcp').fd})
.on('listening', closeServer());
}

if (!common.isWindows) { // Windows doesn't support {fd: <n>}
const handles = randomPipes(6); // generate pipes in advance
// Test listen({handle: pipe}, cb)
net.createServer()
.listen({handle: handles[0]}, closePipeServer(handles[0]));
// Test listen({handle: pipe})
net.createServer()
.listen({handle: handles[1]})
.on('listening', closePipeServer(handles[1]));
// Test listen({_handle: pipe}, cb)
net.createServer()
.listen({_handle: handles[2]}, closePipeServer(handles[2]));
// Test listen({_handle: pipe})
net.createServer()
.listen({_handle: handles[3]})
.on('listening', closePipeServer(handles[3]));
// Test listen({fd: pipe.fd}, cb)
net.createServer()
.listen({fd: handles[4].fd}, closePipeServer(handles[4]));
// Test listen({fd: pipe.fd})
net.createServer()
.listen({fd: handles[5].fd})
.on('listening', closePipeServer(handles[5]));
}

if (!common.isWindows) { // Windows doesn't support {fd: <n>}
// Test invalid fd
const fd = fs.openSync(__filename, 'r');
net.createServer()
.listen({fd: fd}, common.mustNotCall())
.on('error', common.mustCall(function(err) {
assert.strictEqual(err + '', 'Error: listen EINVAL');
this.close();
}));
}
86 changes: 86 additions & 0 deletions test/parallel/test-net-server-listen-options.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const net = require('net');
const util = require('util');

function close() { this.close(); }

function listenError(literals, ...values) {
let result = literals[0];
for (const [i, value] of values.entries()) {
const str = value + '';
// Need to escape special characters.
result += str.replace(/[\\^$.*+?()[\]{}|=!<>:-]/g, '\\$&');
result += literals[i + 1];
}
return new RegExp(`Error: Invalid listen argument: ${result}`);
}

{
// Test listen()
net.createServer().listen().on('listening', common.mustCall(close));
// Test listen(cb)
net.createServer().listen(common.mustCall(close));
// Test listen(port)
net.createServer().listen(0).on('listening', common.mustCall(close));
// Test listen({port})
net.createServer().listen({port: 0})
.on('listening', common.mustCall(close));
}

// Test listen(port, cb) and listen({port: port}, cb) combinations
const listenOnPort = [
(port, cb) => net.createServer().listen({port}, cb),
(port, cb) => net.createServer().listen(port, cb)
];

{
const portError = /^RangeError: "port" argument must be >= 0 and < 65536$/;
for (const listen of listenOnPort) {
// Arbitrary unused ports
listen('0', common.mustCall(close));
listen(0, common.mustCall(close));
listen(undefined, common.mustCall(close));
// Test invalid ports
assert.throws(() => listen(-1, common.mustNotCall()), portError);
assert.throws(() => listen(NaN, common.mustNotCall()), portError);
assert.throws(() => listen(123.456, common.mustNotCall()), portError);
assert.throws(() => listen(65536, common.mustNotCall()), portError);
assert.throws(() => listen(1 / 0, common.mustNotCall()), portError);
assert.throws(() => listen(-1 / 0, common.mustNotCall()), portError);
}
// In listen(options, cb), port takes precedence over path
assert.throws(() => {
net.createServer().listen({ port: -1, path: common.PIPE },
common.mustNotCall());
}, portError);
}

{
function shouldFailToListen(options, optionsInMessage) {
// Plain arguments get normalized into an object before
// formatted in message, options objects don't.
if (arguments.length === 1) {
optionsInMessage = options;
}
const block = () => {
net.createServer().listen(options, common.mustNotCall());
};
assert.throws(block, listenError`${optionsInMessage}`,
`expect listen(${util.inspect(options)}) to throw`);
}

shouldFailToListen(null, { port: null });
shouldFailToListen({ port: null });
shouldFailToListen(false, { port: false });
shouldFailToListen({ port: false });
shouldFailToListen(true, { port: true });
shouldFailToListen({ port: true });
// Invalid fd as listen(handle)
shouldFailToListen({ fd: -1 });
// Invalid path in listen(options)
shouldFailToListen({ path: -1 });
// Host without port
shouldFailToListen({ host: 'localhost' });
}
49 changes: 49 additions & 0 deletions test/parallel/test-net-server-listen-path.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'use strict';

const common = require('../common');
const net = require('net');

common.refreshTmpDir();

function closeServer() {
return common.mustCall(function() {
this.close();
});
}

let counter = 0;

// Avoid conflict with listen-handle
function randomPipePath() {
return common.PIPE + '-listen-path-' + (counter++);
}

// Test listen(path)
{
const handlePath = randomPipePath();
net.createServer()
.listen(handlePath)
.on('listening', closeServer());
}

// Test listen({path})
{
const handlePath = randomPipePath();
net.createServer()
.listen({path: handlePath})
.on('listening', closeServer());
}

// Test listen(path, cb)
{
const handlePath = randomPipePath();
net.createServer()
.listen(handlePath, closeServer());
}

// Test listen(path, cb)
{
const handlePath = randomPipePath();
net.createServer()
.listen({path: handlePath}, closeServer());
}

0 comments on commit 58a342b

Please sign in to comment.