summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorRobert Nagy <ronagy@icloud.com>2019-07-18 13:15:42 +0200
committerMatteo Collina <hello@matteocollina.com>2019-09-03 10:28:48 +0200
commitb03845b9376aec590b89f753a4b7c1b47729c5f8 (patch)
treebc16cf37f489fc97d715642941d4dd25b2e60d42 /test
parentd62d2b456031539617a9e615c3e62c199a7e7dfe (diff)
downloadandroid-node-v8-b03845b9376aec590b89f753a4b7c1b47729c5f8.tar.gz
android-node-v8-b03845b9376aec590b89f753a4b7c1b47729c5f8.tar.bz2
android-node-v8-b03845b9376aec590b89f753a4b7c1b47729c5f8.zip
stream: make finished call the callback if the stream is closed
Make stream.finished callback invoked if stream is already closed/destroyed. PR-URL: https://github.com/nodejs/node/pull/28748 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Diffstat (limited to 'test')
-rw-r--r--test/parallel/test-http-client-finished.js106
-rw-r--r--test/parallel/test-stream-finished.js140
2 files changed, 243 insertions, 3 deletions
diff --git a/test/parallel/test-http-client-finished.js b/test/parallel/test-http-client-finished.js
index 2d7e5b95b3..337f7b596d 100644
--- a/test/parallel/test-http-client-finished.js
+++ b/test/parallel/test-http-client-finished.js
@@ -25,3 +25,109 @@ const { finished } = require('stream');
.end();
}));
}
+
+{
+ // Test abort before finished.
+
+ const server = http.createServer(function(req, res) {
+ });
+
+ server.listen(0, common.mustCall(function() {
+ const req = http.request({
+ port: this.address().port
+ }, common.mustNotCall());
+ req.abort();
+ finished(req, common.mustCall(() => {
+ server.close();
+ }));
+ }));
+}
+
+{
+ // Test abort after request.
+
+ const server = http.createServer(function(req, res) {
+ });
+
+ server.listen(0, common.mustCall(function() {
+ const req = http.request({
+ port: this.address().port
+ }).end();
+ finished(req, (err) => {
+ common.expectsError({
+ type: Error,
+ code: 'ERR_STREAM_PREMATURE_CLOSE'
+ })(err);
+ finished(req, common.mustCall(() => {
+ server.close();
+ }));
+ });
+ req.abort();
+ }));
+}
+
+{
+ // Test abort before end.
+
+ const server = http.createServer(function(req, res) {
+ res.write('test');
+ });
+
+ server.listen(0, common.mustCall(function() {
+ const req = http.request({
+ port: this.address().port
+ }).on('response', common.mustCall((res) => {
+ req.abort();
+ finished(res, common.mustCall(() => {
+ finished(res, common.mustCall(() => {
+ server.close();
+ }));
+ }));
+ })).end();
+ }));
+}
+
+{
+ // Test destroy before end.
+
+ const server = http.createServer(function(req, res) {
+ res.write('test');
+ });
+
+ server.listen(0, common.mustCall(function() {
+ http.request({
+ port: this.address().port
+ }).on('response', common.mustCall((res) => {
+ // TODO(ronag): Bug? Won't emit 'close' unless read.
+ res.on('data', () => {});
+ res.destroy();
+ finished(res, common.mustCall(() => {
+ finished(res, common.mustCall(() => {
+ server.close();
+ }));
+ }));
+ })).end();
+ }));
+}
+
+{
+ // Test finish after end.
+
+ const server = http.createServer(function(req, res) {
+ res.end('asd');
+ });
+
+ server.listen(0, common.mustCall(function() {
+ http.request({
+ port: this.address().port
+ }).on('response', common.mustCall((res) => {
+ // TODO(ronag): Bug? Won't emit 'close' unless read.
+ res.on('data', () => {});
+ finished(res, common.mustCall(() => {
+ finished(res, common.mustCall(() => {
+ server.close();
+ }));
+ }));
+ })).end();
+ }));
+}
diff --git a/test/parallel/test-stream-finished.js b/test/parallel/test-stream-finished.js
index d6361ea303..c5e792b45e 100644
--- a/test/parallel/test-stream-finished.js
+++ b/test/parallel/test-stream-finished.js
@@ -101,11 +101,25 @@ const { promisify } = require('util');
const rs = new Readable();
finished(rs, common.mustCall((err) => {
+ assert(err, 'premature close error');
+ }));
+
+ rs.push(null);
+ rs.emit('close');
+ rs.resume();
+}
+
+{
+ const rs = new Readable();
+
+ finished(rs, common.mustCall((err) => {
assert(!err, 'no error');
}));
rs.push(null);
- rs.emit('close'); // Should not trigger an error
+ rs.on('end', common.mustCall(() => {
+ rs.emit('close'); // Should not trigger an error
+ }));
rs.resume();
}
@@ -155,8 +169,9 @@ const { promisify } = require('util');
rs.resume();
}
-// Test that calling returned function removes listeners
{
+ // Nothing happens if disposed.
+
const ws = new Writable({
write(data, env, cb) {
cb();
@@ -168,6 +183,8 @@ const { promisify } = require('util');
}
{
+ // Nothing happens if disposed.
+
const rs = new Readable();
const removeListeners = finished(rs, common.mustNotCall());
removeListeners();
@@ -178,9 +195,126 @@ const { promisify } = require('util');
}
{
+ // Completed if readable-like is ended before.
+
const streamLike = new EE();
streamLike.readableEnded = true;
streamLike.readable = true;
- finished(streamLike, common.mustCall);
+ finished(streamLike, common.mustCall());
+}
+
+{
+ // Completed if readable-like is never ended.
+
+ const streamLike = new EE();
+ streamLike.readableEnded = false;
+ streamLike.readable = true;
+ finished(streamLike, common.expectsError({
+ code: 'ERR_STREAM_PREMATURE_CLOSE'
+ }));
+ streamLike.emit('close');
+}
+
+{
+ // Completed if writable-like is destroyed before.
+
+ const streamLike = new EE();
+ streamLike.destroyed = true;
+ streamLike.writable = true;
+ finished(streamLike, common.mustCall());
+}
+
+{
+ // Completed if readable-like is aborted before.
+
+ const streamLike = new EE();
+ streamLike.destroyed = true;
+ streamLike.readable = true;
+ finished(streamLike, common.mustCall());
+}
+
+{
+ // Completed if writable-like is aborted before.
+
+ const streamLike = new EE();
+ streamLike.aborted = true;
+ streamLike.writable = true;
+ finished(streamLike, common.mustCall());
+}
+
+{
+ // Completed if readable-like is aborted before.
+
+ const streamLike = new EE();
+ streamLike.aborted = true;
+ streamLike.readable = true;
+ finished(streamLike, common.mustCall());
+}
+
+{
+ // Completed if streamlike is finished before.
+
+ const streamLike = new EE();
+ streamLike.writableFinished = true;
+ streamLike.writable = true;
+ finished(streamLike, common.mustCall());
+}
+
+{
+ // Premature close if stream is not finished.
+
+ const streamLike = new EE();
+ streamLike.writableFinished = false;
+ streamLike.writable = true;
+ finished(streamLike, common.expectsError({
+ code: 'ERR_STREAM_PREMATURE_CLOSE'
+ }));
+ streamLike.emit('close');
+}
+
+{
+ // Premature close if stream never emitted 'finish'
+ // even if writableFinished says something else.
+
+ const streamLike = new EE();
+ streamLike.writable = true;
+ finished(streamLike, common.expectsError({
+ code: 'ERR_STREAM_PREMATURE_CLOSE'
+ }));
+ streamLike.writableFinished = true;
+ streamLike.emit('close');
+}
+
+
+{
+ // Premature close if stream never emitted 'end'
+ // even if readableEnded says something else.
+
+ const streamLike = new EE();
+ streamLike.readable = true;
+ finished(streamLike, common.expectsError({
+ code: 'ERR_STREAM_PREMATURE_CLOSE'
+ }));
+ streamLike.readableEnded = true;
streamLike.emit('close');
}
+
+{
+ // Completes if already finished.
+
+ const w = new Writable();
+ finished(w, common.mustCall(() => {
+ finished(w, common.mustCall());
+ }));
+ w.destroy();
+}
+
+{
+ // Completes if already ended.
+
+ const r = new Readable();
+ finished(r, common.mustCall(() => {
+ finished(r, common.mustCall());
+ }));
+ r.destroy();
+}