From f39c7926cf2380e3ea60978010e7407d82afd261 Mon Sep 17 00:00:00 2001 From: Trivikram Kamat Date: Mon, 2 Oct 2017 22:13:48 -0700 Subject: [PATCH] test: http2 client destroy tests in one file Refs: https://github.com/nodejs/node/pull/14985 Backport-PR-URL: https://github.com/nodejs/node/pull/16070 PR-URL: https://github.com/nodejs/node/pull/15749 Reviewed-By: James M Snell Reviewed-By: Matteo Collina --- lib/internal/http2/core.js | 6 +- ...est-http2-client-destroy-before-connect.js | 30 ---- ...est-http2-client-destroy-before-request.js | 30 ---- .../test-http2-client-destroy-goaway.js | 25 --- test/parallel/test-http2-client-destroy.js | 164 ++++++++++++++---- 5 files changed, 129 insertions(+), 126 deletions(-) delete mode 100644 test/parallel/test-http2-client-destroy-before-connect.js delete mode 100644 test/parallel/test-http2-client-destroy-before-request.js delete mode 100644 test/parallel/test-http2-client-destroy-goaway.js diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index 1a01b3fb75dc4f..fab88ec6c7a068 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -670,8 +670,6 @@ function submitShutdown(options) { function finishSessionDestroy(self, socket) { const state = self[kState]; - if (state.destroyed) - return; if (!socket.destroyed) socket.destroy(); @@ -954,6 +952,7 @@ class Http2Session extends EventEmitter { return; debug(`[${sessionName(this[kType])}] destroying nghttp2session`); state.destroying = true; + state.destroyed = false; // Unenroll the timer this.setTimeout(0, sessionOnTimeout); @@ -968,9 +967,6 @@ class Http2Session extends EventEmitter { delete this[kSocket]; delete this[kServer]; - state.destroyed = false; - state.destroying = true; - if (this[kHandle] !== undefined) this[kHandle].destroying(); diff --git a/test/parallel/test-http2-client-destroy-before-connect.js b/test/parallel/test-http2-client-destroy-before-connect.js deleted file mode 100644 index 3c99b8d6615088..00000000000000 --- a/test/parallel/test-http2-client-destroy-before-connect.js +++ /dev/null @@ -1,30 +0,0 @@ -// Flags: --expose-http2 -'use strict'; - -const common = require('../common'); -if (!common.hasCrypto) - common.skip('missing crypto'); -const h2 = require('http2'); - -const server = h2.createServer(); - -// we use the lower-level API here -server.on('stream', common.mustNotCall()); - -server.listen(0); - -server.on('listening', common.mustCall(() => { - - const client = h2.connect(`http://localhost:${server.address().port}`); - - const req = client.request({ ':path': '/' }); - client.destroy(); - - req.on('response', common.mustNotCall()); - req.resume(); - req.on('end', common.mustCall(() => { - server.close(); - })); - req.end(); - -})); diff --git a/test/parallel/test-http2-client-destroy-before-request.js b/test/parallel/test-http2-client-destroy-before-request.js deleted file mode 100644 index b8510f6a445e2e..00000000000000 --- a/test/parallel/test-http2-client-destroy-before-request.js +++ /dev/null @@ -1,30 +0,0 @@ -// Flags: --expose-http2 -'use strict'; - -const common = require('../common'); -if (!common.hasCrypto) - common.skip('missing crypto'); -const assert = require('assert'); -const h2 = require('http2'); - -const server = h2.createServer(); - -// we use the lower-level API here -server.on('stream', common.mustNotCall()); - -server.listen(0); - -server.on('listening', common.mustCall(() => { - - const client = h2.connect(`http://localhost:${server.address().port}`); - client.destroy(); - - assert.throws(() => client.request({ ':path': '/' }), - common.expectsError({ - code: 'ERR_HTTP2_INVALID_SESSION', - message: /^The session has been destroyed$/ - })); - - server.close(); - -})); diff --git a/test/parallel/test-http2-client-destroy-goaway.js b/test/parallel/test-http2-client-destroy-goaway.js deleted file mode 100644 index c393cfc0706eb5..00000000000000 --- a/test/parallel/test-http2-client-destroy-goaway.js +++ /dev/null @@ -1,25 +0,0 @@ -// Flags: --expose-http2 -'use strict'; - -const common = require('../common'); -if (!common.hasCrypto) - common.skip('missing crypto'); -const http2 = require('http2'); - -const server = http2.createServer(); -server.on('stream', common.mustCall((stream) => { - stream.on('error', common.mustCall()); - stream.session.shutdown(); -})); - -server.listen(0, common.mustCall(() => { - const client = http2.connect(`http://localhost:${server.address().port}`); - - client.on('goaway', common.mustCall(() => { - // We ought to be able to destroy the client in here without an error - server.close(); - client.destroy(); - })); - - client.request(); -})); diff --git a/test/parallel/test-http2-client-destroy.js b/test/parallel/test-http2-client-destroy.js index f1095660313571..962a297e6d1e62 100644 --- a/test/parallel/test-http2-client-destroy.js +++ b/test/parallel/test-http2-client-destroy.js @@ -7,50 +7,142 @@ if (!common.hasCrypto) const assert = require('assert'); const h2 = require('http2'); -const server = h2.createServer(); -server.listen(0); +{ + const server = h2.createServer(); + server.listen( + 0, + common.mustCall(() => { + const destroyCallbacks = [ + (client) => client.destroy(), + (client) => client.socket.destroy() + ]; -server.on('listening', common.mustCall(function() { - const port = this.address().port; + let remaining = destroyCallbacks.length; - const destroyCallbacks = [ - (client) => client.destroy(), - (client) => client.socket.destroy() - ]; + destroyCallbacks.forEach((destroyCallback) => { + const client = h2.connect(`http://localhost:${server.address().port}`); + client.on( + 'connect', + common.mustCall(() => { + const socket = client.socket; - let remaining = destroyCallbacks.length; + assert(client.socket, 'client session has associated socket'); + assert( + !client.destroyed, + 'client has not been destroyed before destroy is called' + ); + assert( + !socket.destroyed, + 'socket has not been destroyed before destroy is called' + ); - destroyCallbacks.forEach((destroyCallback) => { - const client = h2.connect(`http://localhost:${port}`); - client.on('connect', common.mustCall(() => { - const socket = client.socket; + // Ensure that 'close' event is emitted + client.on('close', common.mustCall()); - assert(client.socket, 'client session has associated socket'); - assert(!client.destroyed, - 'client has not been destroyed before destroy is called'); - assert(!socket.destroyed, - 'socket has not been destroyed before destroy is called'); + destroyCallback(client); - // Ensure that 'close' event is emitted - client.on('close', common.mustCall()); + assert( + !client.socket, + 'client.socket undefined after destroy is called' + ); - destroyCallback(client); + // Must must be closed + client.on( + 'close', + common.mustCall(() => { + assert(client.destroyed); + }) + ); - assert(!client.socket, 'client.socket undefined after destroy is called'); + // socket will close on process.nextTick + socket.on( + 'close', + common.mustCall(() => { + assert(socket.destroyed); + }) + ); - // Must must be closed - client.on('close', common.mustCall(() => { - assert(client.destroyed); - })); + if (--remaining === 0) { + server.close(); + } + }) + ); + }); + }) + ); +} - // socket will close on process.nextTick - socket.on('close', common.mustCall(() => { - assert(socket.destroyed); - })); +// test destroy before connect +{ + const server = h2.createServer(); + server.listen( + 0, + common.mustCall(() => { + const client = h2.connect(`http://localhost:${server.address().port}`); - if (--remaining === 0) { - server.close(); - } - })); - }); -})); + const req = client.request({ ':path': '/' }); + client.destroy(); + + req.on('response', common.mustNotCall()); + req.resume(); + req.on( + 'end', + common.mustCall(() => { + server.close(); + }) + ); + req.end(); + }) + ); +} + +// test destroy before request +{ + const server = h2.createServer(); + server.listen( + 0, + common.mustCall(() => { + const client = h2.connect(`http://localhost:${server.address().port}`); + client.destroy(); + + assert.throws( + () => client.request({ ':path': '/' }), + common.expectsError({ + code: 'ERR_HTTP2_INVALID_SESSION', + message: 'The session has been destroyed' + }) + ); + + server.close(); + }) + ); +} + +// test destroy before goaway +{ + const server = h2.createServer(); + server.on( + 'stream', + common.mustCall((stream) => { + stream.on('error', common.mustCall()); + stream.session.shutdown(); + }) + ); + server.listen( + 0, + common.mustCall(() => { + const client = h2.connect(`http://localhost:${server.address().port}`); + + client.on( + 'goaway', + common.mustCall(() => { + // We ought to be able to destroy the client in here without an error + server.close(); + client.destroy(); + }) + ); + + client.request(); + }) + ); +}