java - Why JUnit using CountDownLatch to implement FailOnTimeout -
i started read code of junit 4.13 (https://github.com/junit-team/junit), , little confused implementation of org.junit.internal.runners.statements.failontimeout
:
@override public void evaluate() throws throwable { callablestatement callable = new callablestatement(); futuretask<throwable> task = new futuretask<throwable>(callable); threadgroup threadgroup = new threadgroup("failontimeoutgroup"); thread thread = new thread(threadgroup, task, "time-limited test"); thread.setdaemon(true); thread.start(); callable.awaitstarted(); throwable throwable = getresult(task, thread); if (throwable != null) { throw throwable; } } /** * wait test task, returning exception thrown test if * test failed, exception indicating timeout if test timed out, or * {@code null} if test passed. */ private throwable getresult(futuretask<throwable> task, thread thread) { try { if (timeout > 0) { return task.get(timeout, timeunit); // here limits time } else { return task.get(); } } catch (interruptedexception e) { return e; // caller re-throw; no need call thread.interrupt() } catch (executionexception e) { // test failed; have caller re-throw exception thrown test return e.getcause(); } catch (timeoutexception e) { return createtimeoutexception(thread); } }
where callablestatement
is:
private class callablestatement implements callable<throwable> { private final countdownlatch startlatch = new countdownlatch(1); public throwable call() throws exception { try { startlatch.countdown(); originalstatement.evaluate(); // here test runs } catch (exception e) { throw e; } catch (throwable e) { return e; } return null; } public void awaitstarted() throws interruptedexception { startlatch.await(); } }
here understanding of code:
evaluate()
starts new thread test method. callable.awaitstarted()
blocks evaluate()
until startlatch.countdown()
, , getresult()
times test method.
here question:
- why
thread
(inevaluate()
) should daemon thread? - is
countdownlatch
used blockinggetresult()
untilthread
running? work (i thought nothing can avert context switch betweencallable.awaitstarted()
,getresult()
)? there "simpler" way this?
i'm not familiar concurrency. , i'd appreciate lot if can explain these or pointing out errors. thanks.
more explanation second question:
i denote 2 threads "evaluate() thread" , "callablestatement thread".
i think "evaluate() thread" blocked when callable.awaitstarted()
executed until startlatch.countdown()
done, test method may start run before context switched "evaluate() thread". right after "evaluate() thread" awakened again, calls futuretask.get()
, block "evaluate() thread", cannot ensure "callablestatement thread" awakened right after that.
so, think moment test method beginning has nothing moment task.get(timeout, timeunit)
being called. if there plenty of other threads, there can unnegligible time interval between them.
why thread (in evaluate()) should daemon thread?
if there wrong test allows jvm exit properly. see what daemon thread in java?
is countdownlatch used blocking getresult() until thread running? work (i thought nothing can avert context switch between callable.awaitstarted() , getresult())? there "simpler" way this?
nothing can avert context switch, if thread
started , running cpu attention , originalstatement.evaluate()
executed. reason why way there might not underlying operating system thread available , test execution of test might fail although test correct. there other ways how e.g. semaphore
, countdownlatch
pretty efficient , cheap primitive that.
Comments
Post a Comment