package org.jgroups.tests;
import org.jgroups.*;
import org.jgroups.util.Util;
import org.testng.annotations.Test;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* Tests various methods in JChannel
* @author Bela Ban
*/
@Test(groups=Global.STACK_DEPENDENT)
public class ChannelTest extends ChannelTestBase {
public void testBasicOperations() throws Exception {
JChannel a = createChannel(true,1).name("A");
JChannel b=null;
try {
a.connect("testBasicOperations");
assert a.isOpen();
assert a.isConnected();
assert a.getAddress() != null;
assert a.getView() != null;
assert a.getView().getMembers().contains(a.getAddress());
a.connect("testBasicOperations");
a.disconnect();
assert a.isConnected() == false;
assert a.isOpen();
assert a.getAddress() == null;
assert a.getView() == null;
assert a.getClusterName() == null;
a.connect("testBasicOperations");
a.close();
try {
a.connect("testBasicOperations");
assert false : "Should have generated exception, and it has not";
}
catch (Exception e) {
assert e instanceof IllegalStateException;
}
assert a.isConnected() == false;
assert a.isOpen() == false;
assert a.getAddress() == null;
assert a.getView() == null;
assert a.getClusterName() == null;
a = createChannel(true,2);
a.connect("testBasicOperations");
b = createChannel(a);
b.connect("testBasicOperations");
Util.sleep(1000);
assert a.isOpen();
assert a.isConnected();
assert a.getAddress() != null;
assert a.getView() != null;
assert a.getView().getMembers().contains(a.getAddress());
assert a.getView().getMembers().contains(b.getAddress());
assert b.isOpen();
assert b.isConnected();
assert b.getAddress() != null;
assert b.getView() != null;
assert b.getView().getMembers().contains(b.getAddress());
assert b.getView().getMembers().contains(a.getAddress());
b.close();
Util.sleep(1000);
assert b.isOpen() == false;
assert b.isConnected() == false;
assert b.getAddress() == null;
assert b.getView() == null;
assert a.isOpen();
assert a.isConnected();
assert a.getAddress() != null;
assert a.getView() != null;
assert a.getView().getMembers().contains(a.getAddress());
assert a.getView().getMembers().contains(b.getAddress()) == false;
}
finally {
Util.close(a,b);
}
}
public void testSendOnDisconnectedChannel() throws Exception {
JChannel ch=createChannel();
try {
ch.send(null, "hello world");
assert false : "sending on a disconnected channel should have failed";
}
catch(IllegalStateException ex) {
System.out.println("received \"" + ex + "\" as expected: sending on a disconnected channel is not allowed");
}
}
public void testSendOnClosedChannel() throws Exception {
JChannel ch=createChannel();
try {
Util.close(ch);
ch.send(null, "hello world");
assert false : "sending on a closed channel should have failed";
}
catch(IllegalStateException ex) {
System.out.println("received \"" + ex + "\" as expected: sending on a closed channel is not allowed");
}
}
public void testViewChange() throws Exception {
JChannel ch1 = createChannel(true,2);
ViewChecker checker=new ViewChecker(ch1);
ch1.setReceiver(checker);
ch1.connect("testViewChange");
JChannel ch2=createChannel(ch1);
try {
ch2.connect("testViewChange");
assertTrue(checker.getReason(), checker.isSuccess());
ch2.close();
assertTrue(checker.getReason(), checker.isSuccess());
}
finally {
Util.close(ch1,ch2);
}
}
public void testViewChange2() throws Exception {
JChannel a=createChannel(true, 2).name("A");
JChannel b=createChannel(a).name("B");
a.connect("testViewChange2");
b.connect("testViewChange2");
Util.waitUntilAllChannelsHaveSameView(10000, 1000, a,b);
List<Address> expectedMembers = Arrays.asList(a.getAddress(), b.getAddress());
List<Address> mbrs=a.getView().getMembers();
assert expectedMembers.equals(mbrs);
assert mbrs.equals(expectedMembers);
}
public void testIsConnectedOnFirstViewChange() throws Exception {
JChannel ch1 = createChannel(true,2);
JChannel ch2=createChannel(ch1);
ConnectedChecker tmp=new ConnectedChecker(ch2);
ch2.setReceiver(tmp);
try {
ch1.connect("testIsConnectedOnFirstViewChange");
ch2.connect("testIsConnectedOnFirstViewChange");
assert tmp.isConnected();
}
finally {
Util.close(ch1,ch2);
}
}
public void testNoViewIsReceivedAfterDisconnect() throws Exception {
JChannel ch1 = createChannel(true,2);
JChannel ch2=createChannel(ch1);
MyViewChecker ra = new MyViewChecker(ch2);
ch2.setReceiver(ra);
try {
ch1.connect("testNoViewIsReceivedAfterDisconnect");
ch2.connect("testNoViewIsReceivedAfterDisconnect");
Util.sleep(500);
ch2.disconnect();
Util.sleep(1000);
assert !ra.receivedViewWhenDisconnected : "Received view where not member";
}
finally {
Util.close(ch1,ch2);
}
}
public void testNoViewIsReceivedAfterClose() throws Exception {
JChannel ch1 = createChannel(true,2);
JChannel ch2=createChannel(ch1);
MyViewChecker ra = new MyViewChecker(ch2);
ch2.setReceiver(ra);
try {
ch1.connect("testNoViewIsReceivedAfterClose");
ch2.connect("testNoViewIsReceivedAfterClose");
Util.sleep(200);
ch2.close();
Util.sleep(1000);
assert !ra.receivedViewWhenDisconnected : "Received view where not member";
}
finally {
Util.close(ch1,ch2);
}
}
@Test(expectedExceptions={NullPointerException.class})
public void testNullMessage() throws Exception {
JChannel ch1 = createChannel(true,2);
try{
ch1.connect("testNullMessage");
ch1.send(null);
}
finally{
Util.close(ch1);
}
}
public void testOrdering() throws Exception {
final int NUM=100;
JChannel ch=createChannel(true, 2);
MyReceiver receiver=new MyReceiver(NUM);
ch.setReceiver(receiver);
try {
ch.connect("testOrdering");
for(int i=1;i <= NUM;i++) {
ch.send(new Message(null, i));
}
receiver.waitForCompletion();
List<Integer> nums=receiver.getNums();
checkMonotonicallyIncreasingNumbers(nums);
}
finally {
Util.close(ch);
}
}
private static void checkMonotonicallyIncreasingNumbers(List<Integer> nums) {
int current=-1;
for(int num: nums) {
if(current < 0) {
current=num;
}
else {
assert ++current == num : "list is " + nums;
}
}
}
private static class MyReceiver extends ReceiverAdapter {
final List<Integer> nums=new LinkedList<>();
final int expected;
public MyReceiver(int expected) {
this.expected=expected;
}
public List<Integer> getNums() {
return nums;
}
public void waitForCompletion() throws InterruptedException {
synchronized(nums) {
while(nums.size() < expected) {
nums.wait();
}
}
}
public void receive(Message msg) {
Integer num=(Integer)msg.getObject();
synchronized(nums) {
nums.add(num);
if(nums.size() >= expected) {
nums.notifyAll();
}
}
}
}
private static class ConnectedChecker extends ReceiverAdapter {
boolean connected=false;
public ConnectedChecker(JChannel channel) {
this.channel=channel;
}
final JChannel channel;
public boolean isConnected() {
return connected;
}
public void viewAccepted(View new_view) {
connected=channel.isConnected();
}
}
private static class ViewChecker extends ReceiverAdapter {
final JChannel channel;
boolean success=true;
String reason="";
public ViewChecker(JChannel channel) {
this.channel=channel;
}
public String getReason() {
return reason;
}
public boolean isSuccess() {
return success;
}
public void viewAccepted(View new_view) {
View view=channel.getView();
String str="viewAccepted(): channel's view=" + view + "\nreceived view=" + new_view;
// System.out.println(str);
if(view!= null && !view.equals(new_view)) {
success=false;
reason+=str + "\n";
}
}
}
private static class MyViewChecker extends ReceiverAdapter {
private boolean receivedViewWhenDisconnected;
private final JChannel ch;
public MyViewChecker(JChannel ch) {
this.ch=ch;
}
public void viewAccepted(View new_view) {
receivedViewWhenDisconnected = !new_view.containsMember(ch.getAddress());
}
}
}