summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Johnston <apjohnsto@gmail.com>2018-02-17 19:04:40 +0100
committerLeko <leko.noor@gmail.com>2018-03-02 01:08:00 +0900
commitf7a6971281d863e2b56682ff0f45eee7a7c4d3bb (patch)
tree0e1f8dd6b0dcf10e056a1e5ddacdb3c8f6e79889
parent1980a36dd45997e9dee03fe11688319c2f5c3644 (diff)
downloadandroid-node-v8-f7a6971281d863e2b56682ff0f45eee7a7c4d3bb.tar.gz
android-node-v8-f7a6971281d863e2b56682ff0f45eee7a7c4d3bb.tar.bz2
android-node-v8-f7a6971281d863e2b56682ff0f45eee7a7c4d3bb.zip
http: prevent aborted event when already completed
Tests in progress to reproduce issue consistently. Fixes: https://github.com/nodejs/node/issues/18756 PR-URL: https://github.com/nodejs/node/pull/18999 Reviewed-By: Shingo Inoue <leko.noor@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
-rw-r--r--test/parallel/test-http-client-spurious-aborted.js83
1 files changed, 83 insertions, 0 deletions
diff --git a/test/parallel/test-http-client-spurious-aborted.js b/test/parallel/test-http-client-spurious-aborted.js
new file mode 100644
index 0000000000..1b5f6301a6
--- /dev/null
+++ b/test/parallel/test-http-client-spurious-aborted.js
@@ -0,0 +1,83 @@
+'use strict';
+
+const common = require('../common');
+const http = require('http');
+const assert = require('assert');
+const fs = require('fs');
+const Countdown = require('../common/countdown');
+
+function cleanup(fname) {
+ try {
+ if (fs.statSync(fname)) fs.unlinkSync(fname);
+ } catch (err) {}
+}
+
+const N = 2;
+const fname = '/dev/null';
+let abortRequest = true;
+
+const server = http.Server(common.mustCall((req, res) => {
+ const headers = { 'Content-Type': 'text/plain' };
+ headers['Content-Length'] = 50;
+ const socket = res.socket;
+ res.writeHead(200, headers);
+ setTimeout(() => res.write('aaaaaaaaaa'), 100);
+ setTimeout(() => res.write('bbbbbbbbbb'), 200);
+ setTimeout(() => res.write('cccccccccc'), 300);
+ setTimeout(() => res.write('dddddddddd'), 400);
+ if (abortRequest) {
+ setTimeout(() => socket.destroy(), 600);
+ } else {
+ setTimeout(() => res.end('eeeeeeeeee'), 1000);
+ }
+}, N));
+
+server.listen(0, common.mustCall(() => {
+ cleanup(fname);
+ download();
+}));
+
+const finishCountdown = new Countdown(N, common.mustCall(() => {
+ server.close();
+}));
+const reqCountdown = new Countdown(N, common.mustCall());
+
+function download() {
+ const opts = {
+ port: server.address().port,
+ path: '/',
+ };
+ const req = http.get(opts);
+ req.on('error', common.mustNotCall());
+ req.on('response', (res) => {
+ assert.strictEqual(res.statusCode, 200);
+ assert.strictEqual(res.headers.connection, 'close');
+ let aborted = false;
+ const fstream = fs.createWriteStream(fname);
+ res.pipe(fstream);
+ const _handle = res.socket._handle;
+ _handle._close = res.socket._handle.close;
+ _handle.close = function(callback) {
+ _handle._close();
+ // set readable to true event though request is complete
+ if (res.complete) res.readable = true;
+ callback();
+ };
+ res.on('end', common.mustCall(() => {
+ reqCountdown.dec();
+ }));
+ res.on('aborted', () => {
+ aborted = true;
+ });
+ res.on('error', common.mustNotCall());
+ fstream.on('finish', () => {
+ assert.strictEqual(aborted, abortRequest);
+ cleanup(fname);
+ finishCountdown.dec();
+ if (finishCountdown.remaining === 0) return;
+ abortRequest = false; // next one should be a good response
+ download();
+ });
+ });
+ req.end();
+}