2012-01-31 7 views
9

Hay otras preguntas sobre este tema, pero estoy tratando de averiguar cómo acercarse a la unidad de pruebas algo como esto:Cómo escribir pruebas unitarias que pone a prueba invariantes de concurrencia

public class Semaphore extends Lock { 
     private AtomicInteger semaphore = new AtomicInteger(0); 
     public synchronized boolean available() { 
       return semaphore.intValue() == 0; 
     } 
     public synchronized void acquire() { 
      semaphore.incrementAndGet(); 

     } 
     public synchronized void release() { 
      semaphore.decrementAndGet(); 
     } 
    } 

Ésta es mi mecanismo de andar por casa de bloqueo (solo para fines de aprendizaje). ¿Cómo probaría la seguridad del hilo de esto? Sé que no hay garantías cuando se trata de probar un código concurrente, pero ¿cómo voy a escribir una prueba unitaria que INTENTE probar las constantes invariaciones inherentes a este mecanismo de bloqueo?

+0

¿El análisis estático está fuera de cuestión? – UmNyobe

+0

No, no del todo descartado. Pero me pregunto cómo sería una prueba unitaria para algo como esto ... una vez más, admitiendo que ninguna cantidad de pruebas unitarias garantiza nada cuando se trata de concurrencia. – LuxuryMode

+2

En general, empleas varios trucos: ejecuta un montón de hilos distribuidos al azar, liberando un bloqueo en un hilo mientras otros dos hilos están girando sobre él, etc. Es un arte. –

Respuesta

5

Supongo que responderé a mi propia pregunta ya que investigué. Hay un gran framework llamado MultithreadedTC. Permite configurar las pruebas de este modo:

public class SafeSemaphoreTest extends MultithreadedTestCase { 

    private SafeSemaphore semaphore; 
    AtomicInteger ai = new AtomicInteger(0); 

    @Override 
    public void initialize() { 
     semaphore = new SafeSemaphore(); 
    } 


    public void thread1() throws InterruptedException { 

     assertTick(0); 

     semaphore.acquire(); 
     waitForTick(2); 
     assertTick(2); 

     semaphore.acquire(); 
     assertEquals(semaphore.getValue(), 2); 
     assertEquals(semaphore.getValue()==3, false); 
     semaphore.release(); 
     semaphore.release(); 

    } 

    public void thread2() throws InterruptedException { 
     waitForTick(1); 
     assertTick(1); 
     assertEquals(semaphore.available(), false); 
     waitForTick(3); 
     assertTick(3); 
     assertEquals(semaphore.available(), true); 

    } 

} 

donde el waitForTick (int) hacen llamadas del bloque del hilo actual hasta que se alcanza la garrapata. Incluso hubo algunos desarrollos para hacer esto un poco más moderno para una mejor integración JUnit: http://janvanbesien.blogspot.com/2009/06/modernizing-multithreadedtc-junit-4.html

Cuestiones relacionadas