我有一个Gradle测试任务,从给定的文件运行一系列测试。
有时,某个特定的测试执行会被卡住,无法继续执行列表中的下一个测试。
为此,我尝试添加一个Java代理来检测每个测试执行中的超时,并在这种情况下调用System.exit()。(我知道调用System.exit()似乎是一个仓促的决定,但是抛出异常似乎不能停止测试执行) 该Java代理使用Byte-Buddy建议来完成这项工作。
为此,我尝试添加一个Java代理来检测每个测试执行中的超时,并在这种情况下调用System.exit()。(我知道调用System.exit()似乎是一个仓促的决定,但是抛出异常似乎不能停止测试执行) 该Java代理使用Byte-Buddy建议来完成这项工作。
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();
}
}
这将生成一个后台线程,它将等待latch被倒计时。
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);
}
}
}
latch countDown() 方法将会被处理 OnExit advice 的方法调用。在此之前,线程会等待指定的超时时间。
我的问题是,为什么 System.exit() 调用不影响测试执行/JVM?当这个线程调用 System.exit() 时,测试线程仍然继续执行,就好像什么都没有发生一样。我想在这个时候停止测试的执行。
有什么建议可以在检测到超时时如何停止整个测试执行过程吗?
System.exit()
,它似乎没有任何意义,因为通常你会在单个 VM 中执行所有测试模块或至少大组的测试。对于 17k 个测试,你不会启动 17k 个 JVM,对吧? - kriegaex