2010-09-15 8 views
7

Ich benutze EclEmma für Coverage-Analyse.Warum deckt EclEmma nicht syncronisiert (MyClass.class)?

Mein Java-Code enthält einen synchronisierten (MyClass.class) {} -Block.

EclEmma sagt, es ist nur teilweise abgedeckt, obwohl ich einen Komponententest habe, in dem ein Thread Zugriff erhält und ein anderer Thread blockiert ist.

Ist es möglich, mit EclEmma synchronisiert zu werden?

Kann ich den Code in irgendeiner Weise annotieren, um EclEmma mitzuteilen, dass diese Zeile die volle Abdeckung bietet?

Mit freundlichen Grüßen Roger

Antwort

6

Ich bin nicht sicher, ob es möglich ist, eine vollständige Abdeckung zu erhalten, da issue 2939804 Berichte:

EMMA immer markiert synchronized(..) als teilweise

Beispiele behandelt:

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

Vielleicht würde ein anderes Werkzeug (like Cobertura) ein anderes Ergebnis liefern? (Ich habe es kürzlich nicht getestet).


-Update Dezember 2012 (mehr als 2 Jahre später):

Nathan D Ryanreports:

synchronized auf grün leuchtet, wenn der synchronisierten Block Code enthält, der auf ein Objekt Monitor wartet, und Ein Test unterbricht den wartenden Thread.

Nach ein wenig experimentieren konnte ich vollständige Abdeckung der synchronized Linie erreichen, wenn der synchronized Block normal abgeschlossen und abrupt wegen einer Ausnahme beendet.

+0

Es scheint, als ob Sie Recht haben. Ich habe das versucht: Object synch = MyClass.class; synchronisiert (synch) {}, aber es hat nicht geholfen, obwohl mein Test einen Thread wartet und ein anderer Thread den Mutex bekommt. –

+2

Meiner Erfahrung nach leuchtet 'synchronized' auf grün, wenn der synchronisierte Block Code enthält, der auf einem Objektmonitor wartet, und ein Test unterbricht den wartenden Thread. Ich habe mir nie die Mühe gemacht, mich in die EMMA-Instrumentierung zu vertiefen, um herauszufinden, ob das im allgemeinen Fall zutrifft. –

+1

Nach ein wenig Experimentieren konnte ich eine vollständige Abdeckung der "synchronisierten" Zeile erreichen, wenn der synchronisierte Block aufgrund einer Ausnahme abrupt * und * abrupt beendet wurde. –

0

Ich glaube, das Problem MyClass.class ist die offenbar implementiert

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

Implizite Zweige aufgrund einer versteckten Class.forName() verwenden. Dieser Fall ist ziemlich unglücklich, weil es ziemlich häufig ist und doch hat der Programmierer fast keine Kontrolle darüber.

Da Class.forName() geprüfte Ausnahmen auslösen kann, gibt der Compiler einen catch-Block aus, der sie erneut abhebt. Dieser Catch-Block wird in der Praxis kaum ausgeführt, es gelingt jedoch, die Zeile als teilweise abgedeckt zu markieren.

Ich verpasste das beim ersten Durchlesen.

Ich werde versuchen, meinen Code neu zu schreiben, um vollständige Abdeckung zu erhalten.

/Roger

1

EclEmma verwendet Jacoco unter der Coverage-Analyse.

Wie in Jacoco der (derzeit nicht vorhandenen) JAVAC.SYNC filtering option, das Verhalten ein Ergebnis der Bytecode für synchronisierte Blöcke generiert:

Ein Java synchronisierten Block wird in zwei Bytecode-Anweisungen kompiliert: MONITORENTER bei der Anfang und MONITOREXIT am Ende des Blocks.

Um sicherzustellen, dass der Monitor in jedem Fall freigegeben wird, wird ein Ausnahmebehandler installiert, der auf eine andere MONITOREXIT-Anweisung verweist. Dieser Ausnahmebehandlungsblock bewirkt typischerweise eine teilweise Zeilenüberdeckung, die aus Sicht des Quellcodes nicht sinnvoll ist.

Ein verwandtes Jacoco issue 245 erklärt, wie Ausnahmen ausgelöst werden kann, eine vollständige Abdeckung zu erreichen, sollte dies gewünscht werden, wie auch durch @ nathan-ryan erklärt:

  1. Ein Test, der die synchronisierten Block normalerweise
  2. ausführt
  3. Ein zweiter Test, der eine Ausnahme innerhalb des synchronisierten Blocks auslöst (und daher erwartet).
+1

(Hallo Arie). So versteht Jacoco nicht, dass der Kontrollfluss * sicher * ist: Wenn Sie den Eintrittspunkt erreichen, * * erreichen Sie den Austrittspunkt. Ich stelle mir vor, dass ein Block mit lokalen Variablen in einen Block kompiliert wird, der die Locals initialisiert, den Body ausführt und die Locals bereinigt, mit einem zusätzlichen impliziten Exception-Handler um den Block, der die Locals im Falle einer Exception bereinigt. Das scheint im Stil genauso zu sein; Dennoch können Sie die vollständige Abdeckung eines Blocks erreichen, indem Sie ihn "ausführen". (Unser Java-Tool zur Testabdeckung instrumentiert den Quellcode und würde nicht verwechselt werden). –