Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix flaky test test-http-pipeline-flood #2862

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 25 additions & 12 deletions test/sequential/test-http-pipeline-flood.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@
var common = require('../common');
var assert = require('assert');


// Here we are testing the HTTP server module's flood prevention mechanism.
// When writeable.write returns false (ie the underlying send() indicated the native buffer
// is full), the HTTP server cork()s the readable part of the stream. This means that new requests
// will not be read (however request which have already been read, but are awaiting processing
// will still be processed).
// Normally when the writable stream emits a 'drain' event, the server then uncorks the readable
// stream, although we arent testing that part here.

switch (process.argv[2]) {
case undefined:
return parent();
Expand All @@ -18,22 +27,30 @@ function parent() {
var childClosed = false;
var requests = 0;
var connections = 0;
var backloggedReqs = 0;

var server = http.createServer(function(req, res) {
requests++;
res.setHeader('content-length', bigResponse.length);
res.end(bigResponse);
if(!res.write(bigResponse)){
if(backloggedReqs == 0){
// once the native buffer fills (ie write() returns false), the flood prevention should
// kick in.
// This means the stream should emit no more 'data' events. However we may still be asked
// to process more requests if they were read before mechanism activated.
req.socket.on('data', function(){assert(false)})
}
backloggedReqs++;
}
res.end();
});

server.on('connection', function(conn) {
connections++;
});

// kill the connection after a bit, verifying that the
// flood of requests was eventually halted.
server.setTimeout(200, function(conn) {
gotTimeout = true;
conn.destroy();
});

server.listen(common.PORT, function() {
Expand All @@ -53,17 +70,16 @@ function parent() {
assert.equal(connections, 1);
// The number of requests we end up processing before the outgoing
// connection backs up and requires a drain is implementation-dependent.
// We can safely assume is more than 250.
console.log('server got %d requests', requests);
assert(requests >= 250);
console.log('server sent %d backlogged requests', backloggedReqs);

console.log('ok');
});
}

function child() {
var net = require('net');

var gotEpipe = false;
var conn = net.connect({ port: common.PORT });

var req = 'GET / HTTP/1.1\r\nHost: localhost:' +
Expand All @@ -72,17 +88,14 @@ function child() {
req = new Array(10241).join(req);

conn.on('connect', function() {
//kill child after 1s of flooding
setTimeout(function(){conn.destroy()}, 1000)
write();
});

conn.on('drain', write);

conn.on('error', function(er) {
gotEpipe = true;
});

process.on('exit', function() {
assert(gotEpipe);
console.log('ok - child');
});

Expand Down