package net.jxse.systemtests.colocated;
import static org.junit.Assert.*;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import net.jxta.document.AdvertisementFactory;
import net.jxta.document.MimeMediaType;
import net.jxta.endpoint.ByteArrayMessageElement;
import net.jxta.endpoint.Message;
import net.jxta.endpoint.StringMessageElement;
import net.jxta.id.IDFactory;
import net.jxta.pipe.PipeID;
import net.jxta.pipe.PipeMsgEvent;
import net.jxta.pipe.PipeMsgListener;
import net.jxta.pipe.PipeService;
import net.jxta.platform.NetworkManager;
import net.jxta.protocol.PipeAdvertisement;
import net.jxta.util.JxtaBiDiPipe;
import net.jxta.util.JxtaServerPipe;
import net.jxta.util.ServerPipeAcceptListener;
public class SystemTestUtils {
private static final String TEST_NAMESPACE = "SystemTest";
private static final String STRING_PAYLOAD_ELEMENT = "strPayload";
private static final String EXTRA_BYTES_ELEMENT = "extraBytes";
public static JxtaServerPipe createServerPipe(NetworkManager manager) throws IOException {
return createServerPipe(manager, null);
}
public static JxtaServerPipe createServerPipe(NetworkManager manager, ServerPipeAcceptListener listener) throws IOException {
PipeID pipeId = IDFactory.newPipeID(manager.getNetPeerGroup().getPeerGroupID());
PipeAdvertisement pipeAd = createUnicastPipeAd(pipeId);
if(listener == null) {
return new JxtaServerPipe(manager.getNetPeerGroup(), pipeAd);
} else {
return new JxtaServerPipe(manager.getNetPeerGroup(), pipeAd, listener);
}
}
public static PipeAdvertisement createUnicastPipeAd(PipeID pipeID) {
PipeAdvertisement advertisement = (PipeAdvertisement)
AdvertisementFactory.newAdvertisement(PipeAdvertisement.getAdvertisementType());
advertisement.setPipeID(pipeID);
advertisement.setType(PipeService.UnicastType);
return advertisement;
}
public static Message createMessage(String payload, int numExtraBytes) {
Message msg = new Message();
msg.addMessageElement(TEST_NAMESPACE, new StringMessageElement(STRING_PAYLOAD_ELEMENT, payload, null));
if(numExtraBytes > 0) {
ByteArrayMessageElement extra = new ByteArrayMessageElement(EXTRA_BYTES_ELEMENT, null, createRandomBytes(numExtraBytes), null);
msg.addMessageElement(TEST_NAMESPACE, extra);
}
return msg;
}
private static byte[] createRandomBytes(int numExtraBytes) {
Random r = new Random();
byte[] extraBytes = new byte[numExtraBytes];
r.nextBytes(extraBytes);
return extraBytes;
}
public static Message createMessage(String payload) {
return createMessage(payload, 0);
}
public static String getMessageString(Message msg) {
return msg.getMessageElement(TEST_NAMESPACE, STRING_PAYLOAD_ELEMENT).toString();
}
public static void testPeerCommunication(NetworkManager aliceManager, NetworkManager bobManager) throws IOException, InterruptedException {
final CountDownLatch pipeEstablished = new CountDownLatch(1);
final CountDownLatch aliceRequestReceived = new CountDownLatch(1);
final CountDownLatch bobResponseReceived = new CountDownLatch(1);
final AtomicReference<JxtaBiDiPipe> aliceAcceptedPipe = new AtomicReference<JxtaBiDiPipe>();
ServerPipeAcceptListener listener = new ServerPipeAcceptListener() {
public void pipeAccepted(JxtaBiDiPipe pipe) {
aliceAcceptedPipe.set(pipe);
pipeEstablished.countDown();
}
public void serverPipeClosed() {}
};
JxtaServerPipe aliceServerPipe = createServerPipe(aliceManager, listener);
PipeMsgListener aliceListener = new PipeMsgListener() {
public void pipeMsgEvent(PipeMsgEvent event) {
aliceRequestReceived.countDown();
}
};
PipeMsgListener bobListener = new PipeMsgListener() {
public void pipeMsgEvent(PipeMsgEvent event) {
bobResponseReceived.countDown();
}
};
//TODO We have an issue on initialisation which means need to wait for services to be running before executing test. Only effects relay tests.
Thread.sleep(5000);
JxtaBiDiPipe bobPipe = connectNonBlocking(bobManager, aliceServerPipe.getPipeAdv(), bobListener);
assertTrue("Failed to establish pipe", pipeEstablished.await(10, TimeUnit.SECONDS));
aliceAcceptedPipe.get().setMessageListener(aliceListener);
bobPipe.sendMessage(SystemTestUtils.createMessage("hello alice"));
assertTrue("Failed to send message from bob to alice", aliceRequestReceived.await(5, TimeUnit.SECONDS));
aliceAcceptedPipe.get().sendMessage(SystemTestUtils.createMessage("hello bob"));
assertTrue("Failed to send messages from alice to bob", bobResponseReceived.await(5, TimeUnit.SECONDS));
}
private static JxtaBiDiPipe connectNonBlocking(NetworkManager clientManager,
PipeAdvertisement pipeAdv,
PipeMsgListener clientListener) throws IOException
{
final JxtaBiDiPipe biDiPipe = new JxtaBiDiPipe();
biDiPipe.setWindowSize(20);
biDiPipe.connect(clientManager.getNetPeerGroup(),null, pipeAdv, 5000, clientListener, true);
return biDiPipe;
}
private static JxtaBiDiPipe connectWithRetry(NetworkManager clientManager,
PipeAdvertisement pipeAdv,
PipeMsgListener clientListener) throws IOException {
int tryCount = 0;
while(true) {
try {
return new JxtaBiDiPipe(clientManager.getNetPeerGroup(), pipeAdv, 5000, clientListener);
} catch (SocketTimeoutException e) {
tryCount++;
if(tryCount >= 3) {
throw e;
}
}
}
}
public static PipeEnds createBiDiPipe(NetworkManager acceptor, NetworkManager requestor, final PipeMsgListener acceptorListener, final PipeMsgListener requestorListener, long timeout, TimeUnit timeoutUnit) throws IOException, InterruptedException {
final CountDownLatch acceptLatch = new CountDownLatch(1);
final AtomicReference<JxtaBiDiPipe> acceptedPipeRef = new AtomicReference<JxtaBiDiPipe>();
JxtaServerPipe serverPipe = createServerPipe(acceptor, new ServerPipeAcceptListener() {
public void serverPipeClosed() {}
public void pipeAccepted(JxtaBiDiPipe pipe) {
pipe.setMessageListener(acceptorListener);
acceptedPipeRef.set(pipe);
acceptLatch.countDown();
}
});
Thread.sleep(5000);
JxtaBiDiPipe clientPipeEnd = connectNonBlocking(requestor, serverPipe.getPipeAdv(), requestorListener);
boolean success = acceptLatch.await(timeout, timeoutUnit);
serverPipe.close();
if(success) {
return new PipeEnds(acceptedPipeRef.get(), clientPipeEnd);
} else {
fail("Failed to establish connection between peers");
return null;
}
}
public static void checkMessagesEqual(Message sentMessage, Message receivedMessage) {
assertTrue(receivedMessage.getMessageElement(TEST_NAMESPACE, STRING_PAYLOAD_ELEMENT) != null);
String sentString = sentMessage.getMessageElement(TEST_NAMESPACE, STRING_PAYLOAD_ELEMENT).toString();
String receivedString = receivedMessage.getMessageElement(TEST_NAMESPACE, STRING_PAYLOAD_ELEMENT).toString();
assertEquals(sentString, receivedString);
if(sentMessage.getMessageElement(TEST_NAMESPACE, EXTRA_BYTES_ELEMENT) != null) {
assertTrue(receivedMessage.getMessageElement(TEST_NAMESPACE, EXTRA_BYTES_ELEMENT) != null);
byte[] sentBytes = ((ByteArrayMessageElement)sentMessage.getMessageElement(TEST_NAMESPACE, EXTRA_BYTES_ELEMENT)).getBytes();
byte[] receivedBytes= ((ByteArrayMessageElement)receivedMessage.getMessageElement(TEST_NAMESPACE, EXTRA_BYTES_ELEMENT)).getBytes();
assertArrayEquals(sentBytes, receivedBytes);
}
}
}