From 5b52a62ab153ad2b06164b8b7904581869c3c96c Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Thu, 28 Nov 2019 23:42:12 -0800 Subject: test: move test-http-max-http-headers to parallel test-http-max-http-headers seems to run fine in parallel, even with `tools/test.py -j 96 --repeat 192 test/parallel/test-http-max-http-headers.js`. The same applies to `test-set-http-max-http-headers.js` which (as written) depends on `test-http-max-http-headers.js` being in the same directory. So that is being moved too. PR-URL: https://github.com/nodejs/node/pull/30712 Reviewed-By: David Carlier Reviewed-By: Luigi Pinca --- test/parallel/test-http-max-http-headers.js | 180 ++++++++++++++++++++++ test/parallel/test-set-http-max-http-headers.js | 102 ++++++++++++ test/sequential/test-http-max-http-headers.js | 180 ---------------------- test/sequential/test-set-http-max-http-headers.js | 104 ------------- 4 files changed, 282 insertions(+), 284 deletions(-) create mode 100644 test/parallel/test-http-max-http-headers.js create mode 100644 test/parallel/test-set-http-max-http-headers.js delete mode 100644 test/sequential/test-http-max-http-headers.js delete mode 100644 test/sequential/test-set-http-max-http-headers.js diff --git a/test/parallel/test-http-max-http-headers.js b/test/parallel/test-http-max-http-headers.js new file mode 100644 index 0000000000..04fdebd48c --- /dev/null +++ b/test/parallel/test-http-max-http-headers.js @@ -0,0 +1,180 @@ +// Flags: --expose-internals +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); +const net = require('net'); +const MAX = +(process.argv[2] || 8 * 1024); // Command line option, or 8KB. + +const { getOptionValue } = require('internal/options'); + +console.log('pid is', process.pid); +console.log('max header size is', getOptionValue('--max-http-header-size')); + +// Verify that we cannot receive more than 8KB of headers. + +function once(cb) { + let called = false; + return () => { + if (!called) { + called = true; + cb(); + } + }; +} + +function finished(client, callback) { + ['abort', 'error', 'end'].forEach((e) => { + client.on(e, once(() => setImmediate(callback))); + }); +} + +function fillHeaders(headers, currentSize, valid = false) { + // `llhttp` counts actual header name/value sizes, excluding the whitespace + // and stripped chars. + // OK, Content-Length, 0, X-CRASH, aaa... + headers += 'a'.repeat(MAX - currentSize); + + // Generate valid headers + if (valid) { + headers = headers.slice(0, -1); + } + return headers + '\r\n\r\n'; +} + +function writeHeaders(socket, headers) { + const array = []; + const chunkSize = 100; + let last = 0; + + for (let i = 0; i < headers.length / chunkSize; i++) { + const current = (i + 1) * chunkSize; + array.push(headers.slice(last, current)); + last = current; + } + + // Safety check we are chunking correctly + assert.strictEqual(array.join(''), headers); + + next(); + + function next() { + if (socket.destroyed) { + console.log('socket was destroyed early, data left to write:', + array.join('').length); + return; + } + + const chunk = array.shift(); + + if (chunk) { + console.log('writing chunk of size', chunk.length); + socket.write(chunk, next); + } else { + socket.end(); + } + } +} + +function test1() { + console.log('test1'); + let headers = + 'HTTP/1.1 200 OK\r\n' + + 'Content-Length: 0\r\n' + + 'X-CRASH: '; + + // OK, Content-Length, 0, X-CRASH, aaa... + const currentSize = 2 + 14 + 1 + 7; + headers = fillHeaders(headers, currentSize); + + const server = net.createServer((sock) => { + sock.once('data', () => { + writeHeaders(sock, headers); + sock.resume(); + }); + + // The socket might error but that's ok + sock.on('error', () => {}); + }); + + server.listen(0, common.mustCall(() => { + const port = server.address().port; + const client = http.get({ port: port }, common.mustNotCall()); + + client.on('error', common.mustCall((err) => { + assert.strictEqual(err.code, 'HPE_HEADER_OVERFLOW'); + server.close(test2); + })); + })); +} + +const test2 = common.mustCall(() => { + console.log('test2'); + let headers = + 'GET / HTTP/1.1\r\n' + + 'Host: localhost\r\n' + + 'Agent: nod2\r\n' + + 'X-CRASH: '; + + // /, Host, localhost, Agent, node, X-CRASH, a... + const currentSize = 1 + 4 + 9 + 5 + 4 + 7; + headers = fillHeaders(headers, currentSize); + + const server = http.createServer(common.mustNotCall()); + + server.once('clientError', common.mustCall((err) => { + assert.strictEqual(err.code, 'HPE_HEADER_OVERFLOW'); + })); + + server.listen(0, common.mustCall(() => { + const client = net.connect(server.address().port); + client.on('connect', () => { + writeHeaders(client, headers); + client.resume(); + }); + + finished(client, common.mustCall(() => { + server.close(test3); + })); + })); +}); + +const test3 = common.mustCall(() => { + console.log('test3'); + let headers = + 'GET / HTTP/1.1\r\n' + + 'Host: localhost\r\n' + + 'Agent: nod3\r\n' + + 'X-CRASH: '; + + // /, Host, localhost, Agent, node, X-CRASH, a... + const currentSize = 1 + 4 + 9 + 5 + 4 + 7; + headers = fillHeaders(headers, currentSize, true); + + console.log('writing', headers.length); + + const server = http.createServer(common.mustCall((req, res) => { + res.end('hello from test3 server'); + server.close(); + })); + + server.on('clientError', (err) => { + console.log(err.code); + if (err.code === 'HPE_HEADER_OVERFLOW') { + console.log(err.rawPacket.toString('hex')); + } + }); + server.on('clientError', common.mustNotCall()); + + server.listen(0, common.mustCall(() => { + const client = net.connect(server.address().port); + client.on('connect', () => { + writeHeaders(client, headers); + client.resume(); + }); + + client.pipe(process.stdout); + })); +}); + +test1(); diff --git a/test/parallel/test-set-http-max-http-headers.js b/test/parallel/test-set-http-max-http-headers.js new file mode 100644 index 0000000000..c4df779d2b --- /dev/null +++ b/test/parallel/test-set-http-max-http-headers.js @@ -0,0 +1,102 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const { spawn } = require('child_process'); +const path = require('path'); +const testName = path.join(__dirname, 'test-http-max-http-headers.js'); + +const timeout = common.platformTimeout(100); + +const tests = []; + +function test(fn) { + tests.push(fn); +} + +test(function(cb) { + console.log('running subtest expecting failure'); + + // Validate that the test fails if the max header size is too small. + const args = ['--expose-internals', + '--max-http-header-size=1024', + testName]; + const cp = spawn(process.execPath, args, { stdio: 'inherit' }); + + cp.on('close', common.mustCall((code, signal) => { + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + cb(); + })); +}); + +test(function(cb) { + console.log('running subtest expecting success'); + + const env = Object.assign({}, process.env, { + NODE_DEBUG: 'http' + }); + + // Validate that the test now passes if the same limit is large enough. + const args = ['--expose-internals', + '--max-http-header-size=1024', + testName, + '1024']; + const cp = spawn(process.execPath, args, { + env, + stdio: 'inherit' + }); + + cp.on('close', common.mustCall((code, signal) => { + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + cb(); + })); +}); + +// Next, repeat the same checks using NODE_OPTIONS if it is supported. +if (!process.config.variables.node_without_node_options) { + const env = Object.assign({}, process.env, { + NODE_OPTIONS: '--max-http-header-size=1024' + }); + + test(function(cb) { + console.log('running subtest expecting failure'); + + // Validate that the test fails if the max header size is too small. + const args = ['--expose-internals', testName]; + const cp = spawn(process.execPath, args, { env, stdio: 'inherit' }); + + cp.on('close', common.mustCall((code, signal) => { + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + cb(); + })); + }); + + test(function(cb) { + // Validate that the test now passes if the same limit is large enough. + const args = ['--expose-internals', testName, '1024']; + const cp = spawn(process.execPath, args, { env, stdio: 'inherit' }); + + cp.on('close', common.mustCall((code, signal) => { + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + cb(); + })); + }); +} + +function runTest() { + const fn = tests.shift(); + + if (!fn) { + return; + } + + fn(() => { + setTimeout(runTest, timeout); + }); +} + +runTest(); diff --git a/test/sequential/test-http-max-http-headers.js b/test/sequential/test-http-max-http-headers.js deleted file mode 100644 index 04fdebd48c..0000000000 --- a/test/sequential/test-http-max-http-headers.js +++ /dev/null @@ -1,180 +0,0 @@ -// Flags: --expose-internals -'use strict'; -const common = require('../common'); -const assert = require('assert'); -const http = require('http'); -const net = require('net'); -const MAX = +(process.argv[2] || 8 * 1024); // Command line option, or 8KB. - -const { getOptionValue } = require('internal/options'); - -console.log('pid is', process.pid); -console.log('max header size is', getOptionValue('--max-http-header-size')); - -// Verify that we cannot receive more than 8KB of headers. - -function once(cb) { - let called = false; - return () => { - if (!called) { - called = true; - cb(); - } - }; -} - -function finished(client, callback) { - ['abort', 'error', 'end'].forEach((e) => { - client.on(e, once(() => setImmediate(callback))); - }); -} - -function fillHeaders(headers, currentSize, valid = false) { - // `llhttp` counts actual header name/value sizes, excluding the whitespace - // and stripped chars. - // OK, Content-Length, 0, X-CRASH, aaa... - headers += 'a'.repeat(MAX - currentSize); - - // Generate valid headers - if (valid) { - headers = headers.slice(0, -1); - } - return headers + '\r\n\r\n'; -} - -function writeHeaders(socket, headers) { - const array = []; - const chunkSize = 100; - let last = 0; - - for (let i = 0; i < headers.length / chunkSize; i++) { - const current = (i + 1) * chunkSize; - array.push(headers.slice(last, current)); - last = current; - } - - // Safety check we are chunking correctly - assert.strictEqual(array.join(''), headers); - - next(); - - function next() { - if (socket.destroyed) { - console.log('socket was destroyed early, data left to write:', - array.join('').length); - return; - } - - const chunk = array.shift(); - - if (chunk) { - console.log('writing chunk of size', chunk.length); - socket.write(chunk, next); - } else { - socket.end(); - } - } -} - -function test1() { - console.log('test1'); - let headers = - 'HTTP/1.1 200 OK\r\n' + - 'Content-Length: 0\r\n' + - 'X-CRASH: '; - - // OK, Content-Length, 0, X-CRASH, aaa... - const currentSize = 2 + 14 + 1 + 7; - headers = fillHeaders(headers, currentSize); - - const server = net.createServer((sock) => { - sock.once('data', () => { - writeHeaders(sock, headers); - sock.resume(); - }); - - // The socket might error but that's ok - sock.on('error', () => {}); - }); - - server.listen(0, common.mustCall(() => { - const port = server.address().port; - const client = http.get({ port: port }, common.mustNotCall()); - - client.on('error', common.mustCall((err) => { - assert.strictEqual(err.code, 'HPE_HEADER_OVERFLOW'); - server.close(test2); - })); - })); -} - -const test2 = common.mustCall(() => { - console.log('test2'); - let headers = - 'GET / HTTP/1.1\r\n' + - 'Host: localhost\r\n' + - 'Agent: nod2\r\n' + - 'X-CRASH: '; - - // /, Host, localhost, Agent, node, X-CRASH, a... - const currentSize = 1 + 4 + 9 + 5 + 4 + 7; - headers = fillHeaders(headers, currentSize); - - const server = http.createServer(common.mustNotCall()); - - server.once('clientError', common.mustCall((err) => { - assert.strictEqual(err.code, 'HPE_HEADER_OVERFLOW'); - })); - - server.listen(0, common.mustCall(() => { - const client = net.connect(server.address().port); - client.on('connect', () => { - writeHeaders(client, headers); - client.resume(); - }); - - finished(client, common.mustCall(() => { - server.close(test3); - })); - })); -}); - -const test3 = common.mustCall(() => { - console.log('test3'); - let headers = - 'GET / HTTP/1.1\r\n' + - 'Host: localhost\r\n' + - 'Agent: nod3\r\n' + - 'X-CRASH: '; - - // /, Host, localhost, Agent, node, X-CRASH, a... - const currentSize = 1 + 4 + 9 + 5 + 4 + 7; - headers = fillHeaders(headers, currentSize, true); - - console.log('writing', headers.length); - - const server = http.createServer(common.mustCall((req, res) => { - res.end('hello from test3 server'); - server.close(); - })); - - server.on('clientError', (err) => { - console.log(err.code); - if (err.code === 'HPE_HEADER_OVERFLOW') { - console.log(err.rawPacket.toString('hex')); - } - }); - server.on('clientError', common.mustNotCall()); - - server.listen(0, common.mustCall(() => { - const client = net.connect(server.address().port); - client.on('connect', () => { - writeHeaders(client, headers); - client.resume(); - }); - - client.pipe(process.stdout); - })); -}); - -test1(); diff --git a/test/sequential/test-set-http-max-http-headers.js b/test/sequential/test-set-http-max-http-headers.js deleted file mode 100644 index cfe1ed6953..0000000000 --- a/test/sequential/test-set-http-max-http-headers.js +++ /dev/null @@ -1,104 +0,0 @@ -'use strict'; - -const common = require('../common'); -const assert = require('assert'); -const { spawn } = require('child_process'); -const path = require('path'); -const testName = path.join(__dirname, 'test-http-max-http-headers.js'); - -const timeout = common.platformTimeout(100); - -const tests = []; - -function test(fn) { - tests.push(fn); -} - -test(function(cb) { - console.log('running subtest expecting failure'); - - // Validate that the test fails if the max header size is too small. - const args = ['--expose-internals', - '--max-http-header-size=1024', - testName]; - const cp = spawn(process.execPath, args, { stdio: 'inherit' }); - - cp.on('close', common.mustCall((code, signal) => { - assert.strictEqual(code, 1); - assert.strictEqual(signal, null); - cb(); - })); -}); - -test(function(cb) { - console.log('running subtest expecting success'); - - const env = Object.assign({}, process.env, { - NODE_DEBUG: 'http' - }); - - // Validate that the test fails if the max header size is too small. - // Validate that the test now passes if the same limit becomes large enough. - const args = ['--expose-internals', - '--max-http-header-size=1024', - testName, - '1024']; - const cp = spawn(process.execPath, args, { - env, - stdio: 'inherit' - }); - - cp.on('close', common.mustCall((code, signal) => { - assert.strictEqual(code, 0); - assert.strictEqual(signal, null); - cb(); - })); -}); - -// Next, repeat the same checks using NODE_OPTIONS if it is supported. -if (!process.config.variables.node_without_node_options) { - const env = Object.assign({}, process.env, { - NODE_OPTIONS: '--max-http-header-size=1024' - }); - - test(function(cb) { - console.log('running subtest expecting failure'); - - // Validate that the test fails if the max header size is too small. - const args = ['--expose-internals', testName]; - const cp = spawn(process.execPath, args, { env, stdio: 'inherit' }); - - cp.on('close', common.mustCall((code, signal) => { - assert.strictEqual(code, 1); - assert.strictEqual(signal, null); - cb(); - })); - }); - - test(function(cb) { - // Validate that the test now passes if the same limit - // becomes large enough. - const args = ['--expose-internals', testName, '1024']; - const cp = spawn(process.execPath, args, { env, stdio: 'inherit' }); - - cp.on('close', common.mustCall((code, signal) => { - assert.strictEqual(code, 0); - assert.strictEqual(signal, null); - cb(); - })); - }); -} - -function runTest() { - const fn = tests.shift(); - - if (!fn) { - return; - } - - fn(() => { - setTimeout(runTest, timeout); - }); -} - -runTest(); -- cgit v1.2.3