2010-05-13 10 views
9

Soy nuevo en Java y junit. Tengo el siguiente fragmento de código que quiero probar. Le agradecería si pudiera enviar sus ideas sobre cuál es la mejor manera de probarlo.Cómo probar el código sincronizado de la unidad

Básicamente, el siguiente código trata de elegir un líder de un clúster. El líder mantiene un bloqueo en la memoria caché compartida y los servicios del líder se reanudan y eliminan si de alguna manera pierde el bloqueo en la memoria caché.

¿Cómo puedo asegurarme de que un líder/hilo aún mantiene el bloqueo en el caché y que otro hilo no puede reanudar sus servicios mientras el primero está en ejecución?

public interface ContinuousService { 

public void resume(); 
public void pause(); 
} 


public abstract class ClusterServiceManager { 
private volatile boolean leader = false; 
private volatile boolean electable = true; 
private List<ContinuousService> services; 

protected synchronized void onElected() { 
    if (!leader) { 
     for (ContinuousService service : services) { 
      service.resume(); 
     } 
     leader = true; 
    } 
} 

protected synchronized void onDeposed() { 
    if (leader) { 
     for (ContinuousService service : services) { 
      service.pause(); 
     } 
     leader = false; 
    } 
} 

public void setServices(List<ContinuousService> services) { 
    this.services = services; 
} 

@ManagedAttribute 
public boolean isElectable() { 
    return electable; 
} 

@ManagedAttribute 
public boolean isLeader() { 
    return leader; 
} 



public class TangosolLeaderElector extends ClusterServiceManager implements Runnable { 
private static final Logger log = LoggerFactory.getLogger(TangosolLeaderElector.class); 
private String election; 
private long electionWaitTime= 5000L; 

private NamedCache cache; 

public void start() { 
    log.info("Starting LeaderElector ({})",election); 
    Thread t = new Thread(this, "LeaderElector ("+election+")"); 
    t.setDaemon(true); 
    t.start(); 
} 

public void run() { 
    // Give the connection a chance to start itself up 
    try { 
     Thread.sleep(1000); 
    } catch (InterruptedException e) {} 

    boolean wasElectable = !isElectable(); 
    while (true) { 
     if (isElectable()) { 
      if (!wasElectable) { 
       log.info("Leadership requested on election: {}",election); 
       wasElectable = isElectable(); 
      } 
      boolean elected = false; 
      try { 
       // Try and get the lock on the LeaderElectorCache for the current election 
       if (!cache.lock(election, electionWaitTime)) { 
        // We didn't get the lock. cycle round again. 
        // This code to ensure we check the electable flag every now & then 
        continue; 
       } 
       elected = true; 
       log.info("Leadership taken on election: {}",election); 
       onElected(); 

       // Wait here until the services fail in some way. 
       while (true) { 
        try { 
         Thread.sleep(electionWaitTime); 
        } catch (InterruptedException e) {} 
        if (!cache.lock(election, 0)) { 
         log.warn("Cache lock no longer held for election: {}", election); 
         break; 
        } else if (!isElectable()) { 
         log.warn("Node is no longer electable for election: {}", election); 
         break; 
        } 
        // We're fine - loop round and go back to sleep. 
       } 
      } catch (Exception e) { 
       if (log.isErrorEnabled()) { 
        log.error("Leadership election " + election + " failed (try bfmq logs for details)", e); 
       } 
      } finally { 
       if (elected) { 
        cache.unlock(election); 
        log.info("Leadership resigned on election: {}",election); 
        onDeposed(); 
       } 
       // On deposition, do not try and get re-elected for at least the standard wait time. 
       try { Thread.sleep(electionWaitTime); } catch (InterruptedException e) {} 
      } 
     } else { 
      // Not electable - wait a bit and check again. 
      if (wasElectable) { 
       log.info("Leadership NOT requested on election ({}) - node not electable",election); 
       wasElectable = isElectable(); 
      } 
      try { 
       Thread.sleep(electionWaitTime); 
      } catch (InterruptedException e) {} 
     } 
    } 
} 

public void setElection(String election) { 
    this.election = election; 
} 

@ManagedAttribute 
public String getElection() { 
    return election; 
} 

public void setNamedCache(NamedCache nc) { 
    this.cache = nc; 
} 
+0

http://today.java.net/article/2003/07/12/multithreaded-tests-junit http://www.junit.org/node/54 – Bozho

Respuesta

3

Como alternativa a los marcos de prueba (o en las extensiones adicionales en la parte superior de JUnit, si está utilizando eso) es sólo un código simple y llano:

  • crear varios hilos y aplicarlos a esta rutina.
  • Pasa por los hilos y prueba cada uno hasta saber quién es el líder.
  • Aplique diferentes cambios ambientales (incluido el paso del tiempo) al estado de su programa y vuelva a realizar la prueba. ¿El líder sigue siendo el líder?
  • Ahora, obligue al líder a abdicar (mate ese hilo o algo así). ¿Se hizo cargo de otro hilo?
4

Si no es demasiado particular sobre el uso de JUnit, entonces puede usar TestNG framework. Tienen soporte multihilo.

Cuestiones relacionadas