2010-05-13 10 views
9

Sono nuovo in Java e junit. Ho il seguente codice di prova che voglio testare. Ti sarei grato se potessi inviare le tue idee su quale sia il modo migliore per provarlo.Come testare il codice sincronizzato dell'unità

Fondamentalmente, il seguente codice riguarda l'elezione di un leader da un cluster. Il leader detiene un blocco sulla cache condivisa e i servizi del leader vengono ripristinati e disposti se in qualche modo perde il blocco nella cache.

Come posso essere sicuro che un leader/thread mantenga ancora il blocco sulla cache e che un altro thread non possa riprendere i suoi servizi mentre il primo è in esecuzione?

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

risposta

3

In alternativa al framework di test (o per le estensioni extra sulla cima di JUnit, se si utilizza tale) è solo un po 'di vecchio codice semplice:

  • creare diverse discussioni e applicarli a questa routine.
  • Passare attraverso i thread e testarli fino a scoprire chi è il leader.
  • Applicare modifiche ambientali diverse (incluso il passare del tempo) allo stato del programma e ripetere il test. Il leader è ancora il leader?
  • Ora, costringere il leader ad abdicare (uccidere quel filo o qualcosa del genere). È subentrato un altro thread?
4

Se non si è particolarmente interessati all'utilizzo di JUnit, è possibile utilizzare il framework TestNG. Hanno supporto multi thread.