Skip to content

Commit 7245082

Browse files
TrottMylesBorins
authored andcommittedSep 20, 2017
test: make timers-blocking-callback more reliable
test-timers-blocking-callback may fail erroneously on resource-constrained machines due to the timing nature of the test. There is likely no way around the timing issue. This change tries to decrease the probability of the test failing erroneously by having it retry a small number of times on failure. Tested on 0.10.38 (which has a bug that this test was written for) and (modifying the test slightly to remove ES6 stuff) the test still seems to fail 100% of the time there, which is what we want/expect. PR-URL: #14831 Fixes: #14792 Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Jeremiah Senkpiel <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent c76a54f commit 7245082

File tree

1 file changed

+52
-18
lines changed

1 file changed

+52
-18
lines changed
 

‎test/sequential/test-timers-blocking-callback.js

+52-18
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
'use strict';
22

33
/*
4-
* This is a regression test for https://github.com/joyent/node/issues/15447
5-
* and https://github.com/joyent/node/issues/9333.
4+
* This is a regression test for
5+
* https://github.com/nodejs/node-v0.x-archive/issues/15447 and
6+
* and https://github.com/nodejs/node-v0.x-archive/issues/9333.
67
*
78
* When a timer is added in another timer's callback, its underlying timer
89
* handle was started with a timeout that was actually incorrect.
@@ -28,17 +29,23 @@ const Timer = process.binding('timer_wrap').Timer;
2829

2930
const TIMEOUT = 100;
3031

31-
let nbBlockingCallbackCalls = 0;
32-
let latestDelay = 0;
33-
let timeCallbackScheduled = 0;
32+
let nbBlockingCallbackCalls;
33+
let latestDelay;
34+
let timeCallbackScheduled;
35+
36+
// These tests are timing dependent so they may fail even when the bug is
37+
// not present (if the host is sufficiently busy that the timers are delayed
38+
// significantly). However, they fail 100% of the time when the bug *is*
39+
// present, so to increase reliability, allow for a small number of retries.
40+
let retries = 2;
3441

3542
function initTest() {
3643
nbBlockingCallbackCalls = 0;
3744
latestDelay = 0;
3845
timeCallbackScheduled = 0;
3946
}
4047

41-
function blockingCallback(callback) {
48+
function blockingCallback(retry, callback) {
4249
++nbBlockingCallbackCalls;
4350

4451
if (nbBlockingCallbackCalls > 1) {
@@ -47,34 +54,61 @@ function blockingCallback(callback) {
4754
// to fire, they shouldn't generally be more than 100% late in this case.
4855
// But they are guaranteed to be at least 100ms late given the bug in
4956
// https://github.com/nodejs/node-v0.x-archive/issues/15447 and
50-
// https://github.com/nodejs/node-v0.x-archive/issues/9333..
51-
assert(latestDelay < TIMEOUT * 2);
57+
// https://github.com/nodejs/node-v0.x-archive/issues/9333.
58+
if (latestDelay >= TIMEOUT * 2) {
59+
if (retries > 0) {
60+
retries--;
61+
return retry(callback);
62+
}
63+
assert.fail(null, null,
64+
`timeout delayed by more than 100% (${latestDelay}ms)`);
65+
}
5266
if (callback)
5367
return callback();
5468
} else {
5569
// block by busy-looping to trigger the issue
5670
common.busyLoop(TIMEOUT);
5771

5872
timeCallbackScheduled = Timer.now();
59-
setTimeout(blockingCallback.bind(null, callback), TIMEOUT);
73+
setTimeout(blockingCallback.bind(null, retry, callback), TIMEOUT);
6074
}
6175
}
6276

63-
const testAddingTimerToEmptyTimersList = common.mustCall(function(callback) {
77+
function testAddingTimerToEmptyTimersList(callback) {
6478
initTest();
6579
// Call setTimeout just once to make sure the timers list is
6680
// empty when blockingCallback is called.
67-
setTimeout(blockingCallback.bind(null, callback), TIMEOUT);
68-
});
81+
setTimeout(
82+
blockingCallback.bind(null, testAddingTimerToEmptyTimersList, callback),
83+
TIMEOUT
84+
);
85+
}
86+
87+
function testAddingTimerToNonEmptyTimersList() {
88+
// If both timers fail and attempt a retry, only actually do anything for one
89+
// of them.
90+
let retryOK = true;
91+
const retry = () => {
92+
if (retryOK)
93+
testAddingTimerToNonEmptyTimersList();
94+
retryOK = false;
95+
};
6996

70-
const testAddingTimerToNonEmptyTimersList = common.mustCall(function() {
7197
initTest();
7298
// Call setTimeout twice with the same timeout to make
7399
// sure the timers list is not empty when blockingCallback is called.
74-
setTimeout(blockingCallback, TIMEOUT);
75-
setTimeout(blockingCallback, TIMEOUT);
76-
});
100+
setTimeout(
101+
blockingCallback.bind(null, retry),
102+
TIMEOUT
103+
);
104+
setTimeout(
105+
blockingCallback.bind(null, retry),
106+
TIMEOUT
107+
);
108+
}
77109

78110
// Run the test for the empty timers list case, and then for the non-empty
79-
// timers list one
80-
testAddingTimerToEmptyTimersList(testAddingTimerToNonEmptyTimersList);
111+
// timers list one.
112+
testAddingTimerToEmptyTimersList(
113+
common.mustCall(testAddingTimerToNonEmptyTimersList)
114+
);

0 commit comments

Comments
 (0)
Please sign in to comment.