2010-09-15 17 views
7

Estoy usando EclEmma para el análisis de cobertura.¿Por qué EclEmma no cubre syncronized (MyClass.class)?

Mi código Java incluye un bloque sincronizado (MyClass.class) {}.

EclEmma dice que está parcialmente cubierto, aunque tengo una prueba de unidad en la que un hilo tiene acceso y otro hilo está bloqueado.

¿Es posible obtener una cobertura completa de sincronización utilizando EclEmma?

¿Puedo anotar el código de alguna manera para decirle a EclEmma que proporcione a esta línea una cobertura completa?

Saludos cordiales Roger

Respuesta

6

No estoy seguro de que es posible obtener una cobertura total, ya que issue 2939804 informes:

EMMA marcas siempre synchronized(..) como parcialmente cubierto

Ejemplos:

synchronized (lock) // partially covered (yellow line in EclEmma) 
{ 
// ... 
} 
synchronized (this) // partially covered (yellow line in EclEmma) 
{ 
// ... 
} 

Tal vez una herramienta diferente (like Cobertura) arrojaría un resultado diferente? (No lo he probado recientemente).


actualización diciembre de 2012 (más de 2 años después):

Nathan D Ryanreports:

synchronized se iluminará al verde si el bloque sincronizado contiene código que espera en un monitor objeto, y una prueba interrumpe el hilo de espera.

Después de un poco de experimentación, yo era capaz de conseguir una cobertura completa de la línea synchronized si el bloque synchronized completa normalmente y completó abruptamente debido a una excepción.

+0

Parece que tienes razón. Intenté esto: Object synch = MyClass.class; synchronized (synch) {} pero no sirvió de nada, aunque mi prueba tiene un hilo en espera y otro hilo que obtiene el mutex. –

+2

En mi experiencia, 'synchronized' se iluminará en verde si el bloque sincronizado contiene código que espera en un monitor de objetos, y una prueba interrumpe el hilo de espera. Sin embargo, nunca me molesté en profundizar en la instrumentación EMMA para saber si esto es cierto en el caso general. –

+1

Después de un poco de experimentación, pude lograr una cobertura completa de la línea 'sincronizada' si el bloque sincronizado completado normalmente * y * se completó abruptamente debido a una excepción. –

0

Creo que el problema es MyClass.class que al parecer se implementa utilizando

http://emma.sourceforge.net/faq.html#q.fractional.examples

ramas implícitos debido a una Class.forName oculta(). Este caso es bastante desafortunado porque es bastante común y, sin embargo, el programador casi no tiene control sobre él.

Dado que Class.forName() puede arrojar excepciones comprobadas, el compilador emite un bloque catch que las vuelve a activar como no marcadas. Este bloque catch casi nunca se ejecuta en la práctica, pero logra marcar la línea como parcialmente cubierta.

Me lo perdí en la primera lectura.

Intentaré volver a escribir mi código para obtener una cobertura completa.

/Roger

1

EclEmma utiliza Jacoco debajo para el análisis de la cobertura.

Como se explica en la Jacoco (actualmente inexistente) JAVAC.SYNC filtering option, el comportamiento es el resultado del código de bytes generada por bloques sincronizados:

Java bloque sincronizado se compila en dos instrucciones de código de bytes: MonitorEnter en el comenzando y MONITOREXIT al final del bloque.

Para garantizar que el monitor se libere, en cualquier caso, se instala un controlador de excepción que apunta a otra instrucción MONITOREXIT. Este bloque de controlador de excepciones normalmente causa una cobertura de línea parcial que no tiene sentido desde el punto de vista del código fuente.

Un relacionada Jacoco issue 245 explica cómo las excepciones se pueden activar para alcanzar una cobertura total, si así se desea, según se explica también por @ Nathan-Ryan:

  1. Una prueba que ejecuta el bloque sincronizado normalmente
  2. Una segunda prueba que arroja (y por lo tanto espera) una excepción desde dentro del bloque sincronizado.
+1

(Hola Arie). Entonces Jacoco no entiende que el flujo de control es * seguro *: si llega al punto de entrada, * alcanzará * el punto de salida. Imagino que un bloque con variables locales se compila en un bloque que inicializa a los locales, ejecuta el cuerpo y limpia los locales, con un manejador de excepciones implícito adicional alrededor del bloque que limpia los locales en caso de una excepción. Eso parece exactamente lo mismo en estilo; sin embargo, puede obtener cobertura completa en un bloque "ejecutando a través de". (Nuestra herramienta de cobertura de prueba de Java instrumenta el código fuente y no se confundiría). –

Cuestiones relacionadas