package net.jxse.systemtests.colocated.pipes;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import net.jxse.systemtests.colocated.SystemTestUtils;
import net.jxse.systemtests.colocated.configs.PeerConfigurator;
import net.jxta.pipe.PipeMsgEvent;
import net.jxta.pipe.PipeMsgListener;
import net.jxta.platform.NetworkManager;
import net.jxta.util.JxtaBiDiPipe;
import net.jxta.util.JxtaServerPipe;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class BlockingPipeAcceptTest {
@Rule
public TemporaryFolder tempStorage = new TemporaryFolder();
private NetworkManager aliceManager;
private NetworkManager bobManager;
private NetworkManager relayManager;
@Before
public void initPeers() throws Exception {
String aliceInstanceName = "alice";
String bobInstanceName = "bob";
String relayInstanceName = "relay";
relayManager = PeerConfigurator.createTcpRdvRelayPeer(relayInstanceName, 50000, tempStorage);
aliceManager = PeerConfigurator.createTcpClientPeer(aliceInstanceName, relayManager, tempStorage);
bobManager = PeerConfigurator.createTcpClientPeer(bobInstanceName, relayManager, tempStorage);
aliceManager.getConfigurator().setPrincipal(aliceInstanceName);
bobManager.getConfigurator().setPrincipal(bobInstanceName);
relayManager.getConfigurator().setPrincipal(relayInstanceName);
relayManager.startNetwork();
aliceManager.startNetwork();
bobManager.startNetwork();
// XXX: frustratingly, this test does not pass reliably unless time is given to
// the peers to connect to the Rdv/Relay peer and settle down. Otherwise, the
// pipe accept request is never received by alice unless bob explicitly retries.
Thread.sleep(5000);
}
@After
public void killPeers() throws Exception {
aliceManager.stopNetwork();
bobManager.stopNetwork();
relayManager.stopNetwork();
}
@Test(timeout=60000)
public void testBlockingAccept() throws Exception {
// these latches are used to control the concurrency that is necessary to test the blocking
// API, and waiting for asynchronous delivery of messages.
final CountDownLatch connectionAcceptLatch = new CountDownLatch(1);
final CountDownLatch aliceReceivedRequest = new CountDownLatch(1);
final CountDownLatch bobReceivedResponse = new CountDownLatch(1);
AtomicReference<JxtaBiDiPipe> acceptedPipe = new AtomicReference<JxtaBiDiPipe>(null);
// create the server pipe, and have alice wait for an incoming connection (in another thread)
JxtaServerPipe aliceServerPipe = SystemTestUtils.createServerPipe(aliceManager);
aliceServerPipe.setPipeTimeout(0);
aliceWait(aliceServerPipe, connectionAcceptLatch, acceptedPipe);
// have bob attempt to connect to alice's server pipe
JxtaBiDiPipe bobClientPipe = new JxtaBiDiPipe(bobManager.getNetPeerGroup(), aliceServerPipe.getPipeAdv(), 2000, new PipeMsgListener() {
public void pipeMsgEvent(PipeMsgEvent event) {
bobReceivedResponse.countDown();
}
});
assertTrue("Timeout while waiting for pipe accept", connectionAcceptLatch.await(15, TimeUnit.SECONDS));
// configure alice's end of the newly created BidiPipe
final JxtaBiDiPipe alicePipeEnd = acceptedPipe.get();
alicePipeEnd.setMessageListener(new PipeMsgListener() {
public void pipeMsgEvent(PipeMsgEvent event) {
aliceReceivedRequest.countDown();
}
});
// send the messages in each direction to test the pipe is functioning
bobClientPipe.sendMessage(SystemTestUtils.createMessage("hello alice"));
assertTrue("Timeout while waiting for bob -> alice message", aliceReceivedRequest.await(15, TimeUnit.SECONDS));
alicePipeEnd.sendMessage(SystemTestUtils.createMessage("hello bob"));
assertTrue("Timeout while waiting for alice -> bob message", bobReceivedResponse.await(15, TimeUnit.SECONDS));
}
private void aliceWait(final JxtaServerPipe serverPipe, final CountDownLatch connectionAcceptLatch, final AtomicReference<JxtaBiDiPipe> accepted) {
new Thread(new Runnable() {
public void run() {
try {
accepted.set(serverPipe.accept());
connectionAcceptLatch.countDown();
} catch (IOException e) {
System.err.println("Failed to accept");
e.printStackTrace();
}
}
}).start();
}
}