Skip to content

Commit 4963228

Browse files
TrottMylesBorins
authored andcommitted
test: fix flaky http(s)-set-server-timeout tests
The tests include a callback that might not be invoked but is wrapped in common.mustCall(). Remove the common.mustCall() wrapper and add a comment explaining that it should not be added. Add a new test case that sets the timeout to 1ms and waits for both the connection handler and the timeout handler to be invoked. This version keeps the common.mustCall() wrapper intact around the connection handler (although it's mostly semantic and not necessary for the test as the test will certainly fail or time out if that handler isn't invoked). PR-URL: #14380 Fixes: #11768 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent ae7eeff commit 4963228

File tree

2 files changed

+102
-24
lines changed

2 files changed

+102
-24
lines changed

test/parallel/test-http-set-timeout-server.js

+49-10
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@ function run() {
2121
}
2222

2323
test(function serverTimeout(cb) {
24-
const server = http.createServer((req, res) => {
25-
// Do nothing. We should get a timeout event.
26-
// Might not be invoked. Do not wrap in common.mustCall().
27-
});
24+
const server = http.createServer();
2825
server.listen(common.mustCall(() => {
2926
const s = server.setTimeout(50, common.mustCall((socket) => {
3027
socket.destroy();
@@ -104,11 +101,14 @@ test(function serverResponseTimeoutWithPipeline(cb) {
104101
const server = http.createServer((req, res) => {
105102
if (req.url === '/2')
106103
secReceived = true;
104+
if (req.url === '/1') {
105+
res.end();
106+
return;
107+
}
107108
const s = res.setTimeout(50, () => {
108109
caughtTimeout += req.url;
109110
});
110111
assert.ok(s instanceof http.OutgoingMessage);
111-
if (req.url === '/1') res.end();
112112
});
113113
server.on('timeout', common.mustCall((socket) => {
114114
if (secReceived) {
@@ -131,17 +131,56 @@ test(function serverResponseTimeoutWithPipeline(cb) {
131131
});
132132

133133
test(function idleTimeout(cb) {
134-
const server = http.createServer(common.mustCall((req, res) => {
135-
req.on('timeout', common.mustNotCall());
136-
res.on('timeout', common.mustNotCall());
137-
res.end();
138-
}));
134+
// Test that the an idle connection invokes the timeout callback.
135+
const server = http.createServer();
139136
const s = server.setTimeout(50, common.mustCall((socket) => {
140137
socket.destroy();
141138
server.close();
142139
cb();
143140
}));
144141
assert.ok(s instanceof http.Server);
142+
server.listen(common.mustCall(() => {
143+
const options = {
144+
port: server.address().port,
145+
allowHalfOpen: true,
146+
};
147+
const c = net.connect(options, () => {
148+
// ECONNRESET could happen on a heavily-loaded server.
149+
c.on('error', (e) => {
150+
if (e.message !== 'read ECONNRESET')
151+
throw e;
152+
});
153+
c.write('GET /1 HTTP/1.1\r\nHost: localhost\r\n\r\n');
154+
// Keep-Alive
155+
});
156+
}));
157+
});
158+
159+
test(function fastTimeout(cb) {
160+
let connectionHandlerInvoked = false;
161+
let timeoutHandlerInvoked = false;
162+
let connectionSocket;
163+
164+
function invokeCallbackIfDone() {
165+
if (connectionHandlerInvoked && timeoutHandlerInvoked) {
166+
connectionSocket.destroy();
167+
server.close();
168+
cb();
169+
}
170+
}
171+
172+
const server = http.createServer(common.mustCall((req, res) => {
173+
req.on('timeout', common.mustNotCall());
174+
res.end();
175+
connectionHandlerInvoked = true;
176+
invokeCallbackIfDone();
177+
}));
178+
const s = server.setTimeout(1, common.mustCall((socket) => {
179+
connectionSocket = socket;
180+
timeoutHandlerInvoked = true;
181+
invokeCallbackIfDone();
182+
}));
183+
assert.ok(s instanceof http.Server);
145184
server.listen(common.mustCall(() => {
146185
const options = {
147186
port: server.address().port,

test/parallel/test-https-set-timeout-server.js

+53-14
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,7 @@ function run() {
3434
}
3535

3636
test(function serverTimeout(cb) {
37-
const server = https.createServer(
38-
serverOptions,
39-
(req, res) => {
40-
// Do nothing. We should get a timeout event.
41-
// Might not be invoked. Do not wrap in common.mustCall().
42-
});
37+
const server = https.createServer(serverOptions);
4338
server.listen(common.mustCall(() => {
4439
const s = server.setTimeout(50, common.mustCall((socket) => {
4540
socket.destroy();
@@ -129,11 +124,14 @@ test(function serverResponseTimeoutWithPipeline(cb) {
129124
const server = https.createServer(serverOptions, (req, res) => {
130125
if (req.url === '/2')
131126
secReceived = true;
127+
if (req.url === '/1') {
128+
res.end();
129+
return;
130+
}
132131
const s = res.setTimeout(50, () => {
133132
caughtTimeout += req.url;
134133
});
135134
assert.ok(s instanceof http.OutgoingMessage);
136-
if (req.url === '/1') res.end();
137135
});
138136
server.on('timeout', common.mustCall((socket) => {
139137
if (secReceived) {
@@ -157,19 +155,60 @@ test(function serverResponseTimeoutWithPipeline(cb) {
157155
});
158156

159157
test(function idleTimeout(cb) {
160-
const server = https.createServer(
161-
serverOptions,
162-
common.mustCall((req, res) => {
163-
req.on('timeout', common.mustNotCall());
164-
res.on('timeout', common.mustNotCall());
165-
res.end();
166-
}));
158+
// Test that the an idle connection invokes the timeout callback.
159+
const server = https.createServer(serverOptions);
167160
const s = server.setTimeout(50, common.mustCall((socket) => {
168161
socket.destroy();
169162
server.close();
170163
cb();
171164
}));
172165
assert.ok(s instanceof https.Server);
166+
server.listen(common.mustCall(() => {
167+
const options = {
168+
port: server.address().port,
169+
allowHalfOpen: true,
170+
rejectUnauthorized: false
171+
};
172+
const c = tls.connect(options, () => {
173+
// ECONNRESET could happen on a heavily-loaded server.
174+
c.on('error', (e) => {
175+
if (e.message !== 'read ECONNRESET')
176+
throw e;
177+
});
178+
c.write('GET /1 HTTP/1.1\r\nHost: localhost\r\n\r\n');
179+
// Keep-Alive
180+
});
181+
}));
182+
});
183+
184+
test(function fastTimeout(cb) {
185+
// Test that the socket timeout fires but no timeout fires for the request.
186+
let connectionHandlerInvoked = false;
187+
let timeoutHandlerInvoked = false;
188+
let connectionSocket;
189+
190+
function invokeCallbackIfDone() {
191+
if (connectionHandlerInvoked && timeoutHandlerInvoked) {
192+
connectionSocket.destroy();
193+
server.close();
194+
cb();
195+
}
196+
}
197+
198+
const server = https.createServer(serverOptions, common.mustCall(
199+
(req, res) => {
200+
req.on('timeout', common.mustNotCall());
201+
res.end();
202+
connectionHandlerInvoked = true;
203+
invokeCallbackIfDone();
204+
}
205+
));
206+
const s = server.setTimeout(1, common.mustCall((socket) => {
207+
connectionSocket = socket;
208+
timeoutHandlerInvoked = true;
209+
invokeCallbackIfDone();
210+
}));
211+
assert.ok(s instanceof https.Server);
173212
server.listen(common.mustCall(() => {
174213
const options = {
175214
port: server.address().port,

0 commit comments

Comments
 (0)