I'm using EclEmma for coverage analysis.
My Java code includes a synchronized(MyClass.class) {} block.
EclEmma says it is only partially covered, event though I've got a unit test in which one thread gets access and another thread is blocked.
Is it possible to get full coverage of synchronized using EclEmma?
Can I annotate the code in 开发者_开发百科some way to tell EclEmma to give this line full coverage?
Kind regards Roger
I am not sure it is possible to get a full coverage, since issue 2939804 reports:
EMMA always marks
synchronized(..)
as partially coveredExamples:
synchronized (lock) // partially covered (yellow line in EclEmma)
{
// ...
}
synchronized (this) // partially covered (yellow line in EclEmma)
{
// ...
}
Maybe a different tool (like Cobertura) would yield a different result? (I have not tested it recently).
Update December 2012 (more than 2 years later):
Nathan D Ryan reports:
synchronized
will light to green if the synchronized block contains code that waits on an object monitor, and a test interrupts the waiting thread.After a little experimentation, I was able to achieve complete coverage of the
synchronized
line if thesynchronized
block completed normally and completed abruptly due to an exception.
EclEmma uses Jacoco underneath for the coverage analysis.
As explained in Jacoco's (currently non-existing) JAVAC.SYNC filtering option, the behavior is a result of the byte code generated for synchronized blocks:
A Java synchronized block gets compiled into two bytecode instructions: MONITORENTER at the beginning and MONITOREXIT at the end of the block.
To ensure that the the monitor is released in any case an exception handler is installed which points to another MONITOREXIT instruction. This exception handler block typically causes partial line coverage which doesn't make sense from the source code point of view.
A related Jacoco issue 245 explains how exceptions can be triggered to reach full coverage, should this be desired, as also explained by @nathan-ryan:
- One test that executes the synchronized block normally
- A second test that throws (and hence expects) an exception from within the synchronized block.
I believe the problem is MyClass.class
which apparently is implemented using
http://emma.sourceforge.net/faq.html#q.fractional.examples
Implicit branches due to a hidden Class.forName(). This case is rather unfortunate because it is pretty common and yet the programmer has almost no control over it.
Because Class.forName() can throw checked exceptions, the compiler emits a catch block that rethrows them as unchecked. This catch block hardly ever executes in practice, but it succeeds in marking the line as partially covered.
I missed that on the first read-through.
I will try to re-write my code to get full coverage.
/Roger
精彩评论