package org.jgroups.tests;
import junit.framework.TestCase;
import org.jgroups.JChannel;
import org.jgroups.Message;
import org.jgroups.View;
import org.jgroups.util.Util;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* Tests a SEQUENCER based stack: A, B and C. B starts multicasting messages with a monotonically increasing
* number. Then A is crashed. C and B should receive *all* numbers *without* a gap.
* @author Bela Ban
* @version $Id: SequencerFailoverTest.java,v 1.3 2006/08/08 08:24:50 belaban Exp $
*/
public class SequencerFailoverTest extends TestCase {
JChannel ch1, ch2, ch3; // ch1 is the coordinator
final String GROUP="demo-group";
final int NUM_MSGS=50;
String props="UDP(mcast_addr=228.8.8.8;mcast_port=45566;ip_ttl=32;" +
"mcast_send_buf_size=150000;mcast_recv_buf_size=80000;" +
"enable_bundling=true;use_incoming_packet_handler=true;loopback=true):" +
"PING(timeout=2000;num_initial_members=3):" +
"MERGE2(min_interval=5000;max_interval=10000):" +
"FD(timeout=2000;max_tries=2):" +
"VERIFY_SUSPECT(timeout=1500):" +
"pbcast.NAKACK(gc_lag=50;retransmit_timeout=600,1200,2400,4800):" +
"UNICAST(timeout=600,1200,2400):" +
"pbcast.STABLE(desired_avg_gossip=20000):" +
"pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;" +
"shun=true;print_local_addr=true;view_ack_collection_timeout=2000):" +
"SEQUENCER";
public SequencerFailoverTest(String name) {
super(name);
}
public void setUp() throws Exception {
super.setUp();
ch1=new JChannel(props);
ch1.connect(GROUP);
ch2=new JChannel(props);
ch2.connect(GROUP);
ch3=new JChannel(props);
ch3.connect(GROUP);
}
public void tearDown() throws Exception {
super.tearDown();
if(ch3 != null) {
ch3.close();
ch3 = null;
}
if(ch2 != null) {
ch2.close();
ch2 = null;
}
}
public void testBroadcastSequence() throws Exception {
new Thread() {
public void run() {
Util.sleepRandom(100);
ch1.shutdown(); ch1=null;
}
}.start();
for(int i=1; i <= NUM_MSGS; i++) {
Util.sleep(300);
ch2.send(new Message(null, null, new Integer(i)));
System.out.print("-- messages sent: " + i + "/" + NUM_MSGS + "\r");
}
System.out.println("");
View view=ch2.getView();
System.out.println("ch2's view is " + view);
assertEquals(2, view.getMembers().size());
long total=0;
for(int i=10000; i > 0; i-=1000) {
Util.sleep(1000);
System.out.print("sleeping for " + (i/1000) + " seconds\r");
}
System.out.println("-- verifying messages on ch2 and ch3");
System.out.println("ch2 has " + ch2.getNumMessages() + " messages, ch3 has " + ch3.getNumMessages() + " messages");
verifyNumberOfMessages(NUM_MSGS, ch2);
verifyNumberOfMessages(NUM_MSGS, ch3);
}
private void verifyNumberOfMessages(int num_msgs, JChannel ch) throws Exception {
List msgs=getMessages(ch);
System.out.println("list has " + msgs.size() + " msgs (should have " + NUM_MSGS + ")");
assertEquals(num_msgs, msgs.size());
int tmp, i=1;
for(Iterator it=msgs.iterator(); it.hasNext();) {
tmp=((Integer)it.next()).intValue();
if(tmp != i)
throw new Exception("expected " + i + ", but got " + tmp);
i++;
}
}
private List getMessages(JChannel ch) throws Exception {
List retval=new LinkedList();
Object obj;
while(ch.getNumMessages() > 0) {
obj=ch.receive(1000);
if(obj instanceof Message) {
Message msg=(Message)obj;
retval.add(msg.getObject());
}
}
return retval;
}
public static void main(String[] args) {
String[] testCaseName={SequencerFailoverTest.class.getName()};
junit.textui.TestRunner.main(testCaseName);
}
}