package org.jgroups.blocks;
import org.jgroups.Address;
import org.jgroups.Global;
import org.jgroups.stack.IpAddress;
import org.jgroups.util.DefaultThreadFactory;
import org.jgroups.util.ResourceManager;
import org.jgroups.util.StackType;
import org.jgroups.util.Util;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* Tests ConnectionMap
* @author Bela Ban
*/
@Test(groups=Global.FUNCTIONAL,singleThreaded=true)
public class ConnectionMapTest {
private TCPConnectionMap ct1, ct2;
static final InetAddress loopback_addr;
static {
try {
StackType type=Util.getIpStackType();
String tmp=type == StackType.IPv6? "::1" : "127.0.0.1";
loopback_addr=InetAddress.getByName(tmp);
}
catch(UnknownHostException e) {
throw new RuntimeException("failed initializing loopback_addr", e);
}
}
static byte[] data={'b', 'e', 'l', 'a'};
protected int PORT1, PORT2;
protected Address addr1, addr2;
@BeforeMethod
protected void init() throws Exception {
List<Short> ports=ResourceManager.getNextTcpPorts(loopback_addr, 2);
PORT1=ports.get(0);
PORT2=ports.get(1);
addr1=new IpAddress(loopback_addr, PORT1);
addr2=new IpAddress(loopback_addr, PORT2);
}
@AfterMethod
protected void tearDown() throws Exception {
if(ct2 != null) {
ct2.stop();
ct2=null;
}
if(ct1 != null) {
ct1.stop();
ct1=null;
}
}
/**
* A connects to B and B connects to A at the same time. This test makes sure we only have <em>one</em> connection,
* not two, e.g. a spurious connection. Tests http://jira.jboss.com/jira/browse/JGRP-549.<p/>
* Turned concurrent test into a simple sequential test. We're going to replace this code with NIO2 soon anyway...
*/
public void testReuseOfConnection() throws Exception {
TCPConnectionMap.Receiver dummy=new TCPConnectionMap.Receiver() {
public void receive(Address sender, byte[] data, int offset, int length) {}
};
ct1=new TCPConnectionMap("ConnectionMapTest1",
new DefaultThreadFactory("ConnectionMapTest", true),
null, dummy, loopback_addr, null, 0, PORT1, PORT1);
ct1.start();
ct2=new TCPConnectionMap("ConnectionMapTest2",
new DefaultThreadFactory("ConnectionMapTest", true),
null, dummy, loopback_addr, null, 0, PORT2, PORT2);
ct2.start();
int num_conns;
num_conns=ct1.getNumConnections();
assert num_conns == 0;
num_conns=ct2.getNumConnections();
assert num_conns == 0;
ct1.send(addr2, data, 0, data.length);
ct2.send(addr1, data, 0, data.length);
String msg="ct1: " + ct1 + "\nct2: " + ct2;
System.out.println(msg);
num_conns=ct1.getNumConnections();
assert num_conns == 1 : "num_conns for ct1 is " + num_conns + ", " + msg;
num_conns=ct2.getNumConnections();
assert num_conns == 1 : "num_conns for ct2 is " + num_conns + ", " + msg;
assert ct1.connectionEstablishedTo(addr2) : "valid connection to peer";
assert ct2.connectionEstablishedTo(addr1) : "valid connection to peer";
}
public static void testBlockingQueue() {
final BlockingQueue queue=new LinkedBlockingQueue();
Thread taker=new Thread() {
public void run() {
try {
System.out.println("taking an element from the queue");
queue.take();
System.out.println("clear");
}
catch(InterruptedException e) {
}
}
};
taker.start();
Util.sleep(500);
queue.clear(); // does this release the taker thread ?
Util.interruptAndWaitToDie(taker);
assert !(taker.isAlive()) : "taker: " + taker;
}
public void testStopConnectionMapNoSendQueues() throws Exception {
ct1=new TCPConnectionMap("ConnectionMapTest1",
new DefaultThreadFactory("ConnectionMapTest", true),
new DummyReceiver(), loopback_addr, null, 0, PORT1, PORT1, 60000, 120000);
ct1.setUseSendQueues(false);
ct1.start();
ct2=new TCPConnectionMap("ConnectionMapTest2",
new DefaultThreadFactory("ConnectionMapTest", true),
new DummyReceiver(), loopback_addr, null, 0, PORT2, PORT2, 60000, 120000);
ct2.setUseSendQueues(false);
ct2.start();
_testStop(ct1, ct2);
}
public void testStopConnectionMapWithSendQueues() throws Exception {
ct1=new TCPConnectionMap("ConnectionMapTest1",
new DefaultThreadFactory("ConnectionMapTest", true),
new DummyReceiver(), loopback_addr, null, 0, PORT1, PORT1, 60000, 120000);
ct1.start();
ct2=new TCPConnectionMap("ConnectionMapTest2",
new DefaultThreadFactory("ConnectionMapTest", true),
new DummyReceiver(), loopback_addr, null, 0, PORT2, PORT2, 60000, 120000);
ct2.start();
_testStop(ct1, ct2);
}
/* public void testStopConnectionMapNIONoSendQueues() throws Exception {
ct1=new ConnectionTableNIO(new DummyReceiver(), loopback_addr, null, PORT1, PORT1, 60000, 120000, false);
ct1.setUseSendQueues(false);
ct2=new ConnectionTableNIO(new DummyReceiver(), loopback_addr, null, PORT2, PORT2, 60000, 120000, false);
ct2.setUseSendQueues(false);
ct1.start();
ct2.start();
_testStop(ct1, ct2);
}
public void testStopConnectionMapNIOWithSendQueues() throws Exception {
ct1=new ConnectionTableNIO(new DummyReceiver(), loopback_addr, null, PORT1, PORT1, 60000, 120000, false);
ct2=new ConnectionTableNIO(new DummyReceiver(), loopback_addr, null, PORT2, PORT2, 60000, 120000, false);
ct1.start();
ct2.start();
_testStop(ct1, ct2);
}*/
private void _testStop(TCPConnectionMap table1, TCPConnectionMap table2) throws Exception {
table1.send(addr1, data, 0, data.length); // send to self
assert table1.getNumConnections() == 0;
table1.send(addr2, data, 0, data.length); // send to other
table2.send(addr2, data, 0, data.length); // send to self
table2.send(addr1, data, 0, data.length); // send to other
System.out.println("table1:\n" + table1 + "\ntable2:\n" + table2);
int num_conns_table1=table1.getNumConnections(), num_conns_table2=table2.getNumConnections();
assert num_conns_table1 == 1 : "table1 should have 1 connection, but has " + num_conns_table1 + ": " + table1;
assert num_conns_table2 == 1 : "table2 should have 1 connection, but has " + num_conns_table2 + ": " + table2;
table2.stop();
table1.stop();
assert table1.getNumConnections() == 0 : "table1 should have 0 connections: " + table1;
assert table2.getNumConnections() == 0 : "table2 should have 0 connections: " + table2;
}
static class DummyReceiver implements TCPConnectionMap.Receiver {
public void receive(Address sender, byte[] data, int offset, int length) {
System.out.println("-- received " + length + " bytes from " + sender);
}
}
}