[Pkg-javascript-commits] [node-finished] 04/10: Imported Upstream version 2.1.0
Andrew Kelley
andrewrk-guest at moszumanska.debian.org
Fri Sep 12 04:47:44 UTC 2014
This is an automated email from the git hooks/post-receive script.
andrewrk-guest pushed a commit to branch master
in repository node-finished.
commit 157529b56ebc3767a19fbc0cf6b04e4f09aab8f0
Author: Andrew Kelley <superjoe30 at gmail.com>
Date: Fri Sep 12 01:50:04 2014 +0000
Imported Upstream version 2.1.0
---
.gitignore | 3 +
.npmignore | 3 -
.travis.yml | 2 +-
HISTORY.md | 36 +++--
LICENSE | 23 +++
README.md | 114 +++++++--------
index.js | 109 +++++++++++---
package.json | 29 ++--
test/test.js | 456 ++++++++++++++++++++++++++++++++++++++++++++++++-----------
9 files changed, 587 insertions(+), 188 deletions(-)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..df9af16
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+coverage
+node_modules
+npm-debug.log
diff --git a/.npmignore b/.npmignore
deleted file mode 100644
index cd39b77..0000000
--- a/.npmignore
+++ /dev/null
@@ -1,3 +0,0 @@
-coverage/
-test/
-.travis.yml
diff --git a/.travis.yml b/.travis.yml
index 1ff243c..6299766 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,4 +8,4 @@ matrix:
- node_js: "0.11"
fast_finish: true
script: "npm run-script test-travis"
-after_script: "npm install coveralls at 2.10.0 && cat ./coverage/lcov.info | coveralls"
+after_script: "test $TRAVIS_NODE_VERSION = '0.10' && npm install coveralls at 2 && cat ./coverage/lcov.info | coveralls"
diff --git a/HISTORY.md b/HISTORY.md
index 8937250..0aa241b 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,48 +1,64 @@
+2.1.0 / 2014-08-16
+==================
+
+ * Check if `socket` is detached
+ * Return `undefined` for `isFinished` if state unknown
+
+2.0.0 / 2014-08-16
+==================
+
+ * Add `isFinished` function
+ * Move to `jshttp` organization
+ * Remove support for plain socket argument
+ * Rename to `on-finished`
+ * Support both `req` and `res` as arguments
+ * deps: ee-first at 1.0.5
+
1.2.2 / 2014-06-10
-==========
+==================
- * reduce listeners added to emitters
+ * Reduce listeners added to emitters
- avoids "event emitter leak" warnings when used multiple times on same request
1.2.1 / 2014-06-08
==================
- * fix returned value when already finished
+ * Fix returned value when already finished
1.2.0 / 2014-06-05
==================
- * call callback when called on already-finished socket
+ * Call callback when called on already-finished socket
1.1.4 / 2014-05-27
==================
- * support node.js 0.8
+ * Support node.js 0.8
1.1.3 / 2014-04-30
==================
- * make sure errors passed as instanceof `Error`
+ * Make sure errors passed as instanceof `Error`
1.1.2 / 2014-04-18
==================
- * default the `socket` to passed-in object
+ * Default the `socket` to passed-in object
1.1.1 / 2014-01-16
==================
- * rename module to `finished`
+ * Rename module to `finished`
1.1.0 / 2013-12-25
==================
- * call callback when called on already-errored socket
+ * Call callback when called on already-errored socket
1.0.1 / 2013-12-20
==================
- * actually pass the error to the callback
+ * Actually pass the error to the callback
1.0.0 / 2013-12-20
==================
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..5931fd2
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,23 @@
+(The MIT License)
+
+Copyright (c) 2013 Jonathan Ong <me at jongleberry.com>
+Copyright (c) 2014 Douglas Christopher Wilson <doug at somethingdoug.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
index 79facd5..887b5c3 100644
--- a/README.md
+++ b/README.md
@@ -1,88 +1,90 @@
-# finished
+# on-finished
-[![NPM Version](https://badge.fury.io/js/finished.svg)](http://badge.fury.io/js/finished)
-[![Build Status](https://travis-ci.org/expressjs/finished.svg?branch=master)](https://travis-ci.org/expressjs/finished)
-[![Coverage Status](https://img.shields.io/coveralls/expressjs/finished.svg?branch=master)](https://coveralls.io/r/expressjs/finished)
+[![NPM Version](http://img.shields.io/npm/v/on-finished.svg?style=flat)](https://www.npmjs.org/package/on-finished)
+[![Node.js Version](http://img.shields.io/badge/node.js->=_0.8-brightgreen.svg?style=flat)](http://nodejs.org/download/)
+[![Build Status](http://img.shields.io/travis/jshttp/on-finished.svg?style=flat)](https://travis-ci.org/jshttp/on-finished)
+[![Coverage Status](https://img.shields.io/coveralls/jshttp/on-finished.svg?style=flat)](https://coveralls.io/r/jshttp/on-finished)
Execute a callback when a request closes, finishes, or errors.
-#### Install
+## Install
```sh
-$ npm install finished
+$ npm install on-finished
```
-#### Uses
+## API
-This is useful for cleaning up streams. For example, you want to destroy any file streams you create on socket errors otherwise you will leak file descriptors.
+```js
+var onFinished = require('on-finished')
+```
-This is required to fix what many perceive as issues with node's streams. Relevant:
+### onFinished(res, listener)
-- [node#6041](https://github.com/joyent/node/issues/6041)
-- [koa#184](https://github.com/koajs/koa/issues/184)
-- [koa#165](https://github.com/koajs/koa/issues/165)
+Attach a listener to listen for the response to finish. The listener will
+be invoked only once when the response finished. If the response finished
+to to an error, the first argument will contain the error.
-## API
-
-### finished(response, callback)
+Listening to the end of a response would be used to close things associated
+with the response, like open files.
```js
-var onFinished = require('finished')
-
onFinished(res, function (err) {
- // do something maybe
+ // clean up open fds, etc.
})
```
-### Examples
+### onFinished(req, listener)
-The following code ensures that file descriptors are always closed once the response finishes.
+Attach a listener to listen for the request to finish. The listener will
+be invoked only once when the request finished. If the request finished
+to to an error, the first argument will contain the error.
-#### Node / Connect / Express
+Listening to the end of a request would be used to know when to continue
+after reading the data.
```js
-var onFinished = require('finished')
+var data = ''
-function (req, res, next) {
- var stream = fs.createReadStream('thingie.json')
- stream.pipe(res)
- onFinished(res, function (err) {
- stream.destroy()
- })
-}
+req.setEncoding('utf8')
+res.on('data', function (str) {
+ data += str
+})
+
+onFinished(req, function (err) {
+ // data is read unless there is err
+})
```
-#### Koa
+### onFinished.isFinished(res)
-```js
-function* () {
- var stream = this.body = fs.createReadStream('thingie.json')
- onFinished(this, function (err) {
- stream.destroy()
- })
-}
-```
+Determine if `res` is already finished. This would be useful to check and
+not even start certain operations if the response has already finished.
-## License
+### onFinished.isFinished(req)
-The MIT License (MIT)
+Determine if `req` is already finished. This would be useful to check and
+not even start certain operations if the request has already finished.
-Copyright (c) 2013 Jonathan Ong me at jongleberry.com
+### Example
+
+The following code ensures that file descriptors are always closed
+once the response finishes.
+
+```js
+var destroy = require('destroy')
+var http = require('http')
+var onFinished = require('finished')
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
+http.createServer(function onRequest(req, res) {
+ var stream = fs.createReadStream('package.json')
+ stream.pipe(res)
+ onFinished(res, function (err) {
+ destroy(stream)
+ })
+})
+```
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
+## License
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
+[MIT](LICENSE)
diff --git a/index.js b/index.js
index 90709d4..a505561 100644
--- a/index.js
+++ b/index.js
@@ -1,10 +1,18 @@
/*!
- * finished
- * Copyright(c) 2014 Jonathan Ong
+ * on-finished
+ * Copyright(c) 2013 Jonathan Ong
+ * Copyright(c) 2014 Douglas Christopher Wilson
* MIT Licensed
*/
/**
+ * Module exports.
+ */
+
+module.exports = onFinished;
+module.exports.isFinished = isFinished;
+
+/**
* Module dependencies.
*/
@@ -23,40 +31,97 @@ var defer = typeof setImmediate === 'function'
* Invoke callback when the response has finished, useful for
* cleaning up resources afterwards.
*
- * @param {object} thingie
- * @param {function} callback
+ * @param {object} msg
+ * @param {function} listener
* @return {object}
* @api public
*/
-module.exports = function finished(thingie, callback) {
- var socket = thingie.socket || thingie
- var res = thingie.res || thingie
+function onFinished(msg, listener) {
+ if (isFinished(msg) !== false) {
+ defer(listener)
+ return msg
+ }
- if (res.finished || !socket.writable) {
- defer(callback)
- return thingie
+ // attach the listener to the message
+ attachListener(msg, listener)
+
+ return msg
+}
+
+/**
+ * Determine is message is already finished.
+ *
+ * @param {object} msg
+ * @return {boolean}
+ * @api public
+ */
+
+function isFinished(msg) {
+ var socket = msg.socket
+
+ if (typeof msg.finished === 'boolean') {
+ // OutgoingMessage
+ return Boolean(!socket || msg.finished || !socket.writable)
+ }
+
+ if (typeof msg.complete === 'boolean') {
+ // IncomingMessage
+ return Boolean(!socket || msg.complete || !socket.readable)
}
- var listener = res.__onFinished
+ // don't know
+ return undefined
+}
+
+/**
+ * Attach the listener to the message.
+ *
+ * @param {object} msg
+ * @return {function}
+ * @api private
+ */
+
+function attachListener(msg, listener) {
+ var attached = msg.__onFinished
+ var socket = msg.socket
// create a private single listener with queue
- if (!listener || !listener.queue) {
- listener = res.__onFinished = function onFinished(err) {
- if (res.__onFinished === listener) res.__onFinished = null
- var queue = listener.queue || []
- while (queue.length) queue.shift()(err)
- }
- listener.queue = []
+ if (!attached || !attached.queue) {
+ attached = msg.__onFinished = createListener(msg)
// finished on first event
first([
[socket, 'error', 'close'],
- [res, 'finish'],
- ], listener)
+ [msg, 'end', 'finish'],
+ ], attached)
+ }
+
+ attached.queue.push(listener)
+}
+
+/**
+ * Create listener on message.
+ *
+ * @param {object} msg
+ * @return {function}
+ * @api private
+ */
+
+function createListener(msg) {
+ function listener(err) {
+ if (msg.__onFinished === listener) msg.__onFinished = null
+ if (!listener.queue) return
+
+ var queue = listener.queue
+ listener.queue = null
+
+ for (var i = 0; i < queue.length; i++) {
+ queue[i](err)
+ }
}
- listener.queue.push(callback)
+ listener.queue = []
- return thingie
+ return listener
}
diff --git a/package.json b/package.json
index ab0d433..0b1e5f3 100644
--- a/package.json
+++ b/package.json
@@ -1,24 +1,31 @@
{
- "name": "finished",
+ "name": "on-finished",
"description": "Execute a callback when a request closes, finishes, or errors",
- "version": "1.2.2",
- "author": "Jonathan Ong <me at jongleberry.com> (http://jongleberry.com)",
+ "version": "2.1.0",
+ "contributors": [
+ "Douglas Christopher Wilson <doug at somethingdoug.com>",
+ "Jonathan Ong <me at jongleberry.com> (http://jongleberry.com)"
+ ],
"license": "MIT",
- "repository": "expressjs/finished",
+ "repository": "jshttp/on-finished",
"dependencies": {
- "ee-first": "1.0.3"
+ "ee-first": "1.0.5"
},
"devDependencies": {
- "istanbul": "0.2.10",
- "mocha": "~1.20.1",
- "should": "~4.0.1"
+ "istanbul": "0.3.0",
+ "mocha": "~1.21.4"
},
"engine": {
"node": ">= 0.8.0"
},
+ "files": [
+ "HISTORY.md",
+ "LICENSE",
+ "index.js"
+ ],
"scripts": {
- "test": "mocha --reporter spec test/",
- "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot test/",
- "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec test/"
+ "test": "mocha --reporter spec --bail --check-leaks test/",
+ "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/",
+ "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/"
}
}
diff --git a/test/test.js b/test/test.js
index 61f794c..68bea38 100644
--- a/test/test.js
+++ b/test/test.js
@@ -1,90 +1,115 @@
-var EventEmitter = require('events').EventEmitter
-var should = require('should')
var assert = require('assert')
var http = require('http')
-
+var net = require('net')
var onFinished = require('..')
-function createThingie() {
- var ee = new EventEmitter
- ee.socket = new EventEmitter
- ee.socket.writable = true
- return ee
-}
+describe('onFinished(res, listener)', function () {
+ it('should invoke listener given an unknwon object', function (done) {
+ onFinished({}, done)
+ })
-describe('on socket error', function () {
- it('should execute the callback on socket error', function () {
- var thingie = createThingie()
- var called = false
- onFinished(thingie, function (err) {
- called = true
- err.message.should.equal('boom')
+ describe('when the response finishes', function () {
+ it('should fire the callback', function (done) {
+ var server = http.createServer(function (req, res) {
+ onFinished(res, done)
+ setTimeout(res.end.bind(res), 0)
+ })
+
+ sendget(server)
})
- thingie.socket.emit('error', new Error('boom'))
- called.should.be.true
- })
- it('should not execute the callback if response is finished', function (done) {
- var thingie = createThingie()
- onFinished(thingie, function (err) {
- assert.ifError(err)
- done()
+ it('should fire when called after finish', function (done) {
+ var server = http.createServer(function (req, res) {
+ onFinished(res, function () {
+ onFinished(res, done)
+ })
+ setTimeout(res.end.bind(res), 0)
+ })
+
+ sendget(server)
})
- thingie.emit('finish')
- thingie.socket.emit(new Error('boom'))
})
-})
-describe('when the socket is not writable', function () {
- it('should execute the callback immediately', function (done) {
- var thingie = createThingie()
- thingie.socket.writable = false
- onFinished(thingie, function (err) {
- done()
+ describe('when using keep-alive', function () {
+ it('should fire for each response', function (done) {
+ var called = false
+ var server = http.createServer(function (req, res) {
+ onFinished(res, function () {
+ if (called) {
+ socket.end()
+ server.close()
+ done(called !== req ? null : new Error('fired twice on same req'))
+ return
+ }
+
+ called = req
+
+ writerequest(socket)
+ })
+
+ res.end()
+ })
+ var socket
+
+ server.listen(function () {
+ socket = net.connect(this.address().port, function () {
+ writerequest(this)
+ })
+ })
})
})
-})
-describe('when the socket closes', function () {
- it('should execute the callback', function (done) {
- var thingie = createThingie()
- onFinished(thingie, done)
- thingie.socket.emit('close')
- })
-})
+ describe('when response errors', function () {
+ it('should fire with error', function (done) {
+ var server = http.createServer(function (req, res) {
+ onFinished(res, function (err) {
+ assert.ok(err)
+ done()
+ })
+
+ socket.on('error', noop)
+ socket.write('W')
+ })
+ var socket
-describe('when an emitter emits a non-error', function () {
- it('should ignore the error', function (done) {
- var thingie = createThingie()
- onFinished(thingie, done)
- thingie.socket.emit('close', false)
+ server.listen(function () {
+ socket = net.connect(this.address().port, function () {
+ writerequest(this, true)
+ })
+ })
+ })
})
-})
-describe('http', function () {
- describe('when the request finishes', function () {
+ describe('when the response aborts', function () {
it('should execute the callback', function (done) {
+ var client
var server = http.createServer(function (req, res) {
onFinished(res, done)
- setTimeout(res.end.bind(res), 0)
+ setTimeout(client.abort.bind(client), 0)
})
server.listen(function () {
var port = this.address().port
- http.get('http://127.0.0.1:' + port, function (res) {
- res.resume()
- res.on('close', server.close.bind(server))
- })
+ client = http.get('http://127.0.0.1:' + port)
+ client.on('error', noop)
})
})
+ })
- it('should execute the callback when called after finish', function (done) {
+ describe('when calling many times on same response', function () {
+ it('should not print warnings', function (done) {
var server = http.createServer(function (req, res) {
- onFinished(res, function () {
- onFinished(res, done)
+ var stderr = captureStderr(function () {
+ for (var i = 0; i < 400; i++) {
+ onFinished(res, noop)
+ }
})
- setTimeout(res.end.bind(res), 0)
+
+ onFinished(res, done)
+ assert.equal(stderr, '')
+ res.end()
})
+
server.listen(function () {
var port = this.address().port
http.get('http://127.0.0.1:' + port, function (res) {
@@ -94,59 +119,320 @@ describe('http', function () {
})
})
})
+})
- describe('when the request aborts', function () {
- it('should execute the callback', function (done) {
+describe('isFinished(res)', function () {
+ it('should return undefined for unknown object', function () {
+ assert.strictEqual(onFinished.isFinished({}), undefined)
+ })
+
+ it('should be false before response finishes', function (done) {
+ var server = http.createServer(function (req, res) {
+ assert.ok(!onFinished.isFinished(res))
+ res.end()
+ done()
+ })
+
+ sendget(server)
+ })
+
+ it('should be true after response finishes', function (done) {
+ var server = http.createServer(function (req, res) {
+ onFinished(res, function (err) {
+ assert.ifError(err)
+ assert.ok(onFinished.isFinished(res))
+ done()
+ })
+
+ res.end()
+ })
+
+ sendget(server)
+ })
+
+ describe('when response errors', function () {
+ it('should return true', function (done) {
+ var server = http.createServer(function (req, res) {
+ onFinished(res, function (err) {
+ assert.ok(err)
+ assert.ok(onFinished.isFinished(res))
+ done()
+ })
+
+ socket.on('error', noop)
+ socket.write('W')
+ })
+ var socket
+
+ server.listen(function () {
+ socket = net.connect(this.address().port, function () {
+ writerequest(this, true)
+ })
+ })
+ })
+ })
+
+ describe('when the response aborts', function () {
+ it('should return true', function (done) {
var client
var server = http.createServer(function (req, res) {
- onFinished(res, done)
+ onFinished(res, function (err) {
+ assert.ifError(err)
+ assert.ok(onFinished.isFinished(res))
+ done()
+ })
setTimeout(client.abort.bind(client), 0)
})
server.listen(function () {
var port = this.address().port
client = http.get('http://127.0.0.1:' + port)
- client.on('error', function () {})
+ client.on('error', noop)
})
})
})
})
-describe('event emitter leaks', function () {
- describe('when adding a lot of listeners on the same request', function () {
- it('should not warn and add at most 1 listener per emitter per event', function () {
- // we just have to make sure tests pass without a bunch of logs
- var thingie = createThingie()
+describe('onFinished(req, listener)', function () {
+ describe('when the request finishes', function () {
+ it('should fire the callback', function (done) {
+ var server = http.createServer(function (req, res) {
+ onFinished(req, done)
+ req.resume()
+ setTimeout(res.end.bind(res), 0)
+ })
+
+ sendget(server)
+ })
+
+ it('should fire when called after finish', function (done) {
+ var server = http.createServer(function (req, res) {
+ onFinished(req, function () {
+ onFinished(req, done)
+ })
+ req.resume()
+ setTimeout(res.end.bind(res), 0)
+ })
+
+ sendget(server)
+ })
+ })
+
+ describe('when using keep-alive', function () {
+ it('should fire for each request', function (done) {
var called = false
+ var server = http.createServer(function (req, res) {
+ var data = ''
+
+ onFinished(req, function (err) {
+ assert.ifError(err)
+ assert.equal(data, 'A')
+
+ if (called) {
+ socket.end()
+ server.close()
+ done(called !== req ? null : new Error('fired twice on same req'))
+ return
+ }
+
+ called = req
- onFinished(thingie, function (err) {
- called = true
- err.message.should.equal('boom')
+ res.end()
+ writerequest(socket, true)
+ })
+
+ req.setEncoding('utf8')
+ req.on('data', function (str) {
+ data += str
+ })
+
+ socket.write('1\r\nA\r\n')
+ socket.write('0\r\n\r\n')
})
+ var socket
- for (var i = 0; i < 1000; i++) {
- onFinished(thingie, noop)
- }
+ server.listen(function () {
+ socket = net.connect(this.address().port, function () {
+ writerequest(this, true)
+ })
+ })
+ })
+ })
+
+ describe('when request errors', function () {
+ it('should fire with error', function (done) {
+ var server = http.createServer(function (req, res) {
+ onFinished(req, function (err) {
+ assert.ok(err)
+ done()
+ })
- assert.equal(1, thingie.socket.listeners('error').length)
- assert.equal(1, thingie.socket.listeners('close').length)
- assert.equal(1, thingie.listeners('finish').length)
+ socket.on('error', noop)
+ socket.write('W')
+ })
+ var socket
+
+ server.listen(function () {
+ socket = net.connect(this.address().port, function () {
+ writerequest(this, true)
+ })
+ })
+ })
+ })
- thingie.socket.emit('error', new Error('boom'))
- called.should.be.true
+ describe('when the request aborts', function () {
+ it('should execute the callback', function (done) {
+ var client
+ var server = http.createServer(function (req, res) {
+ onFinished(req, done)
+ setTimeout(client.abort.bind(client), 0)
+ })
+ server.listen(function () {
+ var port = this.address().port
+ client = http.get('http://127.0.0.1:' + port)
+ client.on('error', noop)
+ })
})
})
- it('should clean up after itself', function (done) {
- var thingie = createThingie()
- onFinished(thingie, function () {
- assert(!thingie.socket.listeners('error').length)
- assert(!thingie.socket.listeners('close').length)
- assert(!thingie.listeners('finish').length)
+ describe('when calling many times on same request', function () {
+ it('should not print warnings', function (done) {
+ var server = http.createServer(function (req, res) {
+ var stderr = captureStderr(function () {
+ for (var i = 0; i < 400; i++) {
+ onFinished(req, noop)
+ }
+ })
+
+ onFinished(req, done)
+ assert.equal(stderr, '')
+ res.end()
+ })
+
+ server.listen(function () {
+ var port = this.address().port
+ http.get('http://127.0.0.1:' + port, function (res) {
+ res.resume()
+ res.on('close', server.close.bind(server))
+ })
+ })
+ })
+ })
+})
+
+describe('isFinished(req)', function () {
+ it('should invoke listener given an unknwon object', function (done) {
+ onFinished({}, done)
+ })
+
+ it('should return undefined for unknown object', function () {
+ assert.strictEqual(onFinished.isFinished({}), undefined)
+ })
+
+ it('should be false before request finishes', function (done) {
+ var server = http.createServer(function (req, res) {
+ assert.ok(!onFinished.isFinished(req))
+ req.resume()
+ res.end()
done()
})
- thingie.socket.emit('error')
+ sendget(server)
+ })
+
+ it('should be true after request finishes', function (done) {
+ var server = http.createServer(function (req, res) {
+ onFinished(req, function (err) {
+ assert.ifError(err)
+ assert.ok(onFinished.isFinished(req))
+ done()
+ })
+
+ req.resume()
+ res.end()
+ })
+
+ sendget(server)
+ })
+
+ describe('when request errors', function () {
+ it('should return true', function (done) {
+ var server = http.createServer(function (req, res) {
+ onFinished(req, function (err) {
+ assert.ok(err)
+ assert.ok(onFinished.isFinished(req))
+ done()
+ })
+
+ socket.on('error', noop)
+ socket.write('W')
+ })
+ var socket
+
+ server.listen(function () {
+ socket = net.connect(this.address().port, function () {
+ writerequest(this, true)
+ })
+ })
+ })
+ })
+
+ describe('when the request aborts', function () {
+ it('should return true', function (done) {
+ var client
+ var server = http.createServer(function (req, res) {
+ onFinished(res, function (err) {
+ assert.ifError(err)
+ assert.ok(onFinished.isFinished(req))
+ done()
+ })
+ setTimeout(client.abort.bind(client), 0)
+ })
+ server.listen(function () {
+ var port = this.address().port
+ client = http.get('http://127.0.0.1:' + port)
+ client.on('error', noop)
+ })
+ })
})
})
+function captureStderr(fn) {
+ var chunks = []
+ var write = process.stderr.write
+
+ process.stderr.write = function write(chunk, encoding) {
+ chunks.push(new Buffer(chunk, encoding))
+ }
+
+ try {
+ fn()
+ } finally {
+ process.stderr.write = write
+ }
+
+ return Buffer.concat(chunks).toString('utf8')
+}
+
function noop() {}
+
+function sendget(server) {
+ server.listen(function onListening() {
+ var port = this.address().port
+ http.get('http://127.0.0.1:' + port, function onResponse(res) {
+ res.resume()
+ res.on('close', server.close.bind(server))
+ })
+ })
+}
+
+function writerequest(socket, chunked) {
+ socket.write('GET / HTTP/1.1\r\n')
+ socket.write('Host: localhost\r\n')
+ socket.write('Connection: keep-alive\r\n')
+
+ if (chunked) {
+ socket.write('Transfer-Encoding: chunked\r\n')
+ }
+
+ socket.write('\r\n')
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-finished.git
More information about the Pkg-javascript-commits
mailing list