package cucumber.runtime;
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeoutException;
import static java.lang.Thread.sleep;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class TimeoutTest {
@Test
public void doesnt_time_out_if_it_doesnt_take_too_long() throws Throwable {
final Slow slow = new Slow();
String what = Timeout.timeout(new Timeout.Callback<String>() {
@Override
public String call() throws Throwable {
return slow.slow(10);
}
}, 50);
assertEquals("slept 10ms", what);
}
@Test(expected = TimeoutException.class)
public void times_out_if_it_takes_too_long() throws Throwable {
final Slow slow = new Slow();
Timeout.timeout(new Timeout.Callback<String>() {
@Override
public String call() throws Throwable {
return slow.slow(100);
}
}, 50);
fail();
}
@Test(expected = TimeoutException.class)
public void times_out_infinite_loop_if_it_takes_too_long() throws Throwable {
final Slow slow = new Slow();
Timeout.timeout(new Timeout.Callback<Void>() {
@Override
public Void call() throws Throwable {
slow.infinite();
return null;
}
}, 10);
fail();
}
@Test(expected = TimeoutException.class)
public void times_out_infinite_latch_wait_if_it_takes_too_long() throws Throwable {
final Slow slow = new Slow();
Timeout.timeout(new Timeout.Callback<Void>() {
@Override
public Void call() throws Throwable {
slow.infiniteLatchWait();
return null;
}
}, 10);
fail();
}
@Test
public void doesnt_leak_threads() throws Throwable {
long initialNumberOfThreads = Thread.getAllStackTraces().size();
long currentNumberOfThreads = Long.MAX_VALUE;
boolean cleanedUp = false;
for (int i = 0; i < 1000; i++) {
Timeout.timeout(new Timeout.Callback<String>() {
@Override
public String call() throws Throwable {
return null;
}
}, 10);
Thread.sleep(5);
currentNumberOfThreads = Thread.getAllStackTraces().size();
if (i > 20 && currentNumberOfThreads <= initialNumberOfThreads) {
cleanedUp = true;
break;
}
}
assertTrue(String.format("Threads weren't cleaned up, initial count: %d current count: %d",
initialNumberOfThreads, currentNumberOfThreads),
cleanedUp);
}
public static class Slow {
public String slow(int millis) throws InterruptedException {
sleep(millis);
return String.format("slept %sms", millis);
}
public void infinite() throws InterruptedException {
while (true) {
sleep(1);
}
}
public void infiniteLatchWait() throws InterruptedException {
new CountDownLatch(1).await();
}
}
}