package org.jgroups.blocks; import org.jgroups.*; import org.jgroups.tests.ChannelTestBase; import org.jgroups.util.RspList; import org.jgroups.util.Util; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeoutException; /** * @author Bela Ban */ @Test(groups=Global.STACK_DEPENDENT,singleThreaded=true) public class RpcDispatcherUnitTest extends ChannelTestBase { private RpcDispatcher d1, d2, d3; private JChannel c1, c2, c3; private ServerObject o1, o2, o3; private Address a1, a2, a3; private List<Address> members; @BeforeClass protected void setUp() throws Exception { o1=new ServerObject(); o2=new ServerObject(); o3=new ServerObject(); c1=createChannel(true, 3).setName("A"); final String GROUP="RpcDispatcherUnitTest"; d1=new RpcDispatcher(c1, o1); c1.connect(GROUP); c2=createChannel(c1).setName("B"); d2=new RpcDispatcher(c2, o2); c2.connect(GROUP); c3=createChannel(c1).setName("C"); d3=new RpcDispatcher(c3, o3); c3.connect(GROUP); Util.waitUntilAllChannelsHaveSameView(10000, 1000, c1, c2, c3); a1=c1.getAddress(); a2=c2.getAddress(); a3=c3.getAddress(); members=Arrays.asList(a1, a2, a3); } @BeforeMethod protected void reset() { o1.reset(); o2.reset(); o3.reset(); } @AfterClass protected void tearDown() throws Exception { Util.close(d3,d2,d1,c3, c2, c1); } public void testInvocationOnEntireGroup() throws Exception { RspList rsps=d1.callRemoteMethods(null, "foo", null, null, RequestOptions.SYNC()); System.out.println("rsps:\n" + rsps); assert rsps.size() == 3; assert o1.wasCalled() && o2.wasCalled() && o3.wasCalled(); } public void testInvocationOnEntireGroupWithTargetList() throws Exception { RspList rsps=d1.callRemoteMethods(members, "foo", null, null, RequestOptions.SYNC()); System.out.println("rsps:\n" + rsps); assert rsps.size() == 3; assert o1.wasCalled() && o2.wasCalled() && o3.wasCalled(); } /** Invoke a method on all but myself */ public void testInvocationWithExclusionOfSelf() throws Exception { RequestOptions options=new RequestOptions(ResponseMode.GET_ALL, 5000).exclusionList(a1); RspList rsps=d1.callRemoteMethods(null, "foo", null, null, options); Util.sleep(500); System.out.println("rsps:\n" + rsps); assert rsps.size() == 2; assert rsps.containsKey(a2) && rsps.containsKey(a3); assert !o1.wasCalled() && o2.wasCalled() && o3.wasCalled(); } public void testInvocationWithExclusionOfSelfUsingDontLoopback() throws Exception { RequestOptions options=new RequestOptions(ResponseMode.GET_ALL, 5000).transientFlags(Message.TransientFlag.DONT_LOOPBACK); RspList rsps=d1.callRemoteMethods(null, "foo", null, null, options); Util.sleep(500); System.out.println("rsps:\n" + rsps); assert rsps.size() == 2; assert rsps.containsKey(a2) && rsps.containsKey(a3); assert !o1.wasCalled() && o2.wasCalled() && o3.wasCalled(); } public void testInvocationWithExclusionOfSelfUsingDontLoopbackAnycasting() throws Exception { RequestOptions options=new RequestOptions(ResponseMode.GET_ALL, 5000).transientFlags(Message.TransientFlag.DONT_LOOPBACK); RspList<Object> rsps=d1.callRemoteMethods(null, "foo", null, null, options.anycasting(true)); Util.sleep(500); System.out.println("rsps:\n" + rsps); assert rsps.size() == 2; assert rsps.containsKey(a2) && rsps.containsKey(a3); assert !o1.wasCalled() && o2.wasCalled() && o3.wasCalled(); } /** Invoke a method on all but myself and use DONT_LOOPBACK */ public void testInvocationWithExclusionOfSelfWithDontLoopback() throws Exception { RequestOptions options=new RequestOptions(ResponseMode.GET_ALL, 5000).transientFlags(Message.TransientFlag.DONT_LOOPBACK); RspList rsps=d1.callRemoteMethods(null, "foo", null, null, options); Util.sleep(500); System.out.println("rsps:\n" + rsps); assert rsps.size() == 2; assert rsps.containsKey(a2) && rsps.containsKey(a3); assert o1.getNumCalls() == 0 && o2.getNumCalls() == 1 && o3.getNumCalls() == 1; rsps=d1.callRemoteMethods(Arrays.asList(a1,a2,a3), "foo", null, null, options); Util.sleep(500); System.out.println("rsps:\n" + rsps); assert rsps.size() == 2; assert rsps.containsKey(a2) && rsps.containsKey(a3); assert o1.getNumCalls() == 0 && o2.getNumCalls() == 2 && o3.getNumCalls() == 2; options.clearTransientFlags(Message.TransientFlag.DONT_LOOPBACK); rsps=d1.callRemoteMethods(Arrays.asList(a1,a2,a3), "foo", null, null, options); Util.sleep(500); System.out.println("rsps:\n" + rsps); assert rsps.size() == 3; assert rsps.containsKey(a1) && rsps.containsKey(a2) && rsps.containsKey(a3); assert o1.getNumCalls() == 1 && o2.getNumCalls() == 3 && o3.getNumCalls() == 3; } public void testInvocationWithExclusionOfSelfWithDontLoopbackUnicast() throws Exception { RequestOptions options=new RequestOptions(ResponseMode.GET_ALL, 500).transientFlags(Message.TransientFlag.DONT_LOOPBACK); try { d1.callRemoteMethod(a1,"foo",null,null,options); } catch(TimeoutException ex) { System.out.println("sending unicast to self with DONT_LOOPBACK threw exception as expected: " + ex); } } public void testInvocationWithExclusionOfTwo() throws Exception { RequestOptions options=new RequestOptions(ResponseMode.GET_ALL, 5000).exclusionList(a2, a3); RspList rsps=d1.callRemoteMethods(null, "foo", null, null, options); Util.sleep(500); System.out.println("rsps:\n" + rsps); assert rsps.size() == 1; assert rsps.containsKey(a1); assert o1.wasCalled() && !o2.wasCalled() && !o3.wasCalled(); } public void testInvocationOnEmptyTargetSet() throws Exception { RequestOptions options=new RequestOptions(ResponseMode.GET_ALL, 5000).exclusionList(a1, a2, a3); RspList rsps=d1.callRemoteMethods(null, "foo", null, null, options); assert rsps != null && rsps.isEmpty(); assert !o1.wasCalled() && !o2.wasCalled() && !o3.wasCalled(); } private static class ServerObject { boolean called=false; int num_calls=0; public boolean wasCalled() { return called; } public int getNumCalls() {return num_calls;} public void reset() { called=false; num_calls=0; } public boolean foo() { num_calls++; return called=true; } } }