SingleThreadEventLoopTest failures
Motivation: Some unit tests in SingleThreadEventLoopTest rely upon Thread.sleep for sequencing events between threads. This can be unreliable and result in spurious test failures if thread scheduling does not occur in a fair predictable manner. Modifications: - Reduce the reliance on Thread.sleep in SingleThreadEventLoopTest Result: Fixes https://github.com/netty/netty/issues/5851
This commit is contained in:
parent
32a560e42c
commit
eb1dfb8f5e
@ -169,18 +169,20 @@ public class SingleThreadEventLoopTest {
|
|||||||
is(greaterThanOrEqualTo(TimeUnit.MILLISECONDS.toNanos(500))));
|
is(greaterThanOrEqualTo(TimeUnit.MILLISECONDS.toNanos(500))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(timeout = 5000)
|
||||||
public void scheduleTaskAtFixedRateA() throws Exception {
|
public void scheduleTaskAtFixedRateA() throws Exception {
|
||||||
testScheduleTaskAtFixedRate(loopA);
|
testScheduleTaskAtFixedRate(loopA);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(timeout = 5000)
|
||||||
public void scheduleTaskAtFixedRateB() throws Exception {
|
public void scheduleTaskAtFixedRateB() throws Exception {
|
||||||
testScheduleTaskAtFixedRate(loopB);
|
testScheduleTaskAtFixedRate(loopB);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void testScheduleTaskAtFixedRate(EventLoop loopA) throws InterruptedException {
|
private static void testScheduleTaskAtFixedRate(EventLoop loopA) throws InterruptedException {
|
||||||
final Queue<Long> timestamps = new LinkedBlockingQueue<Long>();
|
final Queue<Long> timestamps = new LinkedBlockingQueue<Long>();
|
||||||
|
final int expectedTimeStamps = 5;
|
||||||
|
final CountDownLatch allTimeStampsLatch = new CountDownLatch(expectedTimeStamps);
|
||||||
ScheduledFuture<?> f = loopA.scheduleAtFixedRate(new Runnable() {
|
ScheduledFuture<?> f = loopA.scheduleAtFixedRate(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -190,11 +192,13 @@ public class SingleThreadEventLoopTest {
|
|||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
|
allTimeStampsLatch.countDown();
|
||||||
}
|
}
|
||||||
}, 100, 100, TimeUnit.MILLISECONDS);
|
}, 100, 100, TimeUnit.MILLISECONDS);
|
||||||
Thread.sleep(550);
|
allTimeStampsLatch.await();
|
||||||
assertTrue(f.cancel(true));
|
assertTrue(f.cancel(true));
|
||||||
assertEquals(5, timestamps.size());
|
Thread.sleep(300);
|
||||||
|
assertEquals(expectedTimeStamps, timestamps.size());
|
||||||
|
|
||||||
// Check if the task was run without a lag.
|
// Check if the task was run without a lag.
|
||||||
Long firstTimestamp = null;
|
Long firstTimestamp = null;
|
||||||
@ -213,18 +217,20 @@ public class SingleThreadEventLoopTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(timeout = 5000)
|
||||||
public void scheduleLaggyTaskAtFixedRateA() throws Exception {
|
public void scheduleLaggyTaskAtFixedRateA() throws Exception {
|
||||||
testScheduleLaggyTaskAtFixedRate(loopA);
|
testScheduleLaggyTaskAtFixedRate(loopA);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(timeout = 5000)
|
||||||
public void scheduleLaggyTaskAtFixedRateB() throws Exception {
|
public void scheduleLaggyTaskAtFixedRateB() throws Exception {
|
||||||
testScheduleLaggyTaskAtFixedRate(loopB);
|
testScheduleLaggyTaskAtFixedRate(loopB);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void testScheduleLaggyTaskAtFixedRate(EventLoop loopA) throws InterruptedException {
|
private static void testScheduleLaggyTaskAtFixedRate(EventLoop loopA) throws InterruptedException {
|
||||||
final Queue<Long> timestamps = new LinkedBlockingQueue<Long>();
|
final Queue<Long> timestamps = new LinkedBlockingQueue<Long>();
|
||||||
|
final int expectedTimeStamps = 5;
|
||||||
|
final CountDownLatch allTimeStampsLatch = new CountDownLatch(expectedTimeStamps);
|
||||||
ScheduledFuture<?> f = loopA.scheduleAtFixedRate(new Runnable() {
|
ScheduledFuture<?> f = loopA.scheduleAtFixedRate(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -237,11 +243,13 @@ public class SingleThreadEventLoopTest {
|
|||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
allTimeStampsLatch.countDown();
|
||||||
}
|
}
|
||||||
}, 100, 100, TimeUnit.MILLISECONDS);
|
}, 100, 100, TimeUnit.MILLISECONDS);
|
||||||
Thread.sleep(550);
|
allTimeStampsLatch.await();
|
||||||
assertTrue(f.cancel(true));
|
assertTrue(f.cancel(true));
|
||||||
assertEquals(5, timestamps.size());
|
Thread.sleep(300);
|
||||||
|
assertEquals(expectedTimeStamps, timestamps.size());
|
||||||
|
|
||||||
// Check if the task was run with lag.
|
// Check if the task was run with lag.
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -263,18 +271,20 @@ public class SingleThreadEventLoopTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(timeout = 5000)
|
||||||
public void scheduleTaskWithFixedDelayA() throws Exception {
|
public void scheduleTaskWithFixedDelayA() throws Exception {
|
||||||
testScheduleTaskWithFixedDelay(loopA);
|
testScheduleTaskWithFixedDelay(loopA);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(timeout = 5000)
|
||||||
public void scheduleTaskWithFixedDelayB() throws Exception {
|
public void scheduleTaskWithFixedDelayB() throws Exception {
|
||||||
testScheduleTaskWithFixedDelay(loopB);
|
testScheduleTaskWithFixedDelay(loopB);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void testScheduleTaskWithFixedDelay(EventLoop loopA) throws InterruptedException {
|
private static void testScheduleTaskWithFixedDelay(EventLoop loopA) throws InterruptedException {
|
||||||
final Queue<Long> timestamps = new LinkedBlockingQueue<Long>();
|
final Queue<Long> timestamps = new LinkedBlockingQueue<Long>();
|
||||||
|
final int expectedTimeStamps = 3;
|
||||||
|
final CountDownLatch allTimeStampsLatch = new CountDownLatch(expectedTimeStamps);
|
||||||
ScheduledFuture<?> f = loopA.scheduleWithFixedDelay(new Runnable() {
|
ScheduledFuture<?> f = loopA.scheduleWithFixedDelay(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -284,11 +294,13 @@ public class SingleThreadEventLoopTest {
|
|||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
|
allTimeStampsLatch.countDown();
|
||||||
}
|
}
|
||||||
}, 100, 100, TimeUnit.MILLISECONDS);
|
}, 100, 100, TimeUnit.MILLISECONDS);
|
||||||
Thread.sleep(500);
|
allTimeStampsLatch.await();
|
||||||
assertTrue(f.cancel(true));
|
assertTrue(f.cancel(true));
|
||||||
assertEquals(3, timestamps.size());
|
Thread.sleep(300);
|
||||||
|
assertEquals(expectedTimeStamps, timestamps.size());
|
||||||
|
|
||||||
// Check if the task was run without a lag.
|
// Check if the task was run without a lag.
|
||||||
Long previousTimestamp = null;
|
Long previousTimestamp = null;
|
||||||
|
Loading…
Reference in New Issue
Block a user