I have a gradle test task which runs a list of tests from a given file. Sometimes, any particular test execution simply gets stuck and does not move on to execute the next test(s) in the list.
For this, I am trying to add a java agent which will detect timeouts in each test execution and calls System.exit() in this case. (I know calling System.exit() seems to be a rash decision, but throwing exception does not seem to stop the test execution) The java agent uses byte-buddy advices for doing this.
public class TimerAdvice {
public static CountDownLatch latch;
@Advice.OnMethodEnter
static long enter(@Advice.This Object thisObject,
@Advice.Origin String origin,
@Advice.Origin("#t #m") String detaildOrigin) throws InterruptedException {
System.out.println("Timer Advice Enter thread: " + Thread.currentThread().getName() + " time: " + Instant.now().toString());
latch = new CountDownLatch(1);
ThreadFactory factory = new MyThreadFactory(new MyExceptionHandler());
ExecutorService threadPool = Executors.newFixedThreadPool(1, factory);
threadPool.execute(new TestCallable());
return System.nanoTime();
}
@Advice.OnMethodExit (onThrowable = Throwable.class)
static void onExit(@Advice.Origin Method method) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
System.out.println("Timer Advice Exit thread: " + Thread.currentThread().getName() + " time: " + Instant.now().toString());
System.out.println("Counting down");
latch.countDown();
}
}
Basically this will spawn a background thread that will wait until the latch is counted down.
public class TestCallable implements Runnable {
@Override
public void run() {
try {
latch.await(10, TimeUnit.MINUTES);
} catch (InterruptedException e) {
e.printStackTrace();
throw new IllegalStateException(e.getMessage());
}
if(latch.getCount() > 0) {
System.err.println("Callable thread"
+ Thread.currentThread().getName() +
"TIMEOUT OCCURED!!!!");
System.exit(1);
}
}
}
The latch countDown() method will be called by the method that handles the OnExit advice. Until then, the thread will wait for the specified timeout.
My question is, Why is the System.exit() call not affecting the test execution/jvm When this thread calls the System.exit(), the test thread still continues to execute as if nothing had happened. I would like to stop the execution of the test at this point.
Any suggestions on how should I stop the entire test execution process when the timeout is detected?