diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..59d90e7 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,4 @@ +test/fixtures +logs +run +coverage diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..c799fe5 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,3 @@ +{ + "extends": "eslint-config-egg" +} diff --git a/.jshintignore b/.jshintignore deleted file mode 100644 index 9d1cf03..0000000 --- a/.jshintignore +++ /dev/null @@ -1,4 +0,0 @@ -.git/ -node_modules/ -coverage/ -docs/ diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 649e9bf..0000000 --- a/.jshintrc +++ /dev/null @@ -1,33 +0,0 @@ -{ - "indent": 2, - "latedef": "nofunc", - "newcap": true, - "curly": true, - "eqeqeq": true, - "eqnull": true, - "strict": true, - "undef": true, - "unused": true, - "laxcomma": false, - "asi": false, - "boss": false, - "expr": true, - "sub": true, - "quotmark": "single", - "loopfunc": false, - "lastsemic": true, - "funcscope": false, - "esnext": true, - "noyield": true, - "browser": true, - "nonstandard": true, - "devel": true, - "node": true, - "mocha": true, - "validthis": true, - "globals": { - "define": false - } -} - - diff --git a/.travis.yml b/.travis.yml index a614bf7..5ec1467 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,12 @@ +sudo: false language: node_js node_js: - - "4" - - "5" - - "6" -sudo: false -script: make travis -after_script: "npm install coveralls@2 && cat ./coverage/lcov.info | coveralls" + - '4' + - '6' + - '7' +install: + - npm i npminstall && npminstall +script: + - npm run ci +after_script: + - npminstall codecov && codecov diff --git a/Makefile b/Makefile deleted file mode 100644 index da2dd7a..0000000 --- a/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -git_version = $$(git branch 2>/dev/null | sed -e '/^[^*]/d'-e's/* \(.*\)/\1/') -npm_bin= $$(npm bin) - -all: test -install: - @npm install -server: - npm i startserver --save-dev - ${npm_bin}/startserver -s -p 8080 & -pre-test: server - sleep 5 -test: - @node \ - ${npm_bin}/istanbul cover ${npm_bin}/_mocha \ - -- \ - --timeout 10000 \ - --require co-mocha -travis: install pre-test - @node \ - ${npm_bin}/istanbul cover ${npm_bin}/_mocha \ - --report lcovonly \ - -- -u exports \ - --timeout 10000 \ - --require co-mocha \ - --bail -jshint: - @${npm_bin}/jshint . -.PHONY: test diff --git a/README.md b/README.md index 408a311..c701931 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,8 @@ --- [![NPM version][npm-image]][npm-url] -[![node version][node-image]][node-url] [![build status][travis-image]][travis-url] -[![Coveralls][coveralls-image]][coveralls-url] +[![Test coverage][codecov-image]][codecov-url] [![npm download][download-image]][download-url] [logo-image]: ./logo.png @@ -14,10 +13,8 @@ [npm-url]: https://npmjs.org/package/detect-port [travis-image]: https://img.shields.io/travis/node-modules/detect-port.svg?style=flat-square [travis-url]: https://travis-ci.org/node-modules/detect-port -[coveralls-image]: https://img.shields.io/coveralls/node-modules/detect-port.svg?style=flat-square -[coveralls-url]: https://coveralls.io/r/node-modules/detect-port?branch=master -[node-image]: https://img.shields.io/badge/node.js-%3E=_4-red.svg?style=flat-square -[node-url]: http://nodejs.org/download/ +[codecov-image]: https://codecov.io/gh/node-modules/detect-port/branch/master/graph/badge.svg +[codecov-url]: https://codecov.io/gh/node-modules/detect-port [download-image]: https://img.shields.io/npm/dm/detect-port.svg?style=flat-square [download-url]: https://npmjs.org/package/detect-port @@ -25,11 +22,11 @@ ## Usage -```shell +```bash $ npm i detect-port --save ``` -```javascript +```js const detect = require('detect-port'); /** diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..2efd0fa --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,16 @@ +environment: + matrix: + - nodejs_version: '4' + - nodejs_version: '6' + - nodejs_version: '7' + +install: + - ps: Install-Product node $env:nodejs_version + - npm i npminstall && node_modules\.bin\npminstall + +test_script: + - node --version + - npm --version + - npm run ci + +build: off diff --git a/lib/detect-port.js b/lib/detect-port.js index 6dff69d..c1cb636 100644 --- a/lib/detect-port.js +++ b/lib/detect-port.js @@ -1,73 +1,39 @@ 'use strict'; +const debug = require('debug')('detect-port'); const net = require('net'); -module.exports = function() { - const args = Array.prototype.slice.call(arguments); - - const promise = new Promise((resolve, reject) => { - if (!args.length) { - return reject('wrong number of arguments'); - } - - const port = parseInt(args[0], 10); - - if (isNaN(port)) { - return reject(`wrong type of arguments with: '${args[0]}'`); - } - - const loop = port => { - const socket = new net.Socket(); - - socket.once('error', () => { - socket.removeAllListeners('error'); - socket.removeAllListeners('connect'); - socket.end(); - socket.destroy(); - socket.unref(); - - const server = new net.Server(); - - server.on('error', () => { - port++; - loop(port); - }); - - server.listen(port, () => { - server.once('close', () => { - resolve(port); - }); - server.close(); - }); - }); - - socket.once('connect', () => { - port++; - loop(port); - socket.removeAllListeners('error'); - socket.removeAllListeners('connect'); - socket.end(); - socket.destroy(); - socket.unref(); - }); +module.exports = (port, callback) => { + if (typeof port === 'function') { + callback = port; + port = null; + } + if (typeof callback === 'function') { + return tryListen(port, callback); + } + // promise + return new Promise(resolve => { + tryListen(port, (_, realPort) => { + resolve(realPort); + }); + }); +}; - socket.connect({ - port: port - }); - }; +function tryListen(port, callback) { + port = parseInt(port) || 0; + const server = new net.Server(); - loop(port); + server.on('error', err => { + debug('listen %s error: %s', port, err); + port = 0; + server.close(); + return tryListen(port, callback); }); - if (args.length > 1) { - const cb = args[1]; - - promise.then(data => { - process.nextTick(cb.bind(null, null, data)); - }, err => { - process.nextTick(cb.bind(null, err)); - }); - } else { - return promise; - } -}; + server.listen({ port }, () => { + port = server.address().port; + server.close(); + debug('get free port: %s', port); + callback(null, port); + }); +} diff --git a/package.json b/package.json index cc8e59a..b70214b 100644 --- a/package.json +++ b/package.json @@ -15,26 +15,27 @@ "type": "git", "url": "git://github.com/node-modules/detect-port.git" }, - "dependencies": {}, + "dependencies": { + "debug": "^2.6.0" + }, "devDependencies": { - "co-mocha": "*", "command-line-test": "^1.0.8", - "istanbul": "*", - "jshint": "*", - "mocha": "2.2.4", - "pre-commit": "^1.1.3", - "should": "~6.0.3" + "egg-bin": "^2.0.0", + "egg-ci": "^1.1.0", + "eslint": "^3.13.1", + "eslint-config-egg": "^3.1.0" }, "scripts": { - "test": "make test", - "jshint": "make jshint" + "test": "egg-bin test", + "ci": "npm run lint && egg-bin cov", + "lint": "eslint ." }, - "precommit": [ - "jshint" - ], "engines": { "node": ">= 4.2.1" }, + "ci": { + "version": "4, 6, 7" + }, "homepage": "https://github.com/node-modules/detect-port", "license": "MIT" } diff --git a/test/cli.test.js b/test/cli.test.js index aad2494..9aec89d 100644 --- a/test/cli.test.js +++ b/test/cli.test.js @@ -2,7 +2,7 @@ const path = require('path'); const CliTest = require('command-line-test'); - +const assert = require('assert'); const pkg = require('../package'); const cliTest = new CliTest(); @@ -10,35 +10,35 @@ const binFile = path.resolve(pkg.bin[pkg.name]); describe('command-line tool test', () => { - it('should show version and exit', function *() { - var res = yield cliTest.execFile(binFile, ['-v'], {}); - res.stdout.should.equal(pkg.version); - res = yield cliTest.execFile(binFile, ['--version'], {}); - res.stdout.should.containEql(pkg.version); + it('should show version and exit', function* () { + let res = yield cliTest.execFile(binFile, [ '-v' ], {}); + assert(res.stdout === pkg.version); + res = yield cliTest.execFile(binFile, [ '--version' ], {}); + assert(res.stdout.includes(pkg.version)); }); - it('should output usage information', function *() { - var res = yield cliTest.execFile(binFile, ['-h'], {}); - res.stdout.should.containEql(pkg.description); - res = yield cliTest.execFile(binFile, ['--help'], {}); - res.stdout.should.containEql(pkg.description); - res = yield cliTest.execFile(binFile, ['help'], {}); - res.stdout.should.containEql(pkg.description); - res = yield cliTest.execFile(binFile, ['xxx'], {}); - res.stdout.should.containEql(pkg.description); + it('should output usage information', function* () { + let res = yield cliTest.execFile(binFile, [ '-h' ], {}); + assert(res.stdout.includes(pkg.description)); + res = yield cliTest.execFile(binFile, [ '--help' ], {}); + assert(res.stdout.includes(pkg.description)); + res = yield cliTest.execFile(binFile, [ 'help' ], {}); + assert(res.stdout.includes(pkg.description)); + res = yield cliTest.execFile(binFile, [ 'xxx' ], {}); + assert(res.stdout.includes(pkg.description)); }); - it('should output available port randomly', function *() { + it('should output available port randomly', function* () { const res = yield cliTest.execFile(binFile, [], {}); const port = parseInt(res.stdout.split(' ')[3], 10); - port.should.within(9000, 65535); + assert(port >= 9000 && port < 65535); }); - it('should output available port from the given port', function *() { + it('should output available port from the given port', function* () { const givenPort = 9000; - const res = yield cliTest.execFile(binFile, [givenPort], {}); + const res = yield cliTest.execFile(binFile, [ givenPort ], {}); const port = parseInt(res.stdout.split(' ')[3], 10); - port.should.within(givenPort, 65535); + assert(port >= givenPort && port < 65535); }); }); diff --git a/test/detect-port.test.js b/test/detect-port.test.js index 57b4142..fada974 100644 --- a/test/detect-port.test.js +++ b/test/detect-port.test.js @@ -1,78 +1,86 @@ 'use strict'; +const assert = require('assert'); +const net = require('net'); const detectPort = require('..'); describe('detect port test', () => { + let server; + before(done => { + server = new net.Server(); + server.listen(7001, done); + }); + after(() => { + server.close(); + }); + + it('get random port', done => { + detectPort((_, port) => { + assert(port >= 1024 && port < 65535); + done(); + }); + }); it('callback with occupied port', done => { const _port = 80; - detectPort(_port, (err, port) => { - if (err) { - console.log(err); - } - port.should.within(_port, 65535); + detectPort(_port, (_, port) => { + assert(port >= _port && port < 65535); + done(); + }); + }); + + it('work with listening port', done => { + const port = 7001; + detectPort(port, (_, realPort) => { + assert(realPort !== 7001); + assert(realPort > 0); done(); }); }); it('callback with string arg', done => { const _port = '8080'; - detectPort(_port, (err, port) => { - if (err) { - console.log(err); - } - port.should.within(parseInt(_port, 10), 65535); + detectPort(_port, (_, port) => { + assert(port >= 8080 && port < 65535); done(); }); }); it('callback with wrong arguments', done => { - detectPort('oooo', err => { - err.should.containEql('wrong type of arguments'); + detectPort('oooo', (_, port) => { + assert(port > 0); done(); }); }); - it('generator usage', function *() { + it('generator usage', function* () { const _port = 8080; - try { - const port = yield detectPort(_port); - port.should.within(_port, 65535); - } catch (err) { - console.log(err); - } + const port = yield detectPort(_port); + assert(port >= _port && port < 65535); }); it('promise usage', done => { const _port = 8080; detectPort(_port) .then(port => { - port.should.within(_port, 65535); + assert(port >= _port && port < 65535); done(); }) - .catch(err => { - console.log(err); - done(); - }); + .catch(done); }); it('promise with wrong arguments', done => { detectPort() - .then(() => { + .then(port => { + assert(port > 0); done(); }) - .catch(err => { - err.should.containEql('wrong number of arguments'); - done(); - }); + .catch(done); }); - it('generator with wrong arguments', function *() { - try { - yield detectPort('oooo'); - } catch (err) { - err.should.containEql('wrong type of arguments'); - } + it('generator with wrong arguments and return random port', function* () { + const port = yield detectPort('oooo'); + assert(port > 0); + assert(typeof port === 'number'); }); - }); diff --git a/test/mocha.opts b/test/mocha.opts deleted file mode 100644 index 9c3fba0..0000000 --- a/test/mocha.opts +++ /dev/null @@ -1,2 +0,0 @@ ---require should ---reporter spec