package org.jgroups.protocols; import org.jgroups.*; import org.jgroups.protocols.pbcast.GMS; import org.jgroups.protocols.pbcast.NAKACK2; import org.jgroups.stack.Protocol; import org.jgroups.stack.ProtocolStack; import org.jgroups.util.Util; import org.testng.annotations.AfterMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.util.Collections; import java.util.LinkedList; import java.util.List; /** * Tests the UNICAST protocol for OOB msgs, tests http://jira.jboss.com/jira/browse/JGRP-377 * @author Bela Ban */ @Test(groups=Global.FUNCTIONAL,singleThreaded=true) public class UNICAST_OOB_Test { JChannel a, b; void setUp(Class<? extends Protocol> unicast_class) throws Exception { a=createChannel(unicast_class, "A"); b=createChannel(unicast_class, "B"); } @AfterMethod void tearDown() throws Exception { Util.close(b,a); } @DataProvider static Object[][] configProvider() { return new Object[][]{ {UNICAST3.class} }; } @Test(dataProvider="configProvider") public void testRegularMessages(Class<? extends Protocol> unicast_class) throws Exception { setUp(unicast_class); sendMessages(false); } @Test(dataProvider="configProvider") public void testOutOfBandMessages(Class<? extends Protocol> unicast_class) throws Exception { setUp(unicast_class); sendMessages(true); } /** * Check that 4 is received before 3 */ private void sendMessages(boolean oob) throws Exception { DISCARD_PAYLOAD discard=new DISCARD_PAYLOAD(); MyReceiver receiver=new MyReceiver(); b.setReceiver(receiver); // the first channel will discard the unicast messages with seqno #3 two times, the let them pass down ProtocolStack stack=a.getProtocolStack(); Protocol neighbor=stack.findProtocol(Util.getUnicastProtocols()); System.out.println("Found unicast protocol " + neighbor.getClass().getSimpleName()); stack.insertProtocolInStack(discard,neighbor,ProtocolStack.Position.BELOW); a.connect("UNICAST_OOB_Test"); b.connect("UNICAST_OOB_Test"); Util.waitUntilAllChannelsHaveSameView(10000, 1000, a, b); Address dest=b.getAddress(); for(int i=1; i <=5; i++) { Message msg=new Message(dest,(long)i); if(i == 4 && oob) msg.setFlag(Message.Flag.OOB); System.out.println("-- sending message #" + i); a.send(msg); Util.sleep(100); } // wait until retransmission of seqno #3 happens, so that 4 and 5 are received as well long target_time=System.currentTimeMillis() + 30000; do { if(receiver.size() >= 5) break; Util.sleep(500); } while(target_time > System.currentTimeMillis()); List<Long> seqnos=receiver.getSeqnos(); System.out.println("sequence numbers: " + seqnos); assert seqnos.size() == 5; if(!oob) { for(int i=0; i < 5; i++) assert seqnos.get(i) == i+1 : " seqno is " + seqnos.get(i) + ", but expected " + i+1; } else { // 4 needs to be received before 3. Reason: 4 is sent OOB, does *not* wait until 3 has been retransmitted ! int index_3=-1, index_4=-1; for(int i=0; i < 5; i++) { if(seqnos.get(i) == 3) index_3=i; if(seqnos.get(i) == 4) index_4=i; } assert index_4 < index_3 : "4 must come before 3 in list " + seqnos; } } protected JChannel createChannel(Class<? extends Protocol> unicast_class, String name) throws Exception { Protocol unicast=unicast_class.newInstance().setValue("xmit_interval",500); return new JChannel( new SHARED_LOOPBACK(), new SHARED_LOOPBACK_PING(), new NAKACK2(), new DISCARD(), unicast, new GMS()) .name(name); } public static class MyReceiver extends ReceiverAdapter { /** List<Long> of unicast sequence numbers */ List<Long> seqnos=Collections.synchronizedList(new LinkedList<>()); public MyReceiver() { } public List<Long> getSeqnos() { return seqnos; } public void receive(Message msg) { if(msg != null) { Long num=msg.getObject(); System.out.println(">> received " + num); seqnos.add(num); } } public int size() {return seqnos.size();} } }