2010-09-15 10 views
7

Sto utilizzando EclEmma per l'analisi della copertura.Perché EclEmma non è sincronizzato (MyClass.class)?

Il mio codice Java include un blocco sincronizzato (MyClass.class) {}.

EclEmma dice che è solo parzialmente coperto, evento anche se ho un test unitario in cui un thread accede e un altro thread è bloccato.

È possibile ottenere una copertura completa sincronizzata utilizzando EclEmma?

Posso annotare il codice in qualche modo per dire a EclEmma di fornire a questa linea una copertura completa?

Cordiali saluti Roger

risposta

6

io non sono sicuro che è possibile ottenere una copertura completa, dal momento che issue 2939804 rapporti:

EMMA segna sempre synchronized(..) come parzialmente coperto

Esempi:

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

Forse uno strumento diverso (like Cobertura) fornirebbe un risultato diverso? (Non l'ho provato di recente).


Aggiornamento dicembre 2012 (più di 2 anni più tardi):

Nathan D Ryanreports:

synchronized si accende in verde se il blocco sincronizzato contiene il codice che attende su un monitor oggetto, e un test interrompe il thread in attesa.

Dopo una piccola sperimentazione, sono stato in grado di ottenere una copertura completa della linea synchronized se il blocco synchronized è stato completato normalmente e completato bruscamente a causa di un'eccezione.

+0

Sembra che tu abbia ragione. Ho provato questo: Object synch = MyClass.class; sincronizzato (synch) {} ma non è stato d'aiuto, anche se il mio test ha un thread in attesa e un altro thread che riceve il mutex. –

+2

Nella mia esperienza, 'sincronizzato' si accenderà in verde se il blocco sincronizzato contiene codice che attende su un monitor oggetto e un test interrompe il thread in attesa. Non mi sono mai preso la briga di scavare nella strumentazione EMMA per scoprire se questo è vero nel caso generale, comunque. –

+1

Dopo una piccola sperimentazione, sono stato in grado di ottenere una copertura completa della linea 'sincronizzata' se il blocco sincronizzato completato normalmente * e * completato bruscamente a causa di un'eccezione. –

0

Credo che il problema è MyClass.class che a quanto pare è implementata utilizzando

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

rami impliciti a causa di un Class.forName nascosto(). Questo caso è piuttosto sfortunato perché è abbastanza comune e tuttavia il programmatore non ha quasi alcun controllo su di esso.

Poiché Class.forName() è in grado di generare eccezioni controllate, il compilatore emette un blocco catch che le ripassa come non selezionato. Questo blocco di cattura non viene quasi mai eseguito in pratica, ma riesce a contrassegnare la linea parzialmente coperta.

Mi è mancato il primo read-through.

Proverò a riscrivere il mio codice per ottenere una copertura completa.

/Roger

1

EclEmma utilizza Jacoco sotto per l'analisi di copertura.

Come spiegato a Jacoco (attualmente inesistente) JAVAC.SYNC filtering option, il comportamento è il risultato del codice byte generato per blocchi sincronizzati:

Un Java blocco sincronizzato viene compilato in due istruzioni bytecode: MONITORENTER al all'inizio e MONITOREXIT alla fine del blocco.

Per garantire che il monitor sia rilasciato, in ogni caso viene installato un gestore di eccezioni che punta a un'altra istruzione MONITOREXIT. Questo blocco di eccezioni tipicamente causa una copertura parziale della linea che non ha senso dal punto di vista del codice sorgente.

un relativo Jacoco issue 245 spiega come eccezioni possono essere attivati ​​per raggiungere la piena copertura, ove auspicata, come spiega anche con @ nathan-Ryan:

  1. Un test che esegue il blocco sincronizzato normalmente
  2. Un secondo test che genera (e quindi si aspetta) un'eccezione all'interno del blocco sincronizzato.
+1

(Ciao Arie). Quindi Jacoco non capisce che il flusso di controllo è * sicuro *: se raggiungi il punto di ingresso, * raggiungerai * il punto di uscita. Immagino che un blocco con variabili locali sia compilato in un blocco che inizializza la gente del posto, esegue il corpo e ripulisce la gente del posto, con un gestore di eccezioni implicite addizionale avvolto attorno al blocco che ripulisce i locali in caso di un'eccezione. Sembra esattamente lo stesso in stile; tuttavia è possibile ottenere una copertura completa su un blocco "eseguendolo attraverso". (Il nostro strumento di copertura del test di Java strumenta il codice sorgente e non verrebbe confuso). –